summaryrefslogtreecommitdiff
path: root/chromium/storage
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2022-05-12 15:59:20 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2022-05-25 06:57:22 +0000
commitf7eaed5286974984ba5f9e3189d8f49d03e99f81 (patch)
treecaed19b2af2024f35449fb0b781d0a25e09d4f8f /chromium/storage
parent9729c4479fe23554eae6e6dd1f30ff488f470c84 (diff)
downloadqtwebengine-chromium-f7eaed5286974984ba5f9e3189d8f49d03e99f81.tar.gz
BASELINE: Update Chromium to 100.0.4896.167
Change-Id: I98cbeb5d7543d966ffe04d8cefded0c493a11333 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/storage')
-rw-r--r--chromium/storage/BUILD.gn2
-rw-r--r--chromium/storage/DEPS1
-rw-r--r--chromium/storage/browser/BUILD.gn5
-rw-r--r--chromium/storage/browser/blob/blob_builder_from_stream.cc2
-rw-r--r--chromium/storage/browser/blob/blob_memory_controller.cc6
-rw-r--r--chromium/storage/browser/blob/blob_registry_impl_unittest.cc6
-rw-r--r--chromium/storage/browser/blob/blob_storage_constants.h2
-rw-r--r--chromium/storage/browser/blob/blob_url_loader.cc13
-rw-r--r--chromium/storage/browser/blob/blob_url_registry.cc25
-rw-r--r--chromium/storage/browser/blob/blob_url_registry.h9
-rw-r--r--chromium/storage/browser/blob/blob_url_registry_unittest.cc20
-rw-r--r--chromium/storage/browser/blob/blob_url_store_impl.cc36
-rw-r--r--chromium/storage/browser/blob/blob_url_store_impl.h3
-rw-r--r--chromium/storage/browser/blob/blob_url_store_impl_unittest.cc5
-rw-r--r--chromium/storage/browser/blob/scoped_file.cc2
-rw-r--r--chromium/storage/browser/database/database_quota_client.cc59
-rw-r--r--chromium/storage/browser/database/database_quota_client.h27
-rw-r--r--chromium/storage/browser/database/database_quota_client_unittest.cc172
-rw-r--r--chromium/storage/browser/database/database_tracker.cc11
-rw-r--r--chromium/storage/browser/database/database_tracker_unittest.cc2
-rw-r--r--chromium/storage/browser/database/vfs_backend.cc8
-rw-r--r--chromium/storage/browser/file_system/dragged_file_util_unittest.cc6
-rw-r--r--chromium/storage/browser/file_system/external_mount_points.cc4
-rw-r--r--chromium/storage/browser/file_system/file_system_context.cc29
-rw-r--r--chromium/storage/browser/file_system/file_system_context.h4
-rw-r--r--chromium/storage/browser/file_system/file_system_quota_client.cc71
-rw-r--r--chromium/storage/browser/file_system/file_system_quota_client.h26
-rw-r--r--chromium/storage/browser/file_system/file_system_quota_client_unittest.cc274
-rw-r--r--chromium/storage/browser/file_system/file_system_quota_util.h5
-rw-r--r--chromium/storage/browser/file_system/file_system_url.cc19
-rw-r--r--chromium/storage/browser/file_system/file_system_url.h12
-rw-r--r--chromium/storage/browser/file_system/isolated_context.cc4
-rw-r--r--chromium/storage/browser/file_system/local_file_util_unittest.cc2
-rw-r--r--chromium/storage/browser/file_system/native_file_util.cc18
-rw-r--r--chromium/storage/browser/file_system/native_file_util_unittest.cc84
-rw-r--r--chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate.cc13
-rw-r--r--chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate_unittest.cc4
-rw-r--r--chromium/storage/browser/file_system/obfuscated_file_util_unittest.cc6
-rw-r--r--chromium/storage/browser/file_system/plugin_private_file_system_backend.cc17
-rw-r--r--chromium/storage/browser/file_system/plugin_private_file_system_backend.h3
-rw-r--r--chromium/storage/browser/file_system/quota/quota_backend_impl.cc3
-rw-r--r--chromium/storage/browser/file_system/sandbox_directory_database.cc2
-rw-r--r--chromium/storage/browser/file_system/sandbox_file_system_backend_delegate.cc24
-rw-r--r--chromium/storage/browser/file_system/sandbox_file_system_backend_delegate.h3
-rw-r--r--chromium/storage/browser/file_system/sandbox_origin_database.cc2
-rw-r--r--chromium/storage/browser/file_system/sandbox_quota_observer.cc3
-rw-r--r--chromium/storage/browser/quota/BUILD.gn17
-rw-r--r--chromium/storage/browser/quota/OWNERS3
-rw-r--r--chromium/storage/browser/quota/client_usage_tracker.cc514
-rw-r--r--chromium/storage/browser/quota/client_usage_tracker.h124
-rw-r--r--chromium/storage/browser/quota/quota_callbacks.h5
-rw-r--r--chromium/storage/browser/quota/quota_database.cc257
-rw-r--r--chromium/storage/browser/quota/quota_database.h78
-rw-r--r--chromium/storage/browser/quota/quota_database_unittest.cc222
-rw-r--r--chromium/storage/browser/quota/quota_features.cc5
-rw-r--r--chromium/storage/browser/quota/quota_features.h3
-rw-r--r--chromium/storage/browser/quota/quota_internals.mojom24
-rw-r--r--chromium/storage/browser/quota/quota_manager_impl.cc1220
-rw-r--r--chromium/storage/browser/quota/quota_manager_impl.h161
-rw-r--r--chromium/storage/browser/quota/quota_manager_proxy.cc82
-rw-r--r--chromium/storage/browser/quota/quota_manager_proxy.h22
-rw-r--r--chromium/storage/browser/quota/quota_manager_unittest.cc2929
-rw-r--r--chromium/storage/browser/quota/quota_temporary_storage_evictor.cc2
-rw-r--r--chromium/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc1
-rw-r--r--chromium/storage/browser/quota/storage_policy_observer.cc59
-rw-r--r--chromium/storage/browser/quota/storage_policy_observer.h7
-rw-r--r--chromium/storage/browser/quota/storage_policy_observer_unittest.cc92
-rw-r--r--chromium/storage/browser/quota/usage_tracker.cc248
-rw-r--r--chromium/storage/browser/quota/usage_tracker.h75
-rw-r--r--chromium/storage/browser/quota/usage_tracker_unittest.cc257
-rw-r--r--chromium/storage/common/file_system/file_system_types.h5
-rw-r--r--chromium/storage/common/file_system/file_system_util.cc12
72 files changed, 4030 insertions, 3448 deletions
diff --git a/chromium/storage/BUILD.gn b/chromium/storage/BUILD.gn
index 23789543889..052117693f0 100644
--- a/chromium/storage/BUILD.gn
+++ b/chromium/storage/BUILD.gn
@@ -10,4 +10,6 @@ test("storage_unittests") {
]
data = [ "//storage/test/data/" ]
+
+ data_deps = [ "//testing/buildbot/filters:storage_unittests_filters" ]
}
diff --git a/chromium/storage/DEPS b/chromium/storage/DEPS
index 0bfd8069e88..fe6db678741 100644
--- a/chromium/storage/DEPS
+++ b/chromium/storage/DEPS
@@ -1,4 +1,5 @@
include_rules = [
+ "+components/crash/core/common/crash_key.h",
"+components/services/filesystem",
"+components/services/storage",
"+crypto",
diff --git a/chromium/storage/browser/BUILD.gn b/chromium/storage/browser/BUILD.gn
index bd02958142c..5e80213ac73 100644
--- a/chromium/storage/browser/BUILD.gn
+++ b/chromium/storage/browser/BUILD.gn
@@ -234,6 +234,7 @@ component("browser") {
"//base:i18n",
"//base/third_party/dynamic_annotations",
"//build:chromeos_buildflags",
+ "//components/crash/core/common:crash_key",
"//components/services/storage/public/cpp",
"//components/services/storage/public/cpp/filesystem",
"//mojo/public/cpp/bindings",
@@ -242,6 +243,7 @@ component("browser") {
"//services/network/public/cpp",
"//services/network/public/mojom",
"//sql",
+ "//storage/browser/quota:mojo_bindings",
"//third_party/blink/public/common",
"//third_party/leveldatabase",
"//third_party/sqlite",
@@ -328,6 +330,7 @@ source_set("unittests") {
"quota/quota_manager_unittest.cc",
"quota/quota_settings_unittest.cc",
"quota/quota_temporary_storage_evictor_unittest.cc",
+ "quota/storage_policy_observer_unittest.cc",
"quota/usage_tracker_unittest.cc",
"test/mock_quota_manager_unittest.cc",
]
@@ -379,6 +382,8 @@ static_library("test_support") {
"test/mock_file_update_observer.h",
"test/mock_quota_client.cc",
"test/mock_quota_client.h",
+ "test/mock_quota_database.cc",
+ "test/mock_quota_database.h",
"test/mock_quota_manager.cc",
"test/mock_quota_manager.h",
"test/mock_quota_manager_proxy.cc",
diff --git a/chromium/storage/browser/blob/blob_builder_from_stream.cc b/chromium/storage/browser/blob/blob_builder_from_stream.cc
index d688f78da36..a39af4e716c 100644
--- a/chromium/storage/browser/blob/blob_builder_from_stream.cc
+++ b/chromium/storage/browser/blob/blob_builder_from_stream.cc
@@ -92,7 +92,7 @@ class DataPipeConsumerHelper {
if (result != MOJO_RESULT_OK) {
// We requested a trap on a condition that can never occur. The state of
// `pipe_` likely changed.
- DCHECK(result == MOJO_RESULT_FAILED_PRECONDITION);
+ DCHECK_EQ(result, MOJO_RESULT_FAILED_PRECONDITION);
InvokeDone(mojo::ScopedDataPipeConsumerHandle(), PassProgressClient(),
/*success=*/true, current_offset_);
delete this;
diff --git a/chromium/storage/browser/blob/blob_memory_controller.cc b/chromium/storage/browser/blob/blob_memory_controller.cc
index 40123a3c62f..9143dfcd229 100644
--- a/chromium/storage/browser/blob/blob_memory_controller.cc
+++ b/chromium/storage/browser/blob/blob_memory_controller.cc
@@ -96,11 +96,11 @@ BlobStorageLimits CalculateBlobStorageLimitsImpl(
// Don't do specialty configuration for error size (-1).
if (memory_size > 0) {
-#if !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_ANDROID) && \
+#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID) && \
defined(ARCH_CPU_64_BITS)
constexpr size_t kTwoGigabytes = 2ull * 1024 * 1024 * 1024;
limits.max_blob_in_memory_space = kTwoGigabytes;
-#elif defined(OS_ANDROID)
+#elif BUILDFLAG(IS_ANDROID)
limits.max_blob_in_memory_space = static_cast<size_t>(memory_size / 100ll);
#else
limits.max_blob_in_memory_space = static_cast<size_t>(memory_size / 5ll);
@@ -116,7 +116,7 @@ BlobStorageLimits CalculateBlobStorageLimitsImpl(
if (disk_size >= 0) {
#if BUILDFLAG(IS_CHROMEOS_ASH)
limits.desired_max_disk_space = static_cast<uint64_t>(disk_size / 2ll);
-#elif defined(OS_ANDROID)
+#elif BUILDFLAG(IS_ANDROID)
limits.desired_max_disk_space = static_cast<uint64_t>(3ll * disk_size / 50);
#else
limits.desired_max_disk_space = static_cast<uint64_t>(disk_size / 10ll);
diff --git a/chromium/storage/browser/blob/blob_registry_impl_unittest.cc b/chromium/storage/browser/blob/blob_registry_impl_unittest.cc
index e7de3b85352..90a5b6b002d 100644
--- a/chromium/storage/browser/blob/blob_registry_impl_unittest.cc
+++ b/chromium/storage/browser/blob/blob_registry_impl_unittest.cc
@@ -7,13 +7,13 @@
#include <limits>
#include <memory>
#include <string>
+#include <tuple>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/files/scoped_temp_dir.h"
-#include "base/ignore_result.h"
#include "base/memory/raw_ptr.h"
#include "base/rand_util.h"
#include "base/run_loop.h"
@@ -334,7 +334,7 @@ TEST_F(BlobRegistryImplTest, Register_ReferencedBlobClosedPipe) {
std::vector<blink::mojom::DataElementPtr> elements;
mojo::PendingRemote<blink::mojom::Blob> referenced_blob_remote;
- ignore_result(referenced_blob_remote.InitWithNewPipeAndPassReceiver());
+ std::ignore = referenced_blob_remote.InitWithNewPipeAndPassReceiver();
elements.push_back(
blink::mojom::DataElement::NewBlob(blink::mojom::DataElementBlob::New(
std::move(referenced_blob_remote), 0, 16)));
@@ -975,7 +975,7 @@ TEST_F(BlobRegistryImplTest, Register_BytesProviderClosedPipe) {
const std::string kId = "id";
mojo::PendingRemote<blink::mojom::BytesProvider> bytes_provider_remote;
- ignore_result(bytes_provider_remote.InitWithNewPipeAndPassReceiver());
+ std::ignore = bytes_provider_remote.InitWithNewPipeAndPassReceiver();
std::vector<blink::mojom::DataElementPtr> elements;
elements.push_back(
diff --git a/chromium/storage/browser/blob/blob_storage_constants.h b/chromium/storage/browser/blob/blob_storage_constants.h
index 0803c4d7af9..19f6e2404b2 100644
--- a/chromium/storage/browser/blob/blob_storage_constants.h
+++ b/chromium/storage/browser/blob/blob_storage_constants.h
@@ -20,7 +20,7 @@ constexpr size_t kDefaultMaxBlobInMemorySpace = 500u * 1024 * 1024;
constexpr uint64_t kDefaultMaxBlobDiskSpace = 0ull;
constexpr uint64_t kDefaultMaxPageFileSize = 100ull * 1024 * 1024;
-#if defined(OS_ANDROID)
+#if BUILDFLAG(IS_ANDROID)
// On minimal Android maximum in-memory space can be as low as 5MB.
constexpr uint64_t kDefaultMinPageFileSize = 5ull * 1024 * 1024 / 2;
const float kDefaultMaxBlobInMemorySpaceUnderPressureRatio = 0.02f;
diff --git a/chromium/storage/browser/blob/blob_url_loader.cc b/chromium/storage/browser/blob/blob_url_loader.cc
index b2e061c4e11..e3a0b7823c8 100644
--- a/chromium/storage/browser/blob/blob_url_loader.cc
+++ b/chromium/storage/browser/blob/blob_url_loader.cc
@@ -234,14 +234,21 @@ void BlobURLLoader::HeadersCompleted(
// TODO(jam): some of this code can be shared with
// services/network/url_loader.h
- client_->OnReceiveResponse(std::move(response));
+
+ client_->OnReceiveResponse(
+ std::move(response),
+ base::FeatureList::IsEnabled(network::features::kCombineResponseBody)
+ ? std::move(response_body_consumer_handle_)
+ : mojo::ScopedDataPipeConsumerHandle());
sent_headers_ = true;
if (metadata.has_value())
client_->OnReceiveCachedMetadata(std::move(metadata.value()));
- client_->OnStartLoadingResponseBody(
- std::move(response_body_consumer_handle_));
+ if (!base::FeatureList::IsEnabled(network::features::kCombineResponseBody)) {
+ client_->OnStartLoadingResponseBody(
+ std::move(response_body_consumer_handle_));
+ }
}
} // namespace storage
diff --git a/chromium/storage/browser/blob/blob_url_registry.cc b/chromium/storage/browser/blob/blob_url_registry.cc
index d658e7e901e..f79e7e0baab 100644
--- a/chromium/storage/browser/blob/blob_url_registry.cc
+++ b/chromium/storage/browser/blob/blob_url_registry.cc
@@ -20,13 +20,16 @@ BlobUrlRegistry::~BlobUrlRegistry() {
bool BlobUrlRegistry::AddUrlMapping(
const GURL& blob_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) {
+ // TODO(https://crbug.com/1224926): Remove these once experiment is over.
+ const base::UnguessableToken& unsafe_agent_cluster_id,
+ const absl::optional<net::SchemefulSite>& unsafe_top_level_site) {
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;
+ if (unsafe_top_level_site)
+ url_to_unsafe_top_level_site_[blob_url] = *unsafe_top_level_site;
url_to_blob_[blob_url] = std::move(blob);
return true;
}
@@ -35,13 +38,12 @@ bool BlobUrlRegistry::RemoveUrlMapping(const GURL& blob_url) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!BlobUrlUtils::UrlHasFragment(blob_url));
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()) {
+ if (blob_it == url_to_blob_.end()) {
return false;
}
url_to_blob_.erase(blob_it);
- url_to_unsafe_agent_cluster_id_.erase(agent_it);
+ url_to_unsafe_agent_cluster_id_.erase(blob_url);
+ url_to_unsafe_top_level_site_.erase(blob_url);
return true;
}
@@ -66,6 +68,17 @@ absl::optional<base::UnguessableToken> BlobUrlRegistry::GetUnsafeAgentClusterID(
return absl::nullopt;
}
+absl::optional<net::SchemefulSite> BlobUrlRegistry::GetUnsafeTopLevelSite(
+ const GURL& blob_url) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ auto it = url_to_unsafe_top_level_site_.find(blob_url);
+ if (it != url_to_unsafe_top_level_site_.end())
+ return it->second;
+ if (fallback_)
+ return fallback_->GetUnsafeTopLevelSite(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 b2b7a3156d2..390a59b3588 100644
--- a/chromium/storage/browser/blob/blob_url_registry.h
+++ b/chromium/storage/browser/blob/blob_url_registry.h
@@ -12,6 +12,7 @@
#include "base/unguessable_token.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "net/base/schemeful_site.h"
#include "storage/browser/blob/blob_storage_constants.h"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
@@ -34,8 +35,9 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobUrlRegistry {
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);
+ // TODO(https://crbug.com/1224926): Remove these once experiment is over.
+ const base::UnguessableToken& unsafe_agent_cluster_id,
+ const absl::optional<net::SchemefulSite>& unsafe_top_level_site);
// Removes the given URL mapping. Returns false if the url wasn't mapped.
bool RemoveUrlMapping(const GURL& url);
@@ -46,6 +48,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobUrlRegistry {
// TODO(https://crbug.com/1224926): Remove this once experiment is over.
absl::optional<base::UnguessableToken> GetUnsafeAgentClusterID(
const GURL& blob_url) const;
+ absl::optional<net::SchemefulSite> GetUnsafeTopLevelSite(
+ const GURL& blob_url) const;
// Returns the blob from the given url. Returns a null remote if the mapping
// doesn't exist.
@@ -77,6 +81,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobUrlRegistry {
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<GURL, net::SchemefulSite> url_to_unsafe_top_level_site_;
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 0795ecaf080..4a1cfeda0dd 100644
--- a/chromium/storage/browser/blob/blob_url_registry_unittest.cc
+++ b/chromium/storage/browser/blob/blob_url_registry_unittest.cc
@@ -40,6 +40,10 @@ TEST(BlobUrlRegistry, URLRegistration) {
const GURL kURL2 = GURL("blob://Blob2");
base::UnguessableToken kTokenId1 = base::UnguessableToken::Create();
base::UnguessableToken kTokenId2 = base::UnguessableToken::Create();
+ net::SchemefulSite kTopLevelSite1 =
+ net::SchemefulSite(GURL("https://example.com"));
+ net::SchemefulSite kTopLevelSite2 =
+ net::SchemefulSite(GURL("https://foobar.com"));
base::test::SingleThreadTaskEnvironment task_environment_;
@@ -52,24 +56,32 @@ TEST(BlobUrlRegistry, URLRegistration) {
EXPECT_FALSE(registry.RemoveUrlMapping(kURL1));
EXPECT_EQ(0u, registry.url_count());
- EXPECT_TRUE(registry.AddUrlMapping(kURL1, blob1.Clone(), kTokenId1));
- EXPECT_FALSE(registry.AddUrlMapping(kURL1, blob2.Clone(), kTokenId1));
+ EXPECT_TRUE(
+ registry.AddUrlMapping(kURL1, blob1.Clone(), kTokenId1, kTopLevelSite1));
+ EXPECT_FALSE(
+ registry.AddUrlMapping(kURL1, blob2.Clone(), kTokenId1, kTopLevelSite1));
EXPECT_EQ(kTokenId1, registry.GetUnsafeAgentClusterID(kURL1));
+ EXPECT_EQ(kTopLevelSite1, registry.GetUnsafeTopLevelSite(kURL1));
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(), kTokenId2));
+ EXPECT_TRUE(
+ registry.AddUrlMapping(kURL2, blob2.Clone(), kTokenId2, kTopLevelSite2));
EXPECT_EQ(kTokenId2, registry.GetUnsafeAgentClusterID(kURL2));
+ EXPECT_EQ(kTopLevelSite2, registry.GetUnsafeTopLevelSite(kURL2));
EXPECT_EQ(2u, registry.url_count());
EXPECT_TRUE(registry.RemoveUrlMapping(kURL2));
EXPECT_FALSE(registry.IsUrlMapped(kURL2));
EXPECT_EQ(absl::nullopt, registry.GetUnsafeAgentClusterID(kURL2));
+ EXPECT_EQ(absl::nullopt, registry.GetUnsafeTopLevelSite(kURL2));
// Both urls point to the same blob.
- EXPECT_TRUE(registry.AddUrlMapping(kURL2, blob1.Clone(), kTokenId2));
+ EXPECT_TRUE(
+ registry.AddUrlMapping(kURL2, blob1.Clone(), kTokenId2, kTopLevelSite2));
EXPECT_EQ(kTokenId2, registry.GetUnsafeAgentClusterID(kURL2));
+ EXPECT_EQ(kTopLevelSite2, registry.GetUnsafeTopLevelSite(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 de637458878..a42d12fd035 100644
--- a/chromium/storage/browser/blob/blob_url_store_impl.cc
+++ b/chromium/storage/browser/blob/blob_url_store_impl.cc
@@ -6,11 +6,13 @@
#include "base/bind.h"
#include "base/strings/strcat.h"
+#include "components/crash/core/common/crash_key.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "storage/browser/blob/blob_impl.h"
#include "storage/browser/blob/blob_url_loader_factory.h"
#include "storage/browser/blob/blob_url_registry.h"
#include "storage/browser/blob/blob_url_utils.h"
+#include "url/url_util.h"
namespace storage {
@@ -73,8 +75,9 @@ BlobURLStoreImpl::~BlobURLStoreImpl() {
void BlobURLStoreImpl::Register(
mojo::PendingRemote<blink::mojom::Blob> blob,
const GURL& url,
- // TODO(https://crbug.com/1224926): Remove this once experiment is over.
+ // TODO(https://crbug.com/1224926): Remove these once experiment is over.
const base::UnguessableToken& unsafe_agent_cluster_id,
+ const absl::optional<net::SchemefulSite>& unsafe_top_level_site,
RegisterCallback callback) {
// TODO(mek): Generate blob URLs here, rather than validating the URLs the
// renderer process generated.
@@ -84,7 +87,8 @@ void BlobURLStoreImpl::Register(
}
if (registry_)
- registry_->AddUrlMapping(url, std::move(blob), unsafe_agent_cluster_id);
+ registry_->AddUrlMapping(url, std::move(blob), unsafe_agent_cluster_id,
+ unsafe_top_level_site);
urls_.insert(url);
std::move(callback).Run();
}
@@ -112,10 +116,16 @@ void BlobURLStoreImpl::ResolveAsURLLoaderFactory(
const GURL& url,
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));
+ if (!registry_) {
+ BlobURLLoaderFactory::Create(mojo::NullRemote(), url, std::move(receiver));
+ std::move(callback).Run(absl::nullopt, absl::nullopt);
+ return;
+ }
+
+ BlobURLLoaderFactory::Create(registry_->GetBlobFromUrl(url), url,
+ std::move(receiver));
+ std::move(callback).Run(registry_->GetUnsafeAgentClusterID(url),
+ registry_->GetUnsafeTopLevelSite(url));
}
void BlobURLStoreImpl::ResolveForNavigation(
@@ -137,6 +147,14 @@ void BlobURLStoreImpl::ResolveForNavigation(
bool BlobURLStoreImpl::BlobUrlIsValid(const GURL& url,
const char* method) const {
+ // TODO(crbug.com/1278268): Remove crash keys.
+ static crash_reporter::CrashKeyString<256> origin_key("origin");
+ static crash_reporter::CrashKeyString<256> url_key("url");
+ crash_reporter::ScopedCrashKeyString scoped_origin_key(
+ &origin_key, origin_.GetDebugString());
+ crash_reporter::ScopedCrashKeyString scoped_url_key(
+ &url_key, url.possibly_invalid_spec());
+
if (!url.SchemeIsBlob()) {
mojo::ReportBadMessage(
base::StrCat({"Invalid scheme passed to BlobURLStore::", method}));
@@ -148,11 +166,15 @@ bool BlobURLStoreImpl::BlobUrlIsValid(const GURL& url,
// `origin_` will always be a non-opaque file: origin for pages loaded from
// file:// URLs. To deal with this, we treat file:// origins and
// opaque origins separately from non-opaque origins.
+ // URLs created by blink::BlobURL::CreateBlobURL() will always get "blank" as
+ // origin if the scheme is local, which usually includes the file scheme and
+ // on Android also the content scheme.
bool valid_origin = true;
if (url_origin.scheme() == url::kFileScheme) {
valid_origin = origin_.scheme() == url::kFileScheme;
} else if (url_origin.opaque()) {
- valid_origin = origin_.opaque() || origin_.scheme() == url::kFileScheme;
+ valid_origin = origin_.opaque() ||
+ base::Contains(url::GetLocalSchemes(), origin_.scheme());
} else {
valid_origin = origin_ == url_origin;
}
diff --git a/chromium/storage/browser/blob/blob_url_store_impl.h b/chromium/storage/browser/blob/blob_url_store_impl.h
index 3db3a95d427..c46b7ffb18b 100644
--- a/chromium/storage/browser/blob/blob_url_store_impl.h
+++ b/chromium/storage/browser/blob/blob_url_store_impl.h
@@ -34,8 +34,9 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobURLStoreImpl
void Register(
mojo::PendingRemote<blink::mojom::Blob> blob,
const GURL& url,
- // TODO(https://crbug.com/1224926): Remove this once experiment is over.
+ // TODO(https://crbug.com/1224926): Remove these once experiment is over.
const base::UnguessableToken& unsafe_agent_cluster_id,
+ const absl::optional<net::SchemefulSite>& unsafe_top_level_site,
RegisterCallback callback) override;
void Revoke(const GURL& url) override;
void Resolve(const GURL& url, ResolveCallback callback) override;
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 04c44794d55..0da6acf7a41 100644
--- a/chromium/storage/browser/blob/blob_url_store_impl_unittest.cc
+++ b/chromium/storage/browser/blob/blob_url_store_impl_unittest.cc
@@ -82,7 +82,7 @@ class BlobURLStoreImplTest : public testing::Test {
const GURL& url) {
base::RunLoop loop;
store->Register(std::move(blob), url, agent_cluster_id_,
- loop.QuitClosure());
+ net::SchemefulSite(), loop.QuitClosure());
loop.Run();
}
@@ -284,7 +284,8 @@ TEST_F(BlobURLStoreImplTest, ResolveAsURLLoaderFactory) {
[](base::OnceClosure done,
const base::UnguessableToken& agent_registered,
const absl::optional<base::UnguessableToken>&
- unsafe_agent_cluster_id) {
+ unsafe_agent_cluster_id,
+ const absl::optional<net::SchemefulSite>& unsafe_top_level_site) {
EXPECT_EQ(agent_registered, unsafe_agent_cluster_id);
std::move(done).Run();
},
diff --git a/chromium/storage/browser/blob/scoped_file.cc b/chromium/storage/browser/blob/scoped_file.cc
index 9a9a2f9121c..98cac2782c8 100644
--- a/chromium/storage/browser/blob/scoped_file.cc
+++ b/chromium/storage/browser/blob/scoped_file.cc
@@ -27,7 +27,7 @@ ScopedFile::ScopedFile(const base::FilePath& path,
DCHECK(path.empty() || policy != DELETE_ON_SCOPE_OUT ||
file_task_runner_.get())
<< "path:" << path.value() << " policy:" << policy
- << " runner:" << file_task_runner.get();
+ << " runner:" << file_task_runner_.get();
}
ScopedFile::ScopedFile(ScopedFile&& other) {
diff --git a/chromium/storage/browser/database/database_quota_client.cc b/chromium/storage/browser/database/database_quota_client.cc
index 8240da802da..eea28bf1fe1 100644
--- a/chromium/storage/browser/database/database_quota_client.cc
+++ b/chromium/storage/browser/database/database_quota_client.cc
@@ -18,6 +18,7 @@
#include "base/task/sequenced_task_runner.h"
#include "base/task/task_runner_util.h"
#include "base/threading/sequenced_task_runner_handle.h"
+#include "components/services/storage/public/cpp/buckets/bucket_locator.h"
#include "net/base/completion_once_callback.h"
#include "net/base/net_errors.h"
#include "storage/browser/database/database_tracker.h"
@@ -42,17 +43,22 @@ DatabaseQuotaClient::~DatabaseQuotaClient() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
-void DatabaseQuotaClient::GetStorageKeyUsage(
- const StorageKey& storage_key,
- StorageType type,
- GetStorageKeyUsageCallback callback) {
+void DatabaseQuotaClient::GetBucketUsage(const BucketLocator& bucket,
+ GetBucketUsageCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!callback.is_null());
- DCHECK_EQ(type, StorageType::kTemporary);
+ DCHECK_EQ(bucket.type, StorageType::kTemporary);
+
+ // Skip non-default buckets because Storage Buckets are not planned to be
+ // supported by WebSQL.
+ if (!bucket.is_default) {
+ std::move(callback).Run(0);
+ return;
+ }
OriginInfo info;
- if (db_tracker_.GetOriginInfo(GetIdentifierFromOrigin(storage_key.origin()),
- &info)) {
+ if (db_tracker_.GetOriginInfo(
+ GetIdentifierFromOrigin(bucket.storage_key.origin()), &info)) {
std::move(callback).Run(info.TotalSize());
} else {
std::move(callback).Run(0);
@@ -77,42 +83,23 @@ void DatabaseQuotaClient::GetStorageKeysForType(
std::move(callback).Run(all_storage_keys);
}
-void DatabaseQuotaClient::GetStorageKeysForHost(
- StorageType type,
- const std::string& host,
- GetStorageKeysForHostCallback callback) {
+void DatabaseQuotaClient::DeleteBucketData(const BucketLocator& bucket,
+ DeleteBucketDataCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!callback.is_null());
- DCHECK_EQ(type, StorageType::kTemporary);
-
- 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);
+ DCHECK_EQ(bucket.type, StorageType::kTemporary);
- 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));
- }
+ // Skip non-default buckets because Storage Buckets are not planned to be
+ // supported by WebSQL.
+ if (!bucket.is_default) {
+ std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk);
+ return;
}
- std::move(callback).Run(host_storage_keys);
-}
-
-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_.DeleteDataForOrigin(
- storage_key.origin(),
+ bucket.storage_key.origin(),
base::BindOnce(
- [](DeleteStorageKeyDataCallback callback, int result) {
+ [](DeleteBucketDataCallback callback, int result) {
std::move(callback).Run(
(result == net::OK) ? blink::mojom::QuotaStatusCode::kOk
: blink::mojom::QuotaStatusCode::kUnknown);
diff --git a/chromium/storage/browser/database/database_quota_client.h b/chromium/storage/browser/database/database_quota_client.h
index d4c9b427314..96510e4213d 100644
--- a/chromium/storage/browser/database/database_quota_client.h
+++ b/chromium/storage/browser/database/database_quota_client.h
@@ -5,31 +5,25 @@
#ifndef STORAGE_BROWSER_DATABASE_DATABASE_QUOTA_CLIENT_H_
#define STORAGE_BROWSER_DATABASE_DATABASE_QUOTA_CLIENT_H_
-#include <set>
-#include <string>
-
#include "base/component_export.h"
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
#include "base/task/single_thread_task_runner.h"
#include "base/thread_annotations.h"
-#include "components/services/storage/public/cpp/storage_key_quota_client.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"
-namespace blink {
-class StorageKey;
-} // namespace blink
-
namespace storage {
class DatabaseTracker;
+struct BucketLocator;
// Integrates WebSQL databases with the quota management system.
//
// This interface is used on the IO thread by the quota manager.
class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseQuotaClient
- : public StorageKeyQuotaClient {
+ : public mojom::QuotaClient {
public:
explicit DatabaseQuotaClient(DatabaseTracker& tracker);
@@ -38,18 +32,13 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseQuotaClient
~DatabaseQuotaClient() override;
- // StorageKeyQuotaClient method overrides.
- void GetStorageKeyUsage(const blink::StorageKey& storage_key,
- blink::mojom::StorageType type,
- GetStorageKeyUsageCallback callback) override;
+ // mojom::QuotaClient method overrides.
+ void GetBucketUsage(const BucketLocator& bucket,
+ GetBucketUsageCallback 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 DeleteBucketData(const BucketLocator& bucket,
+ DeleteBucketDataCallback callback) override;
void PerformStorageCleanup(blink::mojom::StorageType type,
PerformStorageCleanupCallback callback) override;
diff --git a/chromium/storage/browser/database/database_quota_client_unittest.cc b/chromium/storage/browser/database/database_quota_client_unittest.cc
index 06f0483ca51..17fe31dbd1b 100644
--- a/chromium/storage/browser/database/database_quota_client_unittest.cc
+++ b/chromium/storage/browser/database/database_quota_client_unittest.cc
@@ -4,6 +4,7 @@
#include <stdint.h>
+#include <cstdint>
#include <map>
#include <string>
#include <utility>
@@ -13,6 +14,7 @@
#include "base/callback_helpers.h"
#include "base/containers/contains.h"
#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
#include "base/location.h"
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
@@ -20,13 +22,17 @@
#include "base/task/single_thread_task_runner.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
+#include "base/test/test_future.h"
#include "base/threading/sequenced_task_runner_handle.h"
+#include "components/services/storage/public/cpp/buckets/bucket_locator.h"
+#include "components/services/storage/public/cpp/quota_error_or.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_manager.h"
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/browser/quota/special_storage_policy.h"
#include "storage/common/database/database_identifier.h"
@@ -46,11 +52,13 @@ static const blink::mojom::StorageType kTemp =
// Mocks DatabaseTracker methods used by DatabaseQuotaClient.
class MockDatabaseTracker : public DatabaseTracker {
public:
- MockDatabaseTracker()
- : DatabaseTracker(base::FilePath(),
- /*is_incognito=*/false,
+ MockDatabaseTracker(const base::FilePath& path,
+ bool is_incognito,
+ scoped_refptr<QuotaManagerProxy> quota_manager_proxy)
+ : DatabaseTracker(path,
+ is_incognito,
/*special_storage_policy=*/nullptr,
- /*quota_manager_proxy=*/nullptr,
+ quota_manager_proxy,
DatabaseTracker::CreatePassKey()) {}
bool GetOriginInfo(const std::string& origin_identifier,
@@ -126,20 +134,28 @@ class MockDatabaseTracker : public DatabaseTracker {
};
// Base class for our test fixtures.
-class DatabaseQuotaClientTest : public testing::Test {
+class DatabaseQuotaClientTest : public testing::TestWithParam<bool> {
public:
const blink::StorageKey kStorageKeyA;
const blink::StorageKey kStorageKeyB;
- const blink::StorageKey kStorageKeyOther;
DatabaseQuotaClientTest()
: kStorageKeyA(
blink::StorageKey::CreateFromStringForTesting("http://host")),
kStorageKeyB(
- blink::StorageKey::CreateFromStringForTesting("http://host:8000")),
- kStorageKeyOther(
- blink::StorageKey::CreateFromStringForTesting("http://other")),
- mock_tracker_(base::MakeRefCounted<MockDatabaseTracker>()) {}
+ blink::StorageKey::CreateFromStringForTesting("http://host:8000")) {
+ }
+
+ void SetUp() override {
+ ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
+ quota_manager_ = base::MakeRefCounted<QuotaManager>(
+ /*is_incognito_=*/false, data_dir_.GetPath(),
+ base::ThreadTaskRunnerHandle::Get(),
+ /*quota_change_callback=*/base::DoNothing(),
+ /*special_storage_policy=*/nullptr, GetQuotaSettingsFunc());
+ mock_tracker_ = base::MakeRefCounted<MockDatabaseTracker>(
+ data_dir_.GetPath(), is_incognito(), quota_manager_->proxy());
+ }
void TearDown() override {
base::RunLoop run_loop;
@@ -151,19 +167,26 @@ class DatabaseQuotaClientTest : public testing::Test {
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.GetStorageKeyUsage(storage_key, type,
- base::BindLambdaForTesting([&](int64_t usage) {
- result = usage;
- loop.Quit();
- }));
- loop.Run();
- EXPECT_GT(result, -1);
- return result;
+ bool is_incognito() const { return GetParam(); }
+
+ BucketLocator CreateBucketForTesting(const blink::StorageKey& storage_key,
+ const std::string& name,
+ blink::mojom::StorageType type) {
+ base::test::TestFuture<storage::QuotaErrorOr<storage::BucketInfo>>
+ bucket_future;
+ quota_manager_->proxy()->CreateBucketForTesting(
+ storage_key, name, type, base::SequencedTaskRunnerHandle::Get(),
+ bucket_future.GetCallback());
+ auto bucket = bucket_future.Take();
+ EXPECT_TRUE(bucket.ok());
+ return bucket->ToBucketLocator();
+ }
+
+ int64_t GetBucketUsage(mojom::QuotaClient& client,
+ const BucketLocator& bucket) {
+ base::test::TestFuture<int64_t> usage_future;
+ client.GetBucketUsage(bucket, usage_future.GetCallback());
+ return usage_future.Get();
}
static std::vector<blink::StorageKey> GetStorageKeysForType(
@@ -181,85 +204,36 @@ class DatabaseQuotaClientTest : public testing::Test {
return result;
}
- static std::vector<blink::StorageKey> GetStorageKeysForHost(
- mojom::QuotaClient& client,
- blink::mojom::StorageType type,
- const std::string& host) {
- std::vector<blink::StorageKey> result;
- base::RunLoop loop;
- 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 DeleteStorageKeyData(
- mojom::QuotaClient& client,
- blink::mojom::StorageType type,
- const blink::StorageKey& storage_key) {
- blink::mojom::QuotaStatusCode result =
- blink::mojom::QuotaStatusCode::kUnknown;
- base::RunLoop loop;
- client.DeleteStorageKeyData(
- storage_key, type,
- base::BindLambdaForTesting([&](blink::mojom::QuotaStatusCode code) {
- result = code;
- loop.Quit();
- }));
- loop.Run();
- return result;
+ blink::mojom::QuotaStatusCode DeleteBucketData(mojom::QuotaClient& client,
+ const BucketLocator& bucket) {
+ base::test::TestFuture<blink::mojom::QuotaStatusCode> delete_future;
+ client.DeleteBucketData(bucket, delete_future.GetCallback());
+ return delete_future.Get();
}
+ base::ScopedTempDir data_dir_;
base::test::TaskEnvironment task_environment_;
scoped_refptr<MockDatabaseTracker> mock_tracker_;
+ scoped_refptr<QuotaManager> quota_manager_;
base::WeakPtrFactory<DatabaseQuotaClientTest> weak_factory_{this};
};
-TEST_F(DatabaseQuotaClientTest, GetStorageKeyUsage) {
+TEST_P(DatabaseQuotaClientTest, GetBucketUsage) {
DatabaseQuotaClient client(*mock_tracker_);
+ auto bucket_a =
+ CreateBucketForTesting(kStorageKeyA, kDefaultBucketName, kTemp);
+ auto bucket_b =
+ CreateBucketForTesting(kStorageKeyB, kDefaultBucketName, kTemp);
- EXPECT_EQ(0, GetStorageKeyUsage(client, kStorageKeyA, kTemp));
+ EXPECT_EQ(0, GetBucketUsage(client, bucket_a));
mock_tracker_->AddMockDatabase(kStorageKeyA.origin(), "fooDB", 1000);
- EXPECT_EQ(1000, GetStorageKeyUsage(client, kStorageKeyA, kTemp));
+ EXPECT_EQ(1000, GetBucketUsage(client, bucket_a));
- EXPECT_EQ(0, GetStorageKeyUsage(client, kStorageKeyB, kTemp));
+ EXPECT_EQ(0, GetBucketUsage(client, bucket_b));
}
-TEST_F(DatabaseQuotaClientTest, GetStorageKeysForHost) {
- DatabaseQuotaClient client(*mock_tracker_);
-
- EXPECT_EQ(kStorageKeyA.origin().host(), kStorageKeyB.origin().host());
- EXPECT_NE(kStorageKeyA.origin().host(), kStorageKeyOther.origin().host());
-
- std::vector<blink::StorageKey> storage_keys =
- GetStorageKeysForHost(client, kTemp, kStorageKeyA.origin().host());
- EXPECT_TRUE(storage_keys.empty());
-
- 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(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(
- GetStorageKeysForHost(client, kTemp, kStorageKeyOther.origin().host())
- .empty());
-}
-
-TEST_F(DatabaseQuotaClientTest, GetStorageKeysForType) {
+TEST_P(DatabaseQuotaClientTest, GetStorageKeysForType) {
DatabaseQuotaClient client(*mock_tracker_);
EXPECT_TRUE(GetStorageKeysForType(client, kTemp).empty());
@@ -271,18 +245,34 @@ TEST_F(DatabaseQuotaClientTest, GetStorageKeysForType) {
EXPECT_THAT(storage_keys, testing::Contains(kStorageKeyA));
}
-TEST_F(DatabaseQuotaClientTest, DeleteStorageKeyData) {
+TEST_P(DatabaseQuotaClientTest, DeleteBucketData) {
DatabaseQuotaClient client(*mock_tracker_);
+ auto bucket_a =
+ CreateBucketForTesting(kStorageKeyA, kDefaultBucketName, kTemp);
mock_tracker_->set_async_delete(false);
EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk,
- DeleteStorageKeyData(client, kTemp, kStorageKeyA));
+ DeleteBucketData(client, bucket_a));
EXPECT_EQ(1, mock_tracker_->delete_called_count());
mock_tracker_->set_async_delete(true);
EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk,
- DeleteStorageKeyData(client, kTemp, kStorageKeyA));
+ DeleteBucketData(client, bucket_a));
EXPECT_EQ(2, mock_tracker_->delete_called_count());
}
+TEST_P(DatabaseQuotaClientTest, NonDefaultBucket) {
+ DatabaseQuotaClient client(*mock_tracker_);
+ auto bucket = CreateBucketForTesting(kStorageKeyA, "inbox_bucket", kTemp);
+ ASSERT_FALSE(bucket.is_default);
+
+ EXPECT_EQ(0, GetBucketUsage(client, bucket));
+ EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk,
+ DeleteBucketData(client, bucket));
+}
+
+INSTANTIATE_TEST_SUITE_P(DatabaseQuotaClientTests,
+ DatabaseQuotaClientTest,
+ testing::Bool());
+
} // namespace storage
diff --git a/chromium/storage/browser/database/database_tracker.cc b/chromium/storage/browser/database/database_tracker.cc
index 842886e2fce..74423c6f847 100644
--- a/chromium/storage/browser/database/database_tracker.cc
+++ b/chromium/storage/browser/database/database_tracker.cc
@@ -425,8 +425,8 @@ bool DatabaseTracker::DeleteClosedDatabase(
quota_manager_proxy_->NotifyStorageModified(
QuotaClientType::kDatabase,
blink::StorageKey(GetOriginFromIdentifier(origin_identifier)),
- blink::mojom::StorageType::kTemporary, -db_file_size,
- base::Time::Now());
+ blink::mojom::StorageType::kTemporary, -db_file_size, base::Time::Now(),
+ base::SequencedTaskRunnerHandle::Get(), base::DoNothing());
// Clean up the main database and invalidate the cached record.
databases_table_->DeleteDatabaseDetails(origin_identifier, database_name);
@@ -504,8 +504,8 @@ bool DatabaseTracker::DeleteOrigin(const std::string& origin_identifier,
quota_manager_proxy_->NotifyStorageModified(
QuotaClientType::kDatabase,
blink::StorageKey(GetOriginFromIdentifier(origin_identifier)),
- blink::mojom::StorageType::kTemporary, -deleted_size,
- base::Time::Now());
+ blink::mojom::StorageType::kTemporary, -deleted_size, base::Time::Now(),
+ base::SequencedTaskRunnerHandle::Get(), base::DoNothing());
}
return true;
@@ -704,7 +704,8 @@ int64_t DatabaseTracker::UpdateOpenDatabaseInfoAndNotify(
QuotaClientType::kDatabase,
blink::StorageKey(GetOriginFromIdentifier(origin_id)),
blink::mojom::StorageType::kTemporary, new_size - old_size,
- base::Time::Now());
+ base::Time::Now(), base::SequencedTaskRunnerHandle::Get(),
+ base::DoNothing());
for (auto& observer : observers_)
observer.OnDatabaseSizeChanged(origin_id, name, new_size);
}
diff --git a/chromium/storage/browser/database/database_tracker_unittest.cc b/chromium/storage/browser/database/database_tracker_unittest.cc
index 9a83aca64f4..32b315b90b9 100644
--- a/chromium/storage/browser/database/database_tracker_unittest.cc
+++ b/chromium/storage/browser/database/database_tracker_unittest.cc
@@ -270,7 +270,7 @@ class DatabaseTracker_TestHelper_Test {
base::TouchFile(tracker->GetFullDBFilePath(kOrigin2, kDB3),
three_days_ago, three_days_ago));
- // Delete databases modified since yesterday. db2 is whitelisted.
+ // Delete databases modified since yesterday. db2 is in the allowlist.
base::Time yesterday = base::Time::Now();
yesterday -= base::Days(1);
diff --git a/chromium/storage/browser/database/vfs_backend.cc b/chromium/storage/browser/database/vfs_backend.cc
index beb7d59db2a..b9b8a8f363b 100644
--- a/chromium/storage/browser/database/vfs_backend.cc
+++ b/chromium/storage/browser/database/vfs_backend.cc
@@ -12,7 +12,7 @@
#include "build/build_config.h"
#include "third_party/sqlite/sqlite3.h"
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
#include <windows.h>
#endif
@@ -129,7 +129,7 @@ int VfsBackend::DeleteFile(const base::FilePath& file_path, bool sync_dir) {
return SQLITE_IOERR_DELETE;
int error_code = SQLITE_OK;
-#if defined(OS_POSIX) || defined(OS_FUCHSIA)
+#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
if (sync_dir) {
base::File dir(file_path.DirName(), base::File::FLAG_READ);
if (dir.IsValid()) {
@@ -145,9 +145,9 @@ int VfsBackend::DeleteFile(const base::FilePath& file_path, bool sync_dir) {
// static
uint32_t VfsBackend::GetFileAttributes(const base::FilePath& file_path) {
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
uint32_t attributes = ::GetFileAttributes(file_path.value().c_str());
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
+#elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
uint32_t attributes = 0;
if (!access(file_path.value().c_str(), R_OK))
attributes |= static_cast<uint32_t>(R_OK);
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 20c902e9612..22681a159b1 100644
--- a/chromium/storage/browser/file_system/dragged_file_util_unittest.cc
+++ b/chromium/storage/browser/file_system/dragged_file_util_unittest.cc
@@ -52,9 +52,7 @@ constexpr const base::FilePath::CharType* kRootPaths[] = {
};
base::FilePath GetTopLevelPath(const base::FilePath& path) {
- std::vector<base::FilePath::StringType> components;
- path.GetComponents(&components);
- return base::FilePath(components[0]);
+ return base::FilePath(path.GetComponents()[0]);
}
bool IsDirectoryEmpty(FileSystemContext* context, const FileSystemURL& url) {
@@ -372,7 +370,7 @@ TEST_F(DraggedFileUtilTest, ReadDirectoryTest) {
entry.name = current.BaseName();
expected_entry_map[entry.name.value()] = entry;
-#if defined(OS_POSIX)
+#if BUILDFLAG(IS_POSIX)
// Creates a symlink for each file/directory.
// They should be ignored by ReadDirectory, so we don't add them
// to expected_entry_map.
diff --git a/chromium/storage/browser/file_system/external_mount_points.cc b/chromium/storage/browser/file_system/external_mount_points.cc
index 6ee8f8aa5f5..7630b664fd4 100644
--- a/chromium/storage/browser/file_system/external_mount_points.cc
+++ b/chromium/storage/browser/file_system/external_mount_points.cc
@@ -160,8 +160,8 @@ bool ExternalMountPoints::CrackVirtualPath(
return false;
// The virtual_path should comprise of <mount_name> and <relative_path> parts.
- std::vector<base::FilePath::StringType> components;
- virtual_path.GetComponents(&components);
+ std::vector<base::FilePath::StringType> components =
+ virtual_path.GetComponents();
if (components.size() < 1)
return false;
diff --git a/chromium/storage/browser/file_system/file_system_context.cc b/chromium/storage/browser/file_system/file_system_context.cc
index 0b2c0fa920b..808295dbe43 100644
--- a/chromium/storage/browser/file_system/file_system_context.cc
+++ b/chromium/storage/browser/file_system/file_system_context.cc
@@ -110,6 +110,7 @@ int FileSystemContext::GetPermissionPolicy(FileSystemType type) {
case kFileSystemTypeArcContent:
case kFileSystemTypeArcDocumentsProvider:
case kFileSystemTypeSmbFs:
+ case kFileSystemTypeFuseBox:
return FILE_PERMISSION_USE_FILE_PERMISSION;
case kFileSystemTypeRestrictedLocal:
@@ -427,10 +428,10 @@ void FileSystemContext::OpenFileSystem(const blink::StorageKey& storage_key,
// Quota manager isn't provided by all tests.
if (quota_manager_proxy()) {
// Ensure default bucket for `storage_key` exists so that Quota API
- // is aware of the usage. Bucket type 'temporary' is used even though the
- // actual storage type of the file system being opened may be different.
- quota_manager_proxy()->GetOrCreateBucket(
- storage_key, kDefaultBucketName, io_task_runner_.get(),
+ // is aware of the usage.
+ quota_manager_proxy()->GetOrCreateBucketDeprecated(
+ storage_key, kDefaultBucketName, FileSystemTypeToQuotaStorageType(type),
+ io_task_runner_.get(),
base::BindOnce(&FileSystemContext::OnGetOrCreateBucket,
weak_factory_.GetWeakPtr(), storage_key, type, mode,
std::move(callback)));
@@ -445,11 +446,6 @@ void FileSystemContext::OnGetOrCreateBucket(
OpenFileSystemMode mode,
OpenFileSystemCallback callback,
QuotaErrorOr<BucketInfo> result) {
- if (!result.ok()) {
- std::move(callback).Run(GURL(), std::string(),
- base::File::FILE_ERROR_FAILED);
- return;
- }
ResolveURLOnOpenFileSystem(storage_key, type, mode, std::move(callback));
}
@@ -467,9 +463,22 @@ void FileSystemContext::ResolveURLOnOpenFileSystem(
return;
}
+ // Bind `this` to the callback to ensure this instance stays alive while the
+ // URL is resolving.
backend->ResolveURL(
CreateCrackedFileSystemURL(storage_key, type, base::FilePath()), mode,
- std::move(callback));
+ base::BindOnce(&FileSystemContext::DidResolveURLOnOpenFileSystem, this,
+ std::move(callback)));
+}
+
+void FileSystemContext::DidResolveURLOnOpenFileSystem(
+ OpenFileSystemCallback callback,
+ const GURL& filesystem_root,
+ const std::string& filesystem_name,
+ base::File::Error error) {
+ DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
+
+ std::move(callback).Run(filesystem_root, filesystem_name, error);
}
void FileSystemContext::ResolveURL(const FileSystemURL& url,
diff --git a/chromium/storage/browser/file_system/file_system_context.h b/chromium/storage/browser/file_system/file_system_context.h
index d92761afb80..15b2f72ef95 100644
--- a/chromium/storage/browser/file_system/file_system_context.h
+++ b/chromium/storage/browser/file_system/file_system_context.h
@@ -414,6 +414,10 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemContext
FileSystemType type,
OpenFileSystemMode mode,
OpenFileSystemCallback callback);
+ void DidResolveURLOnOpenFileSystem(OpenFileSystemCallback callback,
+ const GURL& filesystem_root,
+ const std::string& filesystem_name,
+ base::File::Error error);
// Returns a FileSystemBackend, used only by test code.
SandboxFileSystemBackend* sandbox_backend() const {
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 abf6649cd9c..7268996ae35 100644
--- a/chromium/storage/browser/file_system/file_system_quota_client.cc
+++ b/chromium/storage/browser/file_system/file_system_quota_client.cc
@@ -19,6 +19,7 @@
#include "base/location.h"
#include "base/sequence_checker.h"
#include "base/task/sequenced_task_runner.h"
+#include "components/services/storage/public/cpp/buckets/bucket_locator.h"
#include "storage/browser/file_system/file_system_backend.h"
#include "storage/browser/file_system/file_system_context.h"
#include "storage/common/file_system/file_system_types.h"
@@ -92,16 +93,6 @@ std::vector<blink::StorageKey> GetStorageKeysForTypeOnFileTaskRunner(
return quota_util->GetStorageKeysForTypeOnFileTaskRunner(type);
}
-std::vector<blink::StorageKey> GetStorageKeysForHostOnFileTaskRunner(
- FileSystemContext* context,
- FileSystemType type,
- const std::string& host) {
- FileSystemQuotaUtil* quota_util = context->GetQuotaUtil(type);
- if (!quota_util)
- return {};
- return quota_util->GetStorageKeysForHostOnFileTaskRunner(type, host);
-}
-
blink::mojom::QuotaStatusCode DeleteStorageKeyOnFileTaskRunner(
FileSystemContext* context,
const blink::StorageKey& storage_key,
@@ -139,15 +130,21 @@ FileSystemQuotaClient::~FileSystemQuotaClient() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
-void FileSystemQuotaClient::GetStorageKeyUsage(
- const blink::StorageKey& storage_key,
- blink::mojom::StorageType storage_type,
- GetStorageKeyUsageCallback callback) {
+void FileSystemQuotaClient::GetBucketUsage(const BucketLocator& bucket,
+ GetBucketUsageCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!callback.is_null());
+ // Skip non-default buckets until Storage Buckets are supported for
+ // FileSystem.
+ // TODO(crbug.com/1218100): Integrate with StorageBuckets.
+ if (!bucket.is_default) {
+ std::move(callback).Run(0);
+ return;
+ }
+
base::span<const FileSystemType> types =
- QuotaStorageTypeToFileSystemTypes(storage_type);
+ QuotaStorageTypeToFileSystemTypes(bucket.type);
base::RepeatingCallback<void(int64_t)> barrier =
base::BarrierCallback<int64_t>(
@@ -165,7 +162,8 @@ void FileSystemQuotaClient::GetStorageKeyUsage(
base::BindOnce(
&FileSystemQuotaUtil::GetStorageKeyUsageOnFileTaskRunner,
base::Unretained(quota_util),
- base::RetainedRef(file_system_context_.get()), storage_key, type),
+ base::RetainedRef(file_system_context_.get()), bucket.storage_key,
+ type),
barrier);
} else {
barrier.Run(0);
@@ -197,41 +195,22 @@ void FileSystemQuotaClient::GetStorageKeysForType(
}
}
-void FileSystemQuotaClient::GetStorageKeysForHost(
- blink::mojom::StorageType storage_type,
- const std::string& host,
- GetStorageKeysForHostCallback callback) {
+void FileSystemQuotaClient::DeleteBucketData(
+ const BucketLocator& bucket,
+ DeleteBucketDataCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!callback.is_null());
- base::span<const FileSystemType> types =
- QuotaStorageTypeToFileSystemTypes(storage_type);
-
- base::RepeatingCallback<void(std::vector<blink::StorageKey>)> barrier =
- base::BarrierCallback<std::vector<blink::StorageKey>>(
- types.size(),
- base::BindOnce(&MergeWithoutDuplicates<blink::StorageKey>)
- .Then(std::move(callback)));
-
- for (auto type : types) {
- file_task_runner()->PostTaskAndReplyWithResult(
- FROM_HERE,
- base::BindOnce(&GetStorageKeysForHostOnFileTaskRunner,
- base::RetainedRef(file_system_context_.get()), type,
- host),
- barrier);
+ // Skip non-default buckets until Storage Buckets are supported for
+ // FileSystem.
+ // TODO(crbug.com/1218100): Integrate with StorageBuckets.
+ if (!bucket.is_default) {
+ std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk);
+ return;
}
-}
-
-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());
base::span<const FileSystemType> fs_types =
- QuotaStorageTypeToFileSystemTypes(type);
+ QuotaStorageTypeToFileSystemTypes(bucket.type);
base::RepeatingCallback<void(blink::mojom::QuotaStatusCode)> barrier =
base::BarrierCallback<blink::mojom::QuotaStatusCode>(
@@ -250,7 +229,7 @@ void FileSystemQuotaClient::DeleteStorageKeyData(
FROM_HERE,
base::BindOnce(&DeleteStorageKeyOnFileTaskRunner,
base::RetainedRef(file_system_context_.get()),
- storage_key, fs_type),
+ bucket.storage_key, fs_type),
barrier);
}
}
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 3fe518389f2..8c52337042a 100644
--- a/chromium/storage/browser/file_system/file_system_quota_client.h
+++ b/chromium/storage/browser/file_system/file_system_quota_client.h
@@ -5,14 +5,12 @@
#ifndef STORAGE_BROWSER_FILE_SYSTEM_FILE_SYSTEM_QUOTA_CLIENT_H_
#define STORAGE_BROWSER_FILE_SYSTEM_FILE_SYSTEM_QUOTA_CLIENT_H_
-#include <string>
-
#include "base/component_export.h"
#include "base/memory/raw_ptr.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 "components/services/storage/public/mojom/quota_client.mojom.h"
#include "storage/browser/file_system/file_system_quota_util.h"
#include "storage/browser/quota/quota_client_type.h"
#include "storage/common/file_system/file_system_types.h"
@@ -22,18 +20,15 @@ namespace base {
class SequencedTaskRunner;
}
-namespace blink {
-class StorageKey;
-} // namespace blink
-
namespace storage {
class FileSystemContext;
+struct BucketLocator;
// 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 StorageKeyQuotaClient {
+ : public mojom::QuotaClient {
public:
explicit FileSystemQuotaClient(FileSystemContext* file_system_context);
~FileSystemQuotaClient() override;
@@ -41,18 +36,13 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemQuotaClient
FileSystemQuotaClient(const FileSystemQuotaClient&) = delete;
FileSystemQuotaClient& operator=(const FileSystemQuotaClient&) = delete;
- // QuotaClient methods.
- void GetStorageKeyUsage(const blink::StorageKey& storage_key,
- blink::mojom::StorageType type,
- GetStorageKeyUsageCallback callback) override;
+ // mojom::QuotaClient methods.
+ void GetBucketUsage(const BucketLocator& bucket,
+ GetBucketUsageCallback 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 DeleteBucketData(const BucketLocator& bucket,
+ DeleteBucketDataCallback callback) override;
void PerformStorageCleanup(blink::mojom::StorageType type,
PerformStorageCleanupCallback callback) override;
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 f8c7fee5bb4..b7bb5a5caec 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
@@ -14,14 +14,20 @@
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
+#include "base/test/test_future.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "components/services/storage/public/cpp/buckets/bucket_locator.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.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.h"
+#include "storage/browser/test/mock_quota_manager_proxy.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"
@@ -63,8 +69,16 @@ class FileSystemQuotaClientTest : public testing::TestWithParam<bool> {
blink::features::kPersistentQuotaIsTemporaryQuota);
}
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
+
+ quota_manager_ = base::MakeRefCounted<MockQuotaManager>(
+ /*is_incognito_=*/false, data_dir_.GetPath(),
+ base::ThreadTaskRunnerHandle::Get(),
+ /*special_storage_policy=*/nullptr);
+ quota_manager_proxy_ = base::MakeRefCounted<storage::MockQuotaManagerProxy>(
+ quota_manager_.get(), base::ThreadTaskRunnerHandle::Get());
+
file_system_context_ = CreateFileSystemContextForTesting(
- /*quota_manager_proxy=*/nullptr, data_dir_.GetPath());
+ quota_manager_proxy_, data_dir_.GetPath());
}
bool persistent_quota_is_temporary_quota() const { return GetParam(); }
@@ -82,19 +96,16 @@ class FileSystemQuotaClientTest : public testing::TestWithParam<bool> {
return file_system_context_.get();
}
- 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()));
+ void GetBucketUsageAsync(storage::mojom::QuotaClient& quota_client,
+ const BucketLocator& bucket) {
+ quota_client.GetBucketUsage(
+ bucket, base::BindOnce(&FileSystemQuotaClientTest::OnGetUsage,
+ weak_factory_.GetWeakPtr()));
}
- int64_t GetStorageKeyUsage(storage::mojom::QuotaClient& quota_client,
- const std::string& origin_url,
- StorageType type) {
- GetStorageKeyUsageAsync(quota_client, origin_url, type);
+ int64_t GetBucketUsage(storage::mojom::QuotaClient& quota_client,
+ const BucketLocator& bucket) {
+ GetBucketUsageAsync(quota_client, bucket);
base::RunLoop().RunUntilIdle();
return usage_;
}
@@ -110,27 +121,11 @@ class FileSystemQuotaClientTest : public testing::TestWithParam<bool> {
return storage_keys_;
}
- const std::vector<StorageKey>& GetStorageKeysForHost(
- storage::mojom::QuotaClient& quota_client,
- StorageType type,
- const std::string& host) {
- storage_keys_.clear();
- quota_client.GetStorageKeysForHost(
- type, host,
- base::BindOnce(&FileSystemQuotaClientTest::OnGetStorageKeys,
- weak_factory_.GetWeakPtr()));
- base::RunLoop().RunUntilIdle();
- return storage_keys_;
- }
-
- 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()));
+ void RunAdditionalBucketUsageTask(storage::mojom::QuotaClient& quota_client,
+ const BucketLocator& bucket) {
+ quota_client.GetBucketUsage(
+ bucket, base::BindOnce(&FileSystemQuotaClientTest::OnGetAdditionalUsage,
+ weak_factory_.GetWeakPtr()));
}
bool CreateFileSystemDirectory(const base::FilePath& file_path,
@@ -171,6 +166,11 @@ class FileSystemQuotaClientTest : public testing::TestWithParam<bool> {
for (const TestFile& file : files) {
base::FilePath path = base::FilePath().AppendASCII(file.name);
if (file.isDirectory) {
+ auto bucket =
+ GetOrCreateBucket(file.origin_url, kDefaultBucketName,
+ FileSystemTypeToQuotaStorageType(file.type));
+ quota_manager_->SetQuota(bucket.storage_key, bucket.type,
+ 1024 * 1024 * 100);
ASSERT_TRUE(
CreateFileSystemDirectory(path, file.origin_url, file.type));
if (path.empty()) {
@@ -179,8 +179,7 @@ class FileSystemQuotaClientTest : public testing::TestWithParam<bool> {
// 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.
- GetStorageKeyUsage(quota_client, file.origin_url,
- FileSystemTypeToQuotaStorageType(file.type));
+ GetBucketUsage(quota_client, bucket);
}
} else {
ASSERT_TRUE(
@@ -209,18 +208,38 @@ class FileSystemQuotaClientTest : public testing::TestWithParam<bool> {
return file_paths_cost;
}
- void DeleteStorageKeyData(FileSystemQuotaClient* quota_client,
- const std::string& origin,
- StorageType type) {
- deletion_status_ = blink::mojom::QuotaStatusCode::kUnknown;
- quota_client->DeleteStorageKeyData(
- StorageKey::CreateFromStringForTesting(origin), type,
- base::BindOnce(&FileSystemQuotaClientTest::OnDeleteStorageKey,
- weak_factory_.GetWeakPtr()));
+ void DeleteBucketData(FileSystemQuotaClient* quota_client,
+ const BucketLocator& bucket) {
+ base::test::TestFuture<blink::mojom::QuotaStatusCode> future;
+ quota_client->DeleteBucketData(bucket, future.GetCallback());
+ ASSERT_EQ(future.Get(), blink::mojom::QuotaStatusCode::kOk);
+ }
+
+ BucketLocator GetOrCreateBucket(const std::string& origin,
+ const std::string& name,
+ StorageType type) {
+ base::test::TestFuture<storage::QuotaErrorOr<storage::BucketInfo>> future;
+ quota_manager_->GetOrCreateBucketDeprecated(
+ blink::StorageKey::CreateFromStringForTesting(origin), name, type,
+ future.GetCallback());
+ auto bucket = future.Take();
+ EXPECT_TRUE(bucket.ok());
+ return bucket->ToBucketLocator();
+ }
+
+ BucketLocator GetBucket(const std::string& origin,
+ const std::string& name,
+ StorageType type) {
+ base::test::TestFuture<storage::QuotaErrorOr<storage::BucketInfo>> future;
+ quota_manager_->GetBucket(
+ blink::StorageKey::CreateFromStringForTesting(origin), name, type,
+ future.GetCallback());
+ auto bucket = future.Take();
+ EXPECT_TRUE(bucket.ok());
+ return bucket->ToBucketLocator();
}
int64_t usage() const { return usage_; }
- blink::mojom::QuotaStatusCode status() { return deletion_status_; }
int additional_callback_count() const { return additional_callback_count_; }
void set_additional_callback_count(int count) {
additional_callback_count_ = count;
@@ -237,26 +256,24 @@ class FileSystemQuotaClientTest : public testing::TestWithParam<bool> {
++additional_callback_count_;
}
- void OnDeleteStorageKey(blink::mojom::QuotaStatusCode status) {
- deletion_status_ = status;
- }
-
base::test::ScopedFeatureList feature_list_;
base::ScopedTempDir data_dir_;
base::test::TaskEnvironment task_environment_;
scoped_refptr<FileSystemContext> file_system_context_;
+ scoped_refptr<MockQuotaManager> quota_manager_;
+ scoped_refptr<storage::MockQuotaManagerProxy> quota_manager_proxy_;
+
int64_t usage_ = 0;
int additional_callback_count_ = 0;
std::vector<StorageKey> storage_keys_;
- blink::mojom::QuotaStatusCode deletion_status_ =
- blink::mojom::QuotaStatusCode::kUnknown;
base::WeakPtrFactory<FileSystemQuotaClientTest> weak_factory_{this};
};
TEST_P(FileSystemQuotaClientTest, NoFileSystemTest) {
FileSystemQuotaClient quota_client(GetFileSystemContext());
- EXPECT_EQ(0, GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary));
+ auto bucket = GetOrCreateBucket(kDummyURL1, kDefaultBucketName, kTemporary);
+ EXPECT_EQ(0, GetBucketUsage(quota_client, bucket));
}
TEST_P(FileSystemQuotaClientTest, NoFileTest) {
@@ -265,13 +282,23 @@ TEST_P(FileSystemQuotaClientTest, NoFileTest) {
InitializeOriginFiles(quota_client,
{{true, "", 0, kDummyURL1, kFileSystemTypeTemporary}});
+ auto bucket = GetOrCreateBucket(kDummyURL1, kDefaultBucketName, kTemporary);
for (int i = 0; i < 2; i++) {
- EXPECT_EQ(0, GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary));
+ EXPECT_EQ(0, GetBucketUsage(quota_client, bucket));
}
}
+TEST_P(FileSystemQuotaClientTest, NonDefaultBucket) {
+ FileSystemQuotaClient quota_client(GetFileSystemContext());
+ auto bucket = GetOrCreateBucket(kDummyURL1, "logs_bucket", kTemporary);
+ ASSERT_FALSE(bucket.is_default);
+ EXPECT_EQ(0, GetBucketUsage(quota_client, bucket));
+ DeleteBucketData(&quota_client, bucket);
+}
+
TEST_P(FileSystemQuotaClientTest, OneFileTest) {
FileSystemQuotaClient quota_client(GetFileSystemContext());
+
const std::vector<TestFile> kFiles = {
{true, "", 0, kDummyURL1, kFileSystemTypeTemporary},
{false, "foo", 4921, kDummyURL1, kFileSystemTypeTemporary},
@@ -280,9 +307,9 @@ TEST_P(FileSystemQuotaClientTest, OneFileTest) {
const int64_t file_paths_cost = ComputeFilePathsCostForOriginAndType(
kFiles, kDummyURL1, kFileSystemTypeTemporary);
+ auto bucket = GetBucket(kDummyURL1, kDefaultBucketName, kTemporary);
for (int i = 0; i < 2; i++) {
- EXPECT_EQ(4921 + file_paths_cost,
- GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary));
+ EXPECT_EQ(4921 + file_paths_cost, GetBucketUsage(quota_client, bucket));
}
}
@@ -297,9 +324,10 @@ TEST_P(FileSystemQuotaClientTest, TwoFilesTest) {
const int64_t file_paths_cost = ComputeFilePathsCostForOriginAndType(
kFiles, kDummyURL1, kFileSystemTypeTemporary);
+ auto bucket = GetBucket(kDummyURL1, kDefaultBucketName, kTemporary);
for (int i = 0; i < 2; i++) {
EXPECT_EQ(10310 + 41 + file_paths_cost,
- GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary));
+ GetBucketUsage(quota_client, bucket));
}
}
@@ -315,9 +343,9 @@ TEST_P(FileSystemQuotaClientTest, EmptyFilesTest) {
const int64_t file_paths_cost = ComputeFilePathsCostForOriginAndType(
kFiles, kDummyURL1, kFileSystemTypeTemporary);
+ auto bucket = GetBucket(kDummyURL1, kDefaultBucketName, kTemporary);
for (int i = 0; i < 2; i++) {
- EXPECT_EQ(file_paths_cost,
- GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary));
+ EXPECT_EQ(file_paths_cost, GetBucketUsage(quota_client, bucket));
}
}
@@ -333,9 +361,10 @@ TEST_P(FileSystemQuotaClientTest, SubDirectoryTest) {
const int64_t file_paths_cost = ComputeFilePathsCostForOriginAndType(
kFiles, kDummyURL1, kFileSystemTypeTemporary);
+ auto bucket = GetBucket(kDummyURL1, kDefaultBucketName, kTemporary);
for (int i = 0; i < 2; i++) {
EXPECT_EQ(11921 + 4814 + file_paths_cost,
- GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary));
+ GetBucketUsage(quota_client, bucket));
}
}
@@ -361,14 +390,17 @@ TEST_P(FileSystemQuotaClientTest, MultiTypeTest) {
for (int i = 0; i < 2; i++) {
if (persistent_quota_is_temporary_quota()) {
+ auto bucket = GetBucket(kDummyURL1, kDefaultBucketName, kTemporary);
EXPECT_EQ(133 + 14 + file_paths_cost_temporary + 193 + 9 +
file_paths_cost_persistent,
- GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary));
+ GetBucketUsage(quota_client, bucket));
} else {
+ auto bucket_temp = GetBucket(kDummyURL1, kDefaultBucketName, kTemporary);
+ auto bucket_perm = GetBucket(kDummyURL1, kDefaultBucketName, kPersistent);
EXPECT_EQ(133 + 14 + file_paths_cost_temporary,
- GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary));
+ GetBucketUsage(quota_client, bucket_temp));
EXPECT_EQ(193 + 9 + file_paths_cost_persistent,
- GetStorageKeyUsage(quota_client, kDummyURL1, kPersistent));
+ GetBucketUsage(quota_client, bucket_perm));
}
}
}
@@ -409,21 +441,29 @@ TEST_P(FileSystemQuotaClientTest, MultiDomainTest) {
for (int i = 0; i < 2; i++) {
if (persistent_quota_is_temporary_quota()) {
+ auto bucket1 = GetBucket(kDummyURL1, kDefaultBucketName, kTemporary);
+ auto bucket2 = GetBucket(kDummyURL2, kDefaultBucketName, kTemporary);
EXPECT_EQ(1331 + 134 + file_paths_cost_temporary1 + 1903 + 19 +
file_paths_cost_persistent1,
- GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary));
+ GetBucketUsage(quota_client, bucket1));
EXPECT_EQ(1319 + 113 + file_paths_cost_temporary2 + 2013 + 18 +
file_paths_cost_persistent2,
- GetStorageKeyUsage(quota_client, kDummyURL2, kTemporary));
+ GetBucketUsage(quota_client, bucket2));
} else {
+ auto bucket1_temp = GetBucket(kDummyURL1, kDefaultBucketName, kTemporary);
+ auto bucket1_perm =
+ GetBucket(kDummyURL1, kDefaultBucketName, kPersistent);
+ auto bucket2_temp = GetBucket(kDummyURL2, kDefaultBucketName, kTemporary);
+ auto bucket2_perm =
+ GetBucket(kDummyURL2, kDefaultBucketName, kPersistent);
EXPECT_EQ(1331 + 134 + file_paths_cost_temporary1,
- GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary));
+ GetBucketUsage(quota_client, bucket1_temp));
EXPECT_EQ(1903 + 19 + file_paths_cost_persistent1,
- GetStorageKeyUsage(quota_client, kDummyURL1, kPersistent));
+ GetBucketUsage(quota_client, bucket1_perm));
EXPECT_EQ(1319 + 113 + file_paths_cost_temporary2,
- GetStorageKeyUsage(quota_client, kDummyURL2, kTemporary));
+ GetBucketUsage(quota_client, bucket2_temp));
EXPECT_EQ(2013 + 18 + file_paths_cost_persistent2,
- GetStorageKeyUsage(quota_client, kDummyURL2, kPersistent));
+ GetBucketUsage(quota_client, bucket2_perm));
}
}
}
@@ -441,18 +481,19 @@ TEST_P(FileSystemQuotaClientTest, GetUsage_MultipleTasks) {
// Dispatching three GetUsage tasks.
set_additional_callback_count(0);
- GetStorageKeyUsageAsync(quota_client, kDummyURL1, kTemporary);
- RunAdditionalStorageKeyUsageTask(quota_client, kDummyURL1, kTemporary);
- RunAdditionalStorageKeyUsageTask(quota_client, kDummyURL1, kTemporary);
+ auto bucket = GetBucket(kDummyURL1, kDefaultBucketName, kTemporary);
+ GetBucketUsageAsync(quota_client, bucket);
+ RunAdditionalBucketUsageTask(quota_client, bucket);
+ RunAdditionalBucketUsageTask(quota_client, bucket);
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);
- RunAdditionalStorageKeyUsageTask(quota_client, kDummyURL1, kTemporary);
- GetStorageKeyUsageAsync(quota_client, kDummyURL1, kTemporary);
- RunAdditionalStorageKeyUsageTask(quota_client, kDummyURL1, kTemporary);
+ RunAdditionalBucketUsageTask(quota_client, bucket);
+ GetBucketUsageAsync(quota_client, bucket);
+ RunAdditionalBucketUsageTask(quota_client, bucket);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(11 + 22 + file_paths_cost, usage());
EXPECT_EQ(2, additional_callback_count());
@@ -481,38 +522,6 @@ TEST_P(FileSystemQuotaClientTest, GetStorageKeysForType) {
}
}
-TEST_P(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/";
- InitializeOriginFiles(quota_client,
- {
- {true, "", 0, kURL1, kFileSystemTypeTemporary},
- {true, "", 0, kURL2, kFileSystemTypeTemporary},
- {true, "", 0, kURL3, kFileSystemTypeTemporary},
- {true, "", 0, kURL4, kFileSystemTypeTemporary},
- {true, "", 0, kURL5, kFileSystemTypePersistent},
- });
-
- if (persistent_quota_is_temporary_quota()) {
- EXPECT_THAT(GetStorageKeysForHost(quota_client, kTemporary, "foo.com"),
- testing::UnorderedElementsAre(
- StorageKey::CreateFromStringForTesting(kURL1),
- StorageKey::CreateFromStringForTesting(kURL2),
- StorageKey::CreateFromStringForTesting(kURL3),
- StorageKey::CreateFromStringForTesting(kURL5)));
- } else {
- EXPECT_THAT(GetStorageKeysForHost(quota_client, kTemporary, "foo.com"),
- testing::UnorderedElementsAre(
- StorageKey::CreateFromStringForTesting(kURL1),
- StorageKey::CreateFromStringForTesting(kURL2),
- StorageKey::CreateFromStringForTesting(kURL3)));
- }
-}
-
TEST_P(FileSystemQuotaClientTest, DeleteOriginTest) {
FileSystemQuotaClient quota_client(GetFileSystemContext());
const std::vector<TestFile> kFiles = {
@@ -551,43 +560,58 @@ TEST_P(FileSystemQuotaClientTest, DeleteOriginTest) {
ComputeFilePathsCostForOriginAndType(kFiles, "https://bar.com/",
kFileSystemTypePersistent);
- DeleteStorageKeyData(&quota_client, "http://foo.com/", kTemporary);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, status());
+ auto foo_temp_bucket =
+ GetBucket("http://foo.com/", kDefaultBucketName, kTemporary);
+ DeleteBucketData(&quota_client, foo_temp_bucket);
if (!persistent_quota_is_temporary_quota()) {
- DeleteStorageKeyData(&quota_client, "http://bar.com/", kPersistent);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, status());
+ auto foo_perm_bucket =
+ GetBucket("http://bar.com/", kDefaultBucketName, kPersistent);
+ DeleteBucketData(&quota_client, foo_perm_bucket);
}
- DeleteStorageKeyData(&quota_client, "http://buz.com/", kTemporary);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, status());
+ auto buz_temp_bucket =
+ GetOrCreateBucket("http://buz.com/", kDefaultBucketName, kTemporary);
+ DeleteBucketData(&quota_client, buz_temp_bucket);
- EXPECT_EQ(0, GetStorageKeyUsage(quota_client, "http://foo.com/", kTemporary));
- EXPECT_EQ(0, GetStorageKeyUsage(quota_client, "http://buz.com/", kTemporary));
+ EXPECT_EQ(0, GetBucketUsage(quota_client, foo_temp_bucket));
+ EXPECT_EQ(0, GetBucketUsage(quota_client, buz_temp_bucket));
+
+ auto foo_https_temp_bucket =
+ GetBucket("https://foo.com/", kDefaultBucketName, kTemporary);
EXPECT_EQ(2 + file_paths_cost_temporary_foo_https,
- GetStorageKeyUsage(quota_client, "https://foo.com/", kTemporary));
+ GetBucketUsage(quota_client, foo_https_temp_bucket));
+
+ auto bar_temp_bucket =
+ GetBucket("http://bar.com/", kDefaultBucketName, kTemporary);
EXPECT_EQ(8 + file_paths_cost_temporary_bar +
(persistent_quota_is_temporary_quota()
? 16 + file_paths_cost_persistent_bar
: 0),
- GetStorageKeyUsage(quota_client, "http://bar.com/", kTemporary));
+ GetBucketUsage(quota_client, bar_temp_bucket));
+
+ auto bar_https_temp_bucket =
+ GetBucket("https://bar.com/", kDefaultBucketName, kTemporary);
EXPECT_EQ(64 + file_paths_cost_temporary_bar_https +
(persistent_quota_is_temporary_quota()
? 32 + file_paths_cost_persistent_bar_https
: 0),
- GetStorageKeyUsage(quota_client, "https://bar.com/", kTemporary));
+ GetBucketUsage(quota_client, bar_https_temp_bucket));
if (!persistent_quota_is_temporary_quota()) {
- EXPECT_EQ(0,
- GetStorageKeyUsage(quota_client, "http://bar.com/", kPersistent));
+ auto bar_perm_bucket =
+ GetBucket("http://bar.com/", kDefaultBucketName, kPersistent);
+ EXPECT_EQ(0, GetBucketUsage(quota_client, bar_perm_bucket));
+
+ auto foo_perm_bucket =
+ GetBucket("http://foo.com/", kDefaultBucketName, kPersistent);
EXPECT_EQ(4 + file_paths_cost_persistent_foo,
- GetStorageKeyUsage(quota_client, "http://foo.com/", kPersistent));
- EXPECT_EQ(
- 32 + file_paths_cost_persistent_bar_https,
- GetStorageKeyUsage(quota_client, "https://bar.com/", kPersistent));
+ GetBucketUsage(quota_client, foo_perm_bucket));
+
+ auto bar_https_perm_bucket =
+ GetBucket("https://bar.com/", kDefaultBucketName, kPersistent);
+ EXPECT_EQ(32 + file_paths_cost_persistent_bar_https,
+ GetBucketUsage(quota_client, bar_https_perm_bucket));
}
}
diff --git a/chromium/storage/browser/file_system/file_system_quota_util.h b/chromium/storage/browser/file_system/file_system_quota_util.h
index d329f63de74..dd34c1e1ee0 100644
--- a/chromium/storage/browser/file_system/file_system_quota_util.h
+++ b/chromium/storage/browser/file_system/file_system_quota_util.h
@@ -7,7 +7,6 @@
#include <stdint.h>
-#include <string>
#include <vector>
#include "base/component_export.h"
@@ -48,10 +47,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemQuotaUtil {
virtual std::vector<blink::StorageKey> GetStorageKeysForTypeOnFileTaskRunner(
FileSystemType type) = 0;
- virtual std::vector<blink::StorageKey> GetStorageKeysForHostOnFileTaskRunner(
- FileSystemType type,
- const std::string& host) = 0;
-
// Returns the amount of data used for the `storage_key` for usage tracking.
virtual int64_t GetStorageKeyUsageOnFileTaskRunner(
FileSystemContext* file_system_context,
diff --git a/chromium/storage/browser/file_system/file_system_url.cc b/chromium/storage/browser/file_system/file_system_url.cc
index 1c164adb270..ec5efe42a13 100644
--- a/chromium/storage/browser/file_system/file_system_url.cc
+++ b/chromium/storage/browser/file_system/file_system_url.cc
@@ -12,6 +12,7 @@
#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 "url/gurl.h"
#include "url/origin.h"
namespace storage {
@@ -69,10 +70,9 @@ FileSystemURL::FileSystemURL(const GURL& url,
GURL origin_url;
// URL should be able to be parsed and the parsed origin should match the
// StorageKey's origin member.
- is_valid_ =
- ParseFileSystemSchemeURL(url, &origin_url, &mount_type_,
- &virtual_path_) &&
- storage_key.origin().IsSameOriginWith(url::Origin::Create(origin_url));
+ is_valid_ = ParseFileSystemSchemeURL(url, &origin_url, &mount_type_,
+ &virtual_path_) &&
+ storage_key.origin().IsSameOriginWith(origin_url);
storage_key_ = storage_key;
path_ = virtual_path_;
type_ = mount_type_;
@@ -113,11 +113,12 @@ GURL FileSystemURL::ToGURL() const {
if (!is_valid_)
return GURL();
- std::string url =
- GetFileSystemRootURI(storage_key_.origin().GetURL(), mount_type_).spec();
- if (url.empty())
+ GURL url = GetFileSystemRootURI(storage_key_.origin().GetURL(), mount_type_);
+ if (!url.is_valid())
return GURL();
+ std::string url_string = url.spec();
+
// Exactly match with DOMFileSystemBase::createFileSystemURL()'s encoding
// behavior, where the path is escaped by KURL::encodeWithURLEscapeSequences
// which is essentially encodeURIComponent except '/'.
@@ -125,10 +126,10 @@ GURL FileSystemURL::ToGURL() const {
virtual_path_.NormalizePathSeparatorsTo('/').AsUTF8Unsafe(),
false /* use_plus */);
base::ReplaceSubstringsAfterOffset(&escaped, 0, "%2F", "/");
- url.append(escaped);
+ url_string.append(escaped);
// Build nested GURL.
- return GURL(url);
+ return GURL(url_string);
}
std::string FileSystemURL::DebugString() const {
diff --git a/chromium/storage/browser/file_system/file_system_url.h b/chromium/storage/browser/file_system/file_system_url.h
index e29a3306cfc..65441a4977f 100644
--- a/chromium/storage/browser/file_system/file_system_url.h
+++ b/chromium/storage/browser/file_system/file_system_url.h
@@ -10,8 +10,10 @@
#include "base/component_export.h"
#include "base/files/file_path.h"
+#include "components/services/storage/public/cpp/buckets/bucket_locator.h"
#include "storage/common/file_system/file_system_mount_option.h"
#include "storage/common/file_system/file_system_types.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "url/gurl.h"
@@ -29,6 +31,7 @@ namespace storage {
// virtual_path() returns 'foo/bar',
// type() returns the same value as mount_type(),
// path() returns the same value as virtual_path(),
+// bucket() returns an empty string unless explicitly set with SetBucket(),
//
// All other accessors return empty or invalid value.
//
@@ -133,6 +136,12 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemURL {
const FileSystemMountOption& mount_option() const { return mount_option_; }
+ // Returns the BucketLocator for this URL's partitioned file location. In
+ // the majority of cases, this will not be populated and the default storage
+ // bucket will be used.
+ const absl::optional<BucketLocator>& bucket() const { return bucket_; }
+ void SetBucket(const BucketLocator& bucket) { bucket_ = bucket; }
+
// Returns the formatted URL of this instance.
GURL ToGURL() const;
@@ -191,6 +200,9 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemURL {
base::FilePath path_;
std::string filesystem_id_;
FileSystemMountOption mount_option_;
+
+ // Values that must be explicitly set.
+ absl::optional<BucketLocator> bucket_;
};
using FileSystemURLSet = std::set<FileSystemURL, FileSystemURL::Comparator>;
diff --git a/chromium/storage/browser/file_system/isolated_context.cc b/chromium/storage/browser/file_system/isolated_context.cc
index 2ab691523aa..f862b8eb708 100644
--- a/chromium/storage/browser/file_system/isolated_context.cc
+++ b/chromium/storage/browser/file_system/isolated_context.cc
@@ -351,8 +351,8 @@ bool IsolatedContext::CrackVirtualPath(
*mount_option = FileSystemMountOption();
// The virtual_path should comprise <id_or_name> and <relative_path> parts.
- std::vector<base::FilePath::StringType> components;
- virtual_path.GetComponents(&components);
+ std::vector<base::FilePath::StringType> components =
+ virtual_path.GetComponents();
if (components.size() < 1)
return false;
auto component_iter = components.begin();
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 20c6378fe3a..90f910646d7 100644
--- a/chromium/storage/browser/file_system/local_file_util_unittest.cc
+++ b/chromium/storage/browser/file_system/local_file_util_unittest.cc
@@ -136,7 +136,7 @@ TEST_F(LocalFileUtilTest, CreateAndClose) {
}
// base::CreateSymbolicLink is supported on most POSIX, but not on Fuchsia.
-#if defined(OS_POSIX)
+#if BUILDFLAG(IS_POSIX)
TEST_F(LocalFileUtilTest, CreateFailForSymlink) {
// Create symlink target file.
const char* target_name = "symlink_target";
diff --git a/chromium/storage/browser/file_system/native_file_util.cc b/chromium/storage/browser/file_system/native_file_util.cc
index 106a742df16..4d0f7df58e5 100644
--- a/chromium/storage/browser/file_system/native_file_util.cc
+++ b/chromium/storage/browser/file_system/native_file_util.cc
@@ -16,9 +16,9 @@
#include "storage/browser/file_system/file_system_url.h"
#include "storage/common/file_system/file_system_mount_option.h"
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
#include "windows.h"
-#endif // defined(OS_WIN)
+#endif // BUILDFLAG(IS_WIN)
namespace storage {
@@ -270,7 +270,7 @@ base::File::Error NativeFileUtil::CopyOrMoveFile(
if (error == base::File::FILE_OK) {
if (info.is_directory != src_is_directory)
return base::File::FILE_ERROR_INVALID_OPERATION;
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
// Overwriting an empty directory with another directory isn't supported
// natively on Windows, so treat this an unsupported. A higher layer is
// responsible for handling it.
@@ -288,7 +288,7 @@ base::File::Error NativeFileUtil::CopyOrMoveFile(
// Cache permissions of dest file before copy/move overwrites the file.
bool should_retain_file_permissions = false;
-#if defined(OS_POSIX)
+#if BUILDFLAG(IS_POSIX)
int dest_mode;
if (options.Has(FileSystemOperation::CopyOrMoveOption::
kPreserveDestinationPermissions)) {
@@ -296,14 +296,14 @@ base::File::Error NativeFileUtil::CopyOrMoveFile(
should_retain_file_permissions =
base::GetPosixFilePermissions(dest_path, &dest_mode);
}
-#elif defined(OS_WIN)
+#elif BUILDFLAG(IS_WIN)
DWORD dest_attributes;
if (options.Has(FileSystemOperation::CopyOrMoveOption::
kPreserveDestinationPermissions)) {
dest_attributes = ::GetFileAttributes(dest_path.value().c_str());
should_retain_file_permissions = dest_attributes != INVALID_FILE_ATTRIBUTES;
}
-#endif // defined(OS_POSIX)
+#endif // BUILDFLAG(IS_POSIX)
switch (mode) {
case COPY_NOSYNC:
@@ -328,11 +328,11 @@ base::File::Error NativeFileUtil::CopyOrMoveFile(
}
if (should_retain_file_permissions) {
-#if defined(OS_POSIX)
+#if BUILDFLAG(IS_POSIX)
base::SetPosixFilePermissions(dest_path, dest_mode);
-#elif defined(OS_WIN)
+#elif BUILDFLAG(IS_WIN)
::SetFileAttributes(dest_path.value().c_str(), dest_attributes);
-#endif // defined(OS_POSIX)
+#endif // BUILDFLAG(IS_POSIX)
}
return base::File::FILE_OK;
diff --git a/chromium/storage/browser/file_system/native_file_util_unittest.cc b/chromium/storage/browser/file_system/native_file_util_unittest.cc
index 16a87636fa5..602751dcb45 100644
--- a/chromium/storage/browser/file_system/native_file_util_unittest.cc
+++ b/chromium/storage/browser/file_system/native_file_util_unittest.cc
@@ -15,9 +15,9 @@
#include "storage/browser/file_system/native_file_util.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
#include "windows.h"
-#endif // defined(OS_WIN)
+#endif // BUILDFLAG(IS_WIN)
namespace storage {
namespace {
@@ -53,7 +53,7 @@ class NativeFileUtilTest : public testing::Test {
return info.size;
}
-#if defined(OS_POSIX)
+#if BUILDFLAG(IS_POSIX)
void ExpectFileHasPermissionsPosix(base::FilePath file, int expected_mode) {
base::File::Info file_info;
int mode;
@@ -62,9 +62,9 @@ class NativeFileUtilTest : public testing::Test {
EXPECT_TRUE(base::GetPosixFilePermissions(file, &mode));
EXPECT_EQ(mode, expected_mode);
}
-#endif // defined(OS_POSIX)
+#endif // BUILDFLAG(IS_POSIX)
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
void ExpectFileHasPermissionsWin(base::FilePath file,
DWORD expected_attributes) {
base::File::Info file_info;
@@ -75,7 +75,7 @@ class NativeFileUtilTest : public testing::Test {
EXPECT_NE(attributes, INVALID_FILE_ATTRIBUTES);
EXPECT_EQ(attributes, expected_attributes);
}
-#endif // defined(OS_WIN)
+#endif // BUILDFLAG(IS_WIN)
private:
base::ScopedTempDir data_dir_;
@@ -362,7 +362,7 @@ TEST_F(NativeFileUtilTest, MoveFile) {
NativeFileUtil::CopyOrMoveFile(
dir, to_file, FileSystemOperation::CopyOrMoveOptionSet(), move));
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
// Source is a directory, destination is a directory.
EXPECT_EQ(base::File::FILE_ERROR_NOT_A_FILE,
NativeFileUtil::CopyOrMoveFile(
@@ -422,7 +422,7 @@ TEST_F(NativeFileUtilTest, MoveFile_Directory) {
EXPECT_EQ(1020, GetSize(to_file));
}
-#if !defined(OS_WIN)
+#if !BUILDFLAG(IS_WIN)
TEST_F(NativeFileUtilTest, MoveFile_OverwriteEmptyDirectory) {
base::FilePath from_directory = Path("fromdirectory");
base::FilePath to_directory = Path("todirectory");
@@ -507,7 +507,7 @@ TEST_F(NativeFileUtilTest, PreserveLastModified) {
EXPECT_EQ(file_info1.last_modified, file_info2.last_modified);
}
-#if defined(OS_POSIX) || defined(OS_WIN)
+#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_WIN)
TEST_F(NativeFileUtilTest, PreserveDestinationPermissions) {
// Ensure both the src and dest files exist.
base::FilePath to_file = Path("to-file");
@@ -523,25 +523,25 @@ TEST_F(NativeFileUtilTest, PreserveDestinationPermissions) {
ASSERT_TRUE(created);
EXPECT_TRUE(FileExists(from_file));
-#if defined(OS_POSIX)
+#if BUILDFLAG(IS_POSIX)
int dest_initial_mode;
ASSERT_TRUE(base::GetPosixFilePermissions(to_file, &dest_initial_mode));
-#elif defined(OS_WIN)
+#elif BUILDFLAG(IS_WIN)
DWORD dest_initial_attributes = ::GetFileAttributes(to_file.value().c_str());
ASSERT_NE(dest_initial_attributes, INVALID_FILE_ATTRIBUTES);
-#endif // defined(OS_POSIX)
+#endif // BUILDFLAG(IS_POSIX)
// Give dest file some distinct permissions it didn't have before.
-#if defined(OS_POSIX)
+#if BUILDFLAG(IS_POSIX)
int old_dest_mode = dest_initial_mode | S_IRGRP | S_IXOTH;
EXPECT_NE(old_dest_mode, dest_initial_mode);
EXPECT_TRUE(base::SetPosixFilePermissions(to_file, old_dest_mode));
-#elif defined(OS_WIN)
+#elif BUILDFLAG(IS_WIN)
DWORD old_dest_attributes = FILE_ATTRIBUTE_NORMAL;
EXPECT_NE(old_dest_attributes, dest_initial_attributes);
EXPECT_TRUE(
::SetFileAttributes(to_file.value().c_str(), old_dest_attributes));
-#endif // defined(OS_POSIX)
+#endif // BUILDFLAG(IS_POSIX)
// Test for copy (nosync).
ASSERT_EQ(base::File::FILE_OK,
@@ -550,11 +550,11 @@ TEST_F(NativeFileUtilTest, PreserveDestinationPermissions) {
CopyOrMoveOptionSet(
CopyOrMoveOption::kPreserveDestinationPermissions),
NativeFileUtil::COPY_NOSYNC));
-#if defined(OS_POSIX)
+#if BUILDFLAG(IS_POSIX)
ExpectFileHasPermissionsPosix(to_file, old_dest_mode);
-#elif defined(OS_WIN)
+#elif BUILDFLAG(IS_WIN)
ExpectFileHasPermissionsWin(to_file, old_dest_attributes);
-#endif // defined(OS_POSIX)
+#endif // BUILDFLAG(IS_POSIX)
// Test for copy (sync).
ASSERT_EQ(base::File::FILE_OK,
@@ -563,11 +563,11 @@ TEST_F(NativeFileUtilTest, PreserveDestinationPermissions) {
CopyOrMoveOptionSet(
CopyOrMoveOption::kPreserveDestinationPermissions),
NativeFileUtil::COPY_SYNC));
-#if defined(OS_POSIX)
+#if BUILDFLAG(IS_POSIX)
ExpectFileHasPermissionsPosix(to_file, old_dest_mode);
-#elif defined(OS_WIN)
+#elif BUILDFLAG(IS_WIN)
ExpectFileHasPermissionsWin(to_file, old_dest_attributes);
-#endif // defined(OS_POSIX)
+#endif // BUILDFLAG(IS_POSIX)
// Test for move.
ASSERT_EQ(base::File::FILE_OK,
@@ -576,15 +576,15 @@ TEST_F(NativeFileUtilTest, PreserveDestinationPermissions) {
CopyOrMoveOptionSet(
CopyOrMoveOption::kPreserveDestinationPermissions),
NativeFileUtil::MOVE));
-#if defined(OS_POSIX)
+#if BUILDFLAG(IS_POSIX)
ExpectFileHasPermissionsPosix(to_file, old_dest_mode);
-#elif defined(OS_WIN)
+#elif BUILDFLAG(IS_WIN)
ExpectFileHasPermissionsWin(to_file, old_dest_attributes);
-#endif // defined(OS_POSIX)
+#endif // BUILDFLAG(IS_POSIX)
}
-#endif // defined(OS_POSIX) || defined(OS_WIN)
+#endif // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_WIN)
-#if defined(OS_POSIX) || defined(OS_WIN)
+#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_WIN)
TEST_F(NativeFileUtilTest, PreserveLastModifiedAndDestinationPermissions) {
base::FilePath from_file = Path("fromfile");
base::FilePath to_file1 = Path("tofile1");
@@ -618,22 +618,22 @@ TEST_F(NativeFileUtilTest, PreserveLastModifiedAndDestinationPermissions) {
// Get initial permissions of the dest files. We can assume that the 3
// destination files have the same permissions.
-#if defined(OS_POSIX)
+#if BUILDFLAG(IS_POSIX)
int dest_initial_mode;
ASSERT_TRUE(base::GetPosixFilePermissions(to_file1, &dest_initial_mode));
-#elif defined(OS_WIN)
+#elif BUILDFLAG(IS_WIN)
DWORD dest_initial_attributes = ::GetFileAttributes(to_file1.value().c_str());
ASSERT_NE(dest_initial_attributes, INVALID_FILE_ATTRIBUTES);
-#endif // defined(OS_POSIX)
+#endif // BUILDFLAG(IS_POSIX)
// Give dest files some distinct permissions they didn't have before.
-#if defined(OS_POSIX)
+#if BUILDFLAG(IS_POSIX)
int old_dest_mode = dest_initial_mode | S_IRGRP | S_IXOTH;
EXPECT_NE(old_dest_mode, dest_initial_mode);
EXPECT_TRUE(base::SetPosixFilePermissions(to_file1, old_dest_mode));
EXPECT_TRUE(base::SetPosixFilePermissions(to_file2, old_dest_mode));
EXPECT_TRUE(base::SetPosixFilePermissions(to_file3, old_dest_mode));
-#elif defined(OS_WIN)
+#elif BUILDFLAG(IS_WIN)
DWORD old_dest_attributes = FILE_ATTRIBUTE_NORMAL;
EXPECT_NE(old_dest_attributes, dest_initial_attributes);
EXPECT_TRUE(
@@ -642,7 +642,7 @@ TEST_F(NativeFileUtilTest, PreserveLastModifiedAndDestinationPermissions) {
::SetFileAttributes(to_file2.value().c_str(), old_dest_attributes));
EXPECT_TRUE(
::SetFileAttributes(to_file3.value().c_str(), old_dest_attributes));
-#endif // defined(OS_POSIX)
+#endif // BUILDFLAG(IS_POSIX)
// Test for copy (nosync).
ASSERT_EQ(base::File::FILE_OK,
@@ -658,11 +658,11 @@ TEST_F(NativeFileUtilTest, PreserveLastModifiedAndDestinationPermissions) {
NativeFileUtil::GetFileInfo(to_file1, &to_file_info));
EXPECT_EQ(from_file_info.last_modified, to_file_info.last_modified);
-#if defined(OS_POSIX)
+#if BUILDFLAG(IS_POSIX)
ExpectFileHasPermissionsPosix(to_file1, old_dest_mode);
-#elif defined(OS_WIN)
+#elif BUILDFLAG(IS_WIN)
ExpectFileHasPermissionsWin(to_file1, old_dest_attributes);
-#endif // defined(OS_POSIX)
+#endif // BUILDFLAG(IS_POSIX)
// Test for copy (sync).
ASSERT_EQ(base::File::FILE_OK,
@@ -676,11 +676,11 @@ TEST_F(NativeFileUtilTest, PreserveLastModifiedAndDestinationPermissions) {
NativeFileUtil::GetFileInfo(to_file2, &to_file_info));
EXPECT_EQ(from_file_info.last_modified, to_file_info.last_modified);
-#if defined(OS_POSIX)
+#if BUILDFLAG(IS_POSIX)
ExpectFileHasPermissionsPosix(to_file2, old_dest_mode);
-#elif defined(OS_WIN)
+#elif BUILDFLAG(IS_WIN)
ExpectFileHasPermissionsWin(to_file2, old_dest_attributes);
-#endif // defined(OS_POSIX)
+#endif // BUILDFLAG(IS_POSIX)
// Test for move.
ASSERT_EQ(base::File::FILE_OK,
@@ -694,12 +694,12 @@ TEST_F(NativeFileUtilTest, PreserveLastModifiedAndDestinationPermissions) {
NativeFileUtil::GetFileInfo(to_file3, &to_file_info));
EXPECT_EQ(from_file_info.last_modified, to_file_info.last_modified);
-#if defined(OS_POSIX)
+#if BUILDFLAG(IS_POSIX)
ExpectFileHasPermissionsPosix(to_file3, old_dest_mode);
-#elif defined(OS_WIN)
+#elif BUILDFLAG(IS_WIN)
ExpectFileHasPermissionsWin(to_file3, old_dest_attributes);
-#endif // defined(OS_POSIX)
+#endif // BUILDFLAG(IS_POSIX)
}
-#endif // defined(OS_POSIX) || defined(OS_WIN)
+#endif // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_WIN)
} // namespace storage
diff --git a/chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate.cc b/chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate.cc
index 7074ca38fa7..a46e047e994 100644
--- a/chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate.cc
+++ b/chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate.cc
@@ -27,7 +27,7 @@ namespace {
// Note that quota assignment is the same for on-disk filesystem and the
// assigned quota is not guaranteed to be allocatable later.
bool IsMemoryAvailable(int64_t required_memory) {
-#if defined(OS_FUCHSIA)
+#if BUILDFLAG(IS_FUCHSIA)
// This function is not implemented on FUCHSIA, yet. (crbug.com/986608)
return true;
#else
@@ -85,9 +85,9 @@ struct ObfuscatedFileUtilMemoryDelegate::DecomposedPath {
ObfuscatedFileUtilMemoryDelegate::ObfuscatedFileUtilMemoryDelegate(
const base::FilePath& file_system_directory)
- : root_(std::make_unique<Entry>(Entry::kDirectory)) {
+ : root_(std::make_unique<Entry>(Entry::kDirectory)),
+ root_path_components_(file_system_directory.GetComponents()) {
DETACH_FROM_SEQUENCE(sequence_checker_);
- file_system_directory.GetComponents(&root_path_components_);
}
ObfuscatedFileUtilMemoryDelegate::~ObfuscatedFileUtilMemoryDelegate() {
@@ -98,8 +98,7 @@ absl::optional<ObfuscatedFileUtilMemoryDelegate::DecomposedPath>
ObfuscatedFileUtilMemoryDelegate::ParsePath(const base::FilePath& path) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DecomposedPath dp;
-
- path.GetComponents(&dp.components);
+ dp.components = path.GetComponents();
// Ensure |path| is under |root_|.
if (dp.components.size() < root_path_components_.size())
@@ -378,7 +377,7 @@ base::File::Error ObfuscatedFileUtilMemoryDelegate::CopyOrMoveFile(
if (dest_dp->entry->type != src_dp->entry->type)
return base::File::FILE_ERROR_INVALID_OPERATION;
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
// Overwriting an empty directory with another directory isn't
// supported natively on Windows.
// To keep the behavior indistinguishable from on-disk operation,
@@ -549,7 +548,7 @@ int ObfuscatedFileUtilMemoryDelegate::WriteFile(
// See crbug.com/1043914 for more context.
// |MaxDirectMapped| function is not implemented on FUCHSIA, yet.
// (crbug.com/986608)
-#if !defined(OS_FUCHSIA)
+#if !BUILDFLAG(IS_FUCHSIA)
if (last_position >= base::MaxDirectMapped() / 2) {
// TODO(https://crbug.com/1043914): Allocated memory is rounded up to
// 100MB blocks to reduce memory allocation delays. Switch to a more
diff --git a/chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate_unittest.cc b/chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate_unittest.cc
index 2430d3136fb..76cf12f10ad 100644
--- a/chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate_unittest.cc
+++ b/chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate_unittest.cc
@@ -488,7 +488,7 @@ TEST_F(ObfuscatedFileUtilMemoryDelegateTest, MoveDirectoryOverDirectory) {
base::File::Error result = file_util()->CopyOrMoveFile(
dir, dir2, FileSystemOperation::CopyOrMoveOptionSet(), move);
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
EXPECT_EQ(base::File::FILE_ERROR_NOT_A_FILE, result);
#else
EXPECT_EQ(base::File::FILE_OK, result);
@@ -578,7 +578,7 @@ TEST_F(ObfuscatedFileUtilMemoryDelegateTest, MoveFile_Directory) {
EXPECT_EQ(1020, GetSize(to_file));
}
-#if !defined(OS_WIN)
+#if !BUILDFLAG(IS_WIN)
TEST_F(ObfuscatedFileUtilMemoryDelegateTest, MoveFile_OverwriteEmptyDirectory) {
base::FilePath from_directory = Path("fromdirectory");
base::FilePath to_directory = Path("todirectory");
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 f8db2da7705..604674b3d16 100644
--- a/chromium/storage/browser/file_system/obfuscated_file_util_unittest.cc
+++ b/chromium/storage/browser/file_system/obfuscated_file_util_unittest.cc
@@ -1284,10 +1284,8 @@ TEST_P(ObfuscatedFileUtilTest, TestPathQuotas) {
bool exclusive = true;
bool recursive = true;
url = CreateURLFromUTF8("directory/to/use");
- std::vector<base::FilePath::StringType> components;
- url.path().GetComponents(&components);
path_cost = 0;
- for (const auto& component : components) {
+ for (const auto& component : url.path().GetComponents()) {
path_cost +=
ObfuscatedFileUtil::ComputeFilePathCost(base::FilePath(component));
}
@@ -2043,7 +2041,7 @@ TEST_P(ObfuscatedFileUtilTest, TestFileEnumeratorTimestamp) {
}
// crbug.com/176470
-#if defined(OS_WIN) || defined(OS_ANDROID)
+#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
#define MAYBE_TestQuotaOnCopyFile DISABLED_TestQuotaOnCopyFile
#else
#define MAYBE_TestQuotaOnCopyFile TestQuotaOnCopyFile
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 c42bd25902c..c3f943b01a5 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
@@ -274,23 +274,6 @@ PluginPrivateFileSystemBackend::GetStorageKeysForTypeOnFileTaskRunner(
return storage_keys;
}
-std::vector<blink::StorageKey>
-PluginPrivateFileSystemBackend::GetStorageKeysForHostOnFileTaskRunner(
- FileSystemType type,
- const std::string& host) {
- if (!CanHandleType(type))
- return std::vector<blink::StorageKey>();
- std::unique_ptr<ObfuscatedFileUtil::AbstractStorageKeyEnumerator> enumerator(
- obfuscated_file_util()->CreateStorageKeyEnumerator());
- std::vector<blink::StorageKey> storage_keys;
- absl::optional<blink::StorageKey> storage_key;
- while ((storage_key = enumerator->Next()).has_value()) {
- if (host == storage_key->origin().host())
- storage_keys.push_back(std::move(storage_key).value());
- }
- return storage_keys;
-}
-
int64_t PluginPrivateFileSystemBackend::GetStorageKeyUsageOnFileTaskRunner(
FileSystemContext* context,
const blink::StorageKey& storage_key,
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 9174aa0c0cd..5b36b8826f4 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
@@ -127,9 +127,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) PluginPrivateFileSystemBackend
FileSystemType type) override;
std::vector<blink::StorageKey> GetStorageKeysForTypeOnFileTaskRunner(
FileSystemType type) override;
- std::vector<blink::StorageKey> GetStorageKeysForHostOnFileTaskRunner(
- FileSystemType type,
- const std::string& host) override;
int64_t GetStorageKeyUsageOnFileTaskRunner(
FileSystemContext* context,
const blink::StorageKey& storage_key,
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 6827bd07cb7..618bc3a7978 100644
--- a/chromium/storage/browser/file_system/quota/quota_backend_impl.cc
+++ b/chromium/storage/browser/file_system/quota/quota_backend_impl.cc
@@ -145,7 +145,8 @@ void QuotaBackendImpl::ReserveQuotaInternal(const QuotaReservationInfo& info) {
quota_manager_proxy_->NotifyStorageModified(
QuotaClientType::kFileSystem, blink::StorageKey(info.origin),
FileSystemTypeToQuotaStorageType(info.type), info.delta,
- base::Time::Now());
+ base::Time::Now(), base::SequencedTaskRunnerHandle::Get(),
+ base::DoNothing());
}
base::File::Error QuotaBackendImpl::GetUsageCachePath(
diff --git a/chromium/storage/browser/file_system/sandbox_directory_database.cc b/chromium/storage/browser/file_system/sandbox_directory_database.cc
index e8eab17fd5e..9f6bb1bff35 100644
--- a/chromium/storage/browser/file_system/sandbox_directory_database.cc
+++ b/chromium/storage/browser/file_system/sandbox_directory_database.cc
@@ -746,7 +746,7 @@ bool SandboxDirectoryDatabase::Init(RecoveryOption recovery_option) {
SandboxDirectoryRepairResult::DB_REPAIR_FAILED,
SandboxDirectoryRepairResult::DB_REPAIR_MAX);
LOG(WARNING) << "Failed to repair SandboxDirectoryDatabase.";
- FALLTHROUGH;
+ [[fallthrough]];
case DELETE_ON_CORRUPTION:
LOG(WARNING) << "Clearing SandboxDirectoryDatabase.";
if (!leveldb_chrome::DeleteDB(filesystem_data_directory_, options).ok())
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 7c4a09757aa..f409b5885d9 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
@@ -340,9 +340,10 @@ SandboxFileSystemBackendDelegate::DeleteStorageKeyDataOnFileTaskRunner(
bool result = obfuscated_file_util()->DeleteDirectoryForStorageKeyAndType(
storage_key, GetTypeString(type));
if (result && proxy && usage) {
- proxy->NotifyStorageModified(QuotaClientType::kFileSystem, storage_key,
- FileSystemTypeToQuotaStorageType(type), -usage,
- base::Time::Now());
+ proxy->NotifyStorageModified(
+ QuotaClientType::kFileSystem, storage_key,
+ FileSystemTypeToQuotaStorageType(type), -usage, base::Time::Now(),
+ base::SequencedTaskRunnerHandle::Get(), base::DoNothing());
}
if (result)
@@ -384,23 +385,6 @@ SandboxFileSystemBackendDelegate::GetStorageKeysForTypeOnFileTaskRunner(
return storage_keys;
}
-std::vector<blink::StorageKey>
-SandboxFileSystemBackendDelegate::GetStorageKeysForHostOnFileTaskRunner(
- FileSystemType type,
- const std::string& host) {
- DCHECK(file_task_runner_->RunsTasksInCurrentSequence());
- std::vector<blink::StorageKey> storage_keys;
- std::unique_ptr<StorageKeyEnumerator> enumerator(
- CreateStorageKeyEnumerator());
- absl::optional<blink::StorageKey> storage_key;
- while ((storage_key = enumerator->Next()).has_value()) {
- if (host == storage_key->origin().host() &&
- enumerator->HasFileSystemType(type))
- storage_keys.push_back(std::move(storage_key).value());
- }
- return storage_keys;
-}
-
int64_t SandboxFileSystemBackendDelegate::GetStorageKeyUsageOnFileTaskRunner(
FileSystemContext* file_system_context,
const blink::StorageKey& storage_key,
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 cc1cc70dc73..7abbc1a959e 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
@@ -156,9 +156,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) SandboxFileSystemBackendDelegate
FileSystemType type) override;
std::vector<blink::StorageKey> GetStorageKeysForTypeOnFileTaskRunner(
FileSystemType type) override;
- std::vector<blink::StorageKey> GetStorageKeysForHostOnFileTaskRunner(
- FileSystemType type,
- const std::string& host) override;
int64_t GetStorageKeyUsageOnFileTaskRunner(
FileSystemContext* context,
const blink::StorageKey& storage_key,
diff --git a/chromium/storage/browser/file_system/sandbox_origin_database.cc b/chromium/storage/browser/file_system/sandbox_origin_database.cc
index 21c8ec86631..800c1248c07 100644
--- a/chromium/storage/browser/file_system/sandbox_origin_database.cc
+++ b/chromium/storage/browser/file_system/sandbox_origin_database.cc
@@ -116,7 +116,7 @@ bool SandboxOriginDatabase::Init(InitOption init_option,
UMA_HISTOGRAM_ENUMERATION(kSandboxOriginDatabaseRepairHistogramLabel,
SandboxOriginRepairResult::DB_REPAIR_FAILED,
SandboxOriginRepairResult::DB_REPAIR_MAX);
- FALLTHROUGH;
+ [[fallthrough]];
case DELETE_ON_CORRUPTION:
if (!base::DeletePathRecursively(file_system_directory_))
return false;
diff --git a/chromium/storage/browser/file_system/sandbox_quota_observer.cc b/chromium/storage/browser/file_system/sandbox_quota_observer.cc
index d9855e49fd5..5428baf2f27 100644
--- a/chromium/storage/browser/file_system/sandbox_quota_observer.cc
+++ b/chromium/storage/browser/file_system/sandbox_quota_observer.cc
@@ -45,7 +45,8 @@ void SandboxQuotaObserver::OnUpdate(const FileSystemURL& url, int64_t delta) {
if (quota_manager_proxy_.get()) {
quota_manager_proxy_->NotifyStorageModified(
QuotaClientType::kFileSystem, url.storage_key(),
- FileSystemTypeToQuotaStorageType(url.type()), delta, base::Time::Now());
+ FileSystemTypeToQuotaStorageType(url.type()), delta, base::Time::Now(),
+ base::SequencedTaskRunnerHandle::Get(), base::DoNothing());
}
base::FilePath usage_file_path = GetUsageCachePath(url);
diff --git a/chromium/storage/browser/quota/BUILD.gn b/chromium/storage/browser/quota/BUILD.gn
new file mode 100644
index 00000000000..f930e025dab
--- /dev/null
+++ b/chromium/storage/browser/quota/BUILD.gn
@@ -0,0 +1,17 @@
+# 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.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+mojom("mojo_bindings") {
+ sources = [ "quota_internals.mojom" ]
+ webui_module_path = "/"
+
+ public_deps = [ "//url/mojom:url_mojom_origin" ]
+
+ disable_variants = true
+
+ component_output_prefix = "storage_browser_interfaces"
+ component_macro_prefix = "STORAGE_BROWSER_INTERFACES"
+}
diff --git a/chromium/storage/browser/quota/OWNERS b/chromium/storage/browser/quota/OWNERS
index 8e88df27dc1..96896d848b8 100644
--- a/chromium/storage/browser/quota/OWNERS
+++ b/chromium/storage/browser/quota/OWNERS
@@ -7,3 +7,6 @@ jsbell@chromium.org
kinuko@chromium.org
mek@chromium.org
pwnall@chromium.org
+
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS \ No newline at end of file
diff --git a/chromium/storage/browser/quota/client_usage_tracker.cc b/chromium/storage/browser/quota/client_usage_tracker.cc
index 87fd0d5690c..2e6a60daf09 100644
--- a/chromium/storage/browser/quota/client_usage_tracker.cc
+++ b/chromium/storage/browser/quota/client_usage_tracker.cc
@@ -5,63 +5,26 @@
#include "storage/browser/quota/client_usage_tracker.h"
#include <stdint.h>
+#include <iterator>
+#include "base/barrier_closure.h"
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/containers/contains.h"
-#include "base/metrics/histogram_macros.h"
+#include "base/metrics/histogram_functions.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
namespace storage {
namespace {
-using StorageKeySetByHost = ClientUsageTracker::StorageKeySetByHost;
-
-void DidGetHostUsage(UsageCallback callback,
- int64_t limited_usage,
- int64_t unlimited_usage) {
- DCHECK_GE(limited_usage, 0);
- DCHECK_GE(unlimited_usage, 0);
- std::move(callback).Run(limited_usage + unlimited_usage);
-}
-
-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(storage_key))
- return false;
-
- if (it->second.empty())
- storage_keys_by_host->erase(host);
- return true;
-}
-
-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) {
- UMA_HISTOGRAM_ENUMERATION("Quota.SkippedInvalidOriginUsage", reason);
+ base::UmaHistogramEnumeration("Quota.SkippedInvalidOriginUsage", reason);
}
} // namespace
struct ClientUsageTracker::AccumulateInfo {
- AccumulateInfo() = default;
- ~AccumulateInfo() = default;
-
- AccumulateInfo(const AccumulateInfo&) = delete;
- AccumulateInfo& operator=(const AccumulateInfo&) = delete;
-
- size_t pending_jobs = 0;
int64_t limited_usage = 0;
int64_t unlimited_usage = 0;
};
@@ -73,9 +36,6 @@ ClientUsageTracker::ClientUsageTracker(
scoped_refptr<SpecialStoragePolicy> special_storage_policy)
: client_(client),
type_(type),
- global_limited_usage_(0),
- global_unlimited_usage_(0),
- global_usage_retrieved_(false),
special_storage_policy_(std::move(special_storage_policy)) {
DCHECK(client_);
if (special_storage_policy_.get())
@@ -88,83 +48,94 @@ ClientUsageTracker::~ClientUsageTracker() {
special_storage_policy_->RemoveObserver(this);
}
-void ClientUsageTracker::GetGlobalUsage(GlobalUsageCallback callback) {
+void ClientUsageTracker::GetBucketsUsage(const std::set<BucketLocator>& buckets,
+ UsageCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (global_usage_retrieved_ &&
- 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;
- }
+ DCHECK_GT(buckets.size(), 0u);
- client_->GetStorageKeysForType(
- type_,
- base::BindOnce(&ClientUsageTracker::DidGetStorageKeysForGlobalUsage,
- weak_factory_.GetWeakPtr(), std::move(callback)));
-}
+ auto info = std::make_unique<AccumulateInfo>();
+ auto* info_ptr = info.get();
+ base::RepeatingClosure barrier = base::BarrierClosure(
+ buckets.size(),
+ base::BindOnce(&ClientUsageTracker::FinallySendBucketsUsage,
+ weak_factory_.GetWeakPtr(), std::move(callback),
+ std::move(info)));
-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_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;
- }
+ for (const auto& bucket : buckets) {
+ // TODO(https://crbug.com/941480): `storage_key` should not be opaque or
+ // have an empty url, but sometimes it is.
+ if (bucket.storage_key.origin().opaque()) {
+ DVLOG(1) << "GetBucketsUsage for opaque storage_key!";
+ RecordSkippedOriginHistogram(InvalidOriginReason::kIsOpaque);
+ barrier.Run();
+ continue;
+ }
- if (!host_usage_accumulators_.Add(
- host, base::BindOnce(&DidGetHostUsage, std::move(callback))))
- return;
- client_->GetStorageKeysForHost(
- type_, host,
- base::BindOnce(&ClientUsageTracker::DidGetStorageKeysForHostUsage,
- weak_factory_.GetWeakPtr(), host));
+ if (bucket.storage_key.origin().GetURL().is_empty()) {
+ DVLOG(1) << "GetBucketsUsage for storage_key with empty url!";
+ RecordSkippedOriginHistogram(InvalidOriginReason::kIsEmpty);
+ barrier.Run();
+ continue;
+ }
+
+ // Use a cached usage value, if we have one.
+ int64_t cached_usage = GetCachedBucketUsage(bucket);
+ if (cached_usage != -1) {
+ AccumulateBucketsUsage(barrier, bucket, info_ptr, cached_usage);
+ continue;
+ }
+
+ client_->GetBucketUsage(
+ bucket,
+ // base::Unretained usage is safe here because barrier holds the
+ // std::unque_ptr that keeps AccumulateInfo alive, and the barrier
+ // will outlive all the AccumulateClientGlobalUsage closures.
+ base::BindOnce(&ClientUsageTracker::AccumulateBucketsUsage,
+ weak_factory_.GetWeakPtr(), barrier, bucket,
+ base::Unretained(info_ptr)));
+ }
}
-void ClientUsageTracker::UpdateUsageCache(const blink::StorageKey& storage_key,
- int64_t delta) {
+void ClientUsageTracker::UpdateBucketUsageCache(const BucketLocator& bucket,
+ int64_t delta) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- const std::string& host = storage_key.origin().host();
- if (base::Contains(cached_hosts_, host)) {
- 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][storage_key]);
- cached_usage_by_host_[host][storage_key] += delta;
- UpdateGlobalUsageValue(IsStorageUnlimited(storage_key)
- ? &global_unlimited_usage_
- : &global_limited_usage_,
- delta);
+ if (!IsUsageCacheEnabledForStorageKey(bucket.storage_key))
+ return;
+ auto bucket_it = cached_bucket_usage_.find(bucket);
+ if (bucket_it != cached_bucket_usage_.end()) {
+ // Constrain `delta` to avoid negative usage values.
+ // TODO(crbug.com/463729): At least one storage API sends deltas that
+ // result in negative total usage. The line below works around this bug.
+ // Fix the bug, and remove the workaround.
+ delta = std::max(delta, -bucket_it->second);
+ bucket_it->second += delta;
return;
}
+ // Retrieve bucket usage and update cache.
+ GetBucketUsage(bucket, base::DoNothing());
+}
- // We call GetHostUsage() so that the cache still updates, but we don't need
- // to do anything else with the usage so we do not pass a callback.
- GetHostUsage(host, base::DoNothing());
+void ClientUsageTracker::DeleteBucketCache(const BucketLocator& bucket) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ cached_bucket_usage_.erase(bucket);
}
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& storage_key_and_usage : host_and_usage_map.second)
- usage += storage_key_and_usage.second;
- }
+ for (const auto& bucket_and_usage : cached_bucket_usage_)
+ usage += bucket_and_usage.second;
return usage;
}
std::map<std::string, int64_t> ClientUsageTracker::GetCachedHostsUsage() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::map<std::string, int64_t> host_usage;
- for (const auto& host_and_usage_map : cached_usage_by_host_) {
- const std::string& host = host_and_usage_map.first;
- host_usage[host] += GetCachedHostUsage(host);
+ for (const auto& bucket_and_usage : cached_bucket_usage_) {
+ const std::string& host =
+ bucket_and_usage.first.storage_key.origin().host();
+ host_usage[host] += bucket_and_usage.second;
}
return host_usage;
}
@@ -173,255 +144,121 @@ std::map<blink::StorageKey, int64_t>
ClientUsageTracker::GetCachedStorageKeysUsage() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::map<blink::StorageKey, int64_t> storage_key_usage;
- for (const auto& host_and_usage_map : cached_usage_by_host_) {
- 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;
+ for (const auto& bucket_and_usage : cached_bucket_usage_) {
+ const blink::StorageKey& storage_key = bucket_and_usage.first.storage_key;
+ storage_key_usage[storage_key] += bucket_and_usage.second;
}
return storage_key_usage;
}
-std::set<blink::StorageKey> ClientUsageTracker::GetCachedStorageKeys() const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- std::set<blink::StorageKey> storage_keys;
- for (const auto& host_and_usage_map : cached_usage_by_host_) {
- for (const auto& storage_key_and_usage : host_and_usage_map.second)
- storage_keys.insert(storage_key_and_usage.first);
- }
- return storage_keys;
-}
-
void ClientUsageTracker::SetUsageCacheEnabled(
const blink::StorageKey& storage_key,
bool enabled) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- const std::string& host = storage_key.origin().host();
- if (!enabled) {
- // 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 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);
- }
- }
- }
+ if (enabled) {
+ non_cached_limited_storage_keys_.erase(storage_key);
+ non_cached_unlimited_storage_keys_.erase(storage_key);
+ return;
+ }
- if (IsStorageUnlimited(storage_key))
- non_cached_unlimited_storage_keys_by_host_[host].insert(storage_key);
- else
- non_cached_limited_storage_keys_by_host_[host].insert(storage_key);
- } else {
- // 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;
+ // Find all buckets for `storage_key` in `cached_bucket_usage_`
+ // and remove them from the cache. Erases cached bucket usage while iterating.
+ for (auto it = cached_bucket_usage_.cbegin();
+ it != cached_bucket_usage_.cend();) {
+ if (it->first.storage_key == storage_key) {
+ // Calling erase() while iterating is safe because (1) std::map::erase()
+ // only invalidates the iterator pointing to the erased element, and (2)
+ // `it` is advanced off of the erased element before erase() is called.
+ cached_bucket_usage_.erase(it++);
+ } else {
+ ++it;
}
}
-}
-void ClientUsageTracker::DidGetStorageKeysForGlobalUsage(
- GlobalUsageCallback callback,
- const std::vector<blink::StorageKey>& storage_keys) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- 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
- // cached, which may in turn dispatch the completion callback before we finish
- // 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 = 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::OwnedRef(std::move(callback)));
-
- 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_for_host =
- host_and_storage_keys.second;
- if (host_usage_accumulators_.Add(host, accumulator))
- GetUsageForStorageKeys(host, storage_keys_for_host);
+ // Add to `non_cached_*_storage_keys_` to exclude `storage_key` from quota
+ // restrictions.
+ if (IsStorageUnlimited(storage_key)) {
+ non_cached_unlimited_storage_keys_.insert(storage_key);
+ } else {
+ non_cached_limited_storage_keys_.insert(storage_key);
}
-
- // 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,
- int64_t limited_usage,
- int64_t unlimited_usage) {
- DCHECK_GT(info->pending_jobs, 0U);
+bool ClientUsageTracker::IsUsageCacheEnabledForStorageKey(
+ const blink::StorageKey& storage_key) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- info->limited_usage += limited_usage;
- info->unlimited_usage += unlimited_usage;
- if (--info->pending_jobs)
- return;
-
- DCHECK_GE(info->limited_usage, 0);
- DCHECK_GE(info->unlimited_usage, 0);
-
- global_usage_retrieved_ = true;
- std::move(callback).Run(info->limited_usage + info->unlimited_usage,
- info->unlimited_usage);
+ return !base::Contains(non_cached_limited_storage_keys_, storage_key) &&
+ !base::Contains(non_cached_unlimited_storage_keys_, storage_key);
}
-void ClientUsageTracker::DidGetStorageKeysForHostUsage(
- const std::string& host,
- const std::vector<blink::StorageKey>& storage_keys) {
+void ClientUsageTracker::AccumulateBucketsUsage(
+ base::OnceClosure barrier_callback,
+ const BucketLocator& bucket,
+ AccumulateInfo* info,
+ int64_t usage) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- GetUsageForStorageKeys(host, storage_keys);
-}
+ // Defend against confusing inputs from clients.
+ // TODO(crbug.com/1292210): Remove this check after fixing QuotaClients.
+ if (usage < 0)
+ usage = 0;
-void ClientUsageTracker::GetUsageForStorageKeys(
- const std::string& host,
- const std::vector<blink::StorageKey>& storage_keys) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- AccumulateInfo* info = new AccumulateInfo;
- // 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::AccumulateStorageKeyUsage,
- weak_factory_.GetWeakPtr(), base::Owned(info), host);
-
- for (const auto& storage_key : storage_keys) {
- DCHECK_EQ(host, storage_key.origin().host());
-
- int64_t storage_key_usage = 0;
- if (GetCachedStorageKeyUsage(storage_key, &storage_key_usage)) {
- accumulator.Run(storage_key, storage_key_usage);
- } else {
- client_->GetStorageKeyUsage(storage_key, type_,
- base::BindOnce(accumulator, storage_key));
- }
+ if (IsStorageUnlimited(bucket.storage_key)) {
+ info->unlimited_usage += usage;
+ } else {
+ info->limited_usage += usage;
}
- // Fire the sentinel as we've now called GetStorageKeyUsage for all clients.
- accumulator.Run(absl::nullopt, 0);
+ if (IsUsageCacheEnabledForStorageKey(bucket.storage_key))
+ CacheBucketUsage(bucket, usage);
+ std::move(barrier_callback).Run();
}
-void ClientUsageTracker::AccumulateStorageKeyUsage(
- AccumulateInfo* info,
- const std::string& host,
- const absl::optional<blink::StorageKey>& storage_key,
- int64_t usage) {
- DCHECK_GT(info->pending_jobs, 0U);
+void ClientUsageTracker::FinallySendBucketsUsage(
+ UsageCallback callback,
+ std::unique_ptr<AccumulateInfo> info) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- 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 (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(*storage_key))
- info->unlimited_usage += usage;
- else
- info->limited_usage += usage;
- if (IsUsageCacheEnabledForStorageKey(*storage_key))
- AddCachedStorageKey(*storage_key, usage);
- }
- }
- if (--info->pending_jobs)
- return;
+ DCHECK_GE(info->limited_usage, 0);
+ DCHECK_GE(info->unlimited_usage, 0);
- AddCachedHost(host);
- host_usage_accumulators_.Run(
- host, info->limited_usage, info->unlimited_usage);
+ std::move(callback).Run(info->limited_usage + info->unlimited_usage,
+ info->unlimited_usage);
}
-void ClientUsageTracker::AddCachedStorageKey(
- const blink::StorageKey& storage_key,
- int64_t new_usage) {
+void ClientUsageTracker::CacheBucketUsage(const BucketLocator& bucket,
+ int64_t new_usage) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(IsUsageCacheEnabledForStorageKey(storage_key));
-
- 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(storage_key)
- ? &global_unlimited_usage_
- : &global_limited_usage_,
- delta);
- }
+ DCHECK(IsUsageCacheEnabledForStorageKey(bucket.storage_key));
+ cached_bucket_usage_[bucket] = new_usage;
}
-void ClientUsageTracker::AddCachedHost(const std::string& host) {
+int64_t ClientUsageTracker::GetCachedBucketUsage(
+ const BucketLocator& bucket) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- cached_hosts_.insert(host);
+ auto bucket_it = cached_bucket_usage_.find(bucket);
+ if (bucket_it == cached_bucket_usage_.end())
+ return -1;
+ return bucket_it->second;
}
-int64_t ClientUsageTracker::GetCachedHostUsage(const std::string& host) const {
+void ClientUsageTracker::GetBucketUsage(const BucketLocator& bucket,
+ UsageCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- auto it = cached_usage_by_host_.find(host);
- if (it == cached_usage_by_host_.end())
- return 0;
-
- int64_t usage = 0;
- const UsageMap& usage_map = it->second;
- for (const auto& storage_key_and_usage : usage_map)
- usage += storage_key_and_usage.second;
- return usage;
+ client_->GetBucketUsage(
+ bucket,
+ base::BindOnce(&ClientUsageTracker::DidGetBucketUsage,
+ weak_factory_.GetWeakPtr(), bucket, std::move(callback)));
+ return;
}
-bool ClientUsageTracker::GetCachedStorageKeyUsage(
- const blink::StorageKey& storage_key,
- int64_t* usage) const {
+void ClientUsageTracker::DidGetBucketUsage(const BucketLocator& bucket,
+ UsageCallback callback,
+ int64_t usage) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- 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;
+ if (IsUsageCacheEnabledForStorageKey(bucket.storage_key))
+ CacheBucketUsage(bucket, usage);
- auto storage_key_it = host_it->second.find(storage_key);
- if (storage_key_it == host_it->second.end())
- return false;
-
- DCHECK(IsUsageCacheEnabledForStorageKey(storage_key));
- *usage = storage_key_it->second;
- return true;
-}
-
-bool ClientUsageTracker::IsUsageCacheEnabledForStorageKey(
- const blink::StorageKey& storage_key) const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- 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);
+ int64_t unlimited_usage = IsStorageUnlimited(bucket.storage_key) ? usage : 0;
+ std::move(callback).Run(usage, unlimited_usage);
}
void ClientUsageTracker::OnGranted(const url::Origin& origin_url,
@@ -431,16 +268,8 @@ void ClientUsageTracker::OnGranted(const url::Origin& origin_url,
// 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 (GetCachedStorageKeyUsage(storage_key, &usage)) {
- global_unlimited_usage_ += usage;
- global_limited_usage_ -= usage;
- }
-
- 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);
+ if (non_cached_limited_storage_keys_.erase(storage_key))
+ non_cached_unlimited_storage_keys_.insert(storage_key);
}
}
@@ -451,52 +280,17 @@ void ClientUsageTracker::OnRevoked(const url::Origin& origin_url,
// 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 (GetCachedStorageKeyUsage(storage_key, &usage)) {
- global_unlimited_usage_ -= usage;
- global_limited_usage_ += usage;
- }
-
- 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);
+ if (non_cached_unlimited_storage_keys_.erase(storage_key))
+ non_cached_limited_storage_keys_.insert(storage_key);
}
}
void ClientUsageTracker::OnCleared() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- global_limited_usage_ += global_unlimited_usage_;
- global_unlimited_usage_ = 0;
-
- 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_storage_keys_by_host_.clear();
-}
-
-void ClientUsageTracker::UpdateGlobalUsageValue(int64_t* usage_value,
- int64_t delta) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- *usage_value += delta;
- if (*usage_value >= 0)
- return;
-
- // If we have a negative global usage value, recalculate them.
- // TODO(michaeln): There are book keeping bugs, crbug/463729
- global_limited_usage_ = 0;
- global_unlimited_usage_ = 0;
- for (const auto& host_and_usage_map : cached_usage_by_host_) {
- 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_ += storage_key_and_usage.second;
- }
- }
+ non_cached_limited_storage_keys_.insert(
+ std::make_move_iterator(non_cached_unlimited_storage_keys_.begin()),
+ std::make_move_iterator(non_cached_unlimited_storage_keys_.end()));
+ non_cached_unlimited_storage_keys_.clear();
}
bool ClientUsageTracker::IsStorageUnlimited(
diff --git a/chromium/storage/browser/quota/client_usage_tracker.h b/chromium/storage/browser/quota/client_usage_tracker.h
index e22336bb40d..6fe44ebf6fa 100644
--- a/chromium/storage/browser/quota/client_usage_tracker.h
+++ b/chromium/storage/browser/quota/client_usage_tracker.h
@@ -16,6 +16,7 @@
#include "base/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/sequence_checker.h"
+#include "components/services/storage/public/cpp/buckets/bucket_locator.h"
#include "components/services/storage/public/mojom/quota_client.mojom.h"
#include "storage/browser/quota/quota_callbacks.h"
#include "storage/browser/quota/quota_task.h"
@@ -41,17 +42,13 @@ enum class InvalidOriginReason {
kMaxValue = kIsEmpty
};
-// Holds per-client usage tracking information and caches
-// per-host usage data.
+// Holds per-client usage tracking information and caches bucket usage data.
//
// A UsageTracker object will own one ClientUsageTracker instance per client.
// This class is not thread-safe. All methods other than the constructor must be
// called on the same sequence.
class ClientUsageTracker : public SpecialStoragePolicy::Observer {
public:
- using StorageKeySetByHost =
- std::map<std::string, std::set<blink::StorageKey>>;
-
// The caller must ensure that `client` outlives this instance.
ClientUsageTracker(
UsageTracker* tracker,
@@ -64,81 +61,86 @@ class ClientUsageTracker : public SpecialStoragePolicy::Observer {
~ClientUsageTracker() override;
- void GetGlobalUsage(GlobalUsageCallback callback);
- void GetHostUsage(const std::string& host, UsageCallback callback);
- void UpdateUsageCache(const blink::StorageKey& storage_key, int64_t delta);
+ // Computes total usage and unlimited usage for `buckets`.
+ void GetBucketsUsage(const std::set<BucketLocator>& buckets,
+ UsageCallback callback);
+
+ // Reflects an increase by `delta` to `bucket`'s quota usage.
+ //
+ // This can be called with a `bucket` whose usage is not yet cached.
+ // A negative `delta` value reflects a reduction in quota usage.
+ // Negative `delta` values are clamped to ensure the total cached usage never
+ // goes below zero (crbug.com/463729).
+ void UpdateBucketUsageCache(const BucketLocator& bucket, int64_t delta);
+
+ // Deletes `bucket` from the cache if it exists. Called either for bucket
+ // deletion or disabling cache for `bucket`'s Storage Key.
+ void DeleteBucketCache(const BucketLocator& bucket);
+
+ // Accumulates all cached usage to determine storage pressure.
int64_t GetCachedUsage() const;
+
+ // Returns cached usage organized by host. Expected to be called after
+ // GetGlobalUsage which retrieves and caches host usage.
std::map<std::string, int64_t> GetCachedHostsUsage() const;
+
+ // Returns cached usage organized by StorageKey. Used for histogram recording.
+ // TODO(ayui): Update to return bucket usage map.
std::map<blink::StorageKey, int64_t> GetCachedStorageKeysUsage() const;
- std::set<blink::StorageKey> GetCachedStorageKeys() const;
- bool IsUsageCacheEnabledForStorageKey(
- const blink::StorageKey& storage_key) const;
+
+ // Sets if a `storage_key` for `client_` should / should not be excluded from
+ // quota restrictions.
void SetUsageCacheEnabled(const blink::StorageKey& storage_key, bool enabled);
private:
- using UsageMap = std::map<blink::StorageKey, int64_t>;
-
struct AccumulateInfo;
- void DidGetStorageKeysForGlobalUsage(
- GlobalUsageCallback callback,
- const std::vector<blink::StorageKey>& storage_keys);
- void AccumulateHostUsage(AccumulateInfo* info,
- GlobalUsageCallback& callback,
- int64_t limited_usage,
- int64_t unlimited_usage);
-
- void DidGetStorageKeysForHostUsage(
- const std::string& host,
- const std::vector<blink::StorageKey>& storage_keys);
-
- 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
- // 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;
- bool GetCachedStorageKeyUsage(const blink::StorageKey& storage_key,
- int64_t* usage) const;
-
- // SpecialStoragePolicy::Observer overrides
+ bool IsUsageCacheEnabledForStorageKey(
+ const blink::StorageKey& storage_key) const;
+
+ void AccumulateBucketsUsage(base::OnceClosure barrier_callback,
+ const BucketLocator& bucket,
+ AccumulateInfo* info,
+ int64_t usage);
+
+ void FinallySendBucketsUsage(UsageCallback callback,
+ std::unique_ptr<AccumulateInfo> info);
+
+ // Adds `bucket` and its `usage` to the cache. An existing cached value is
+ // replaced with the new value provided here. Used by tasks that gather
+ // global/host usage to incrementally cache as usage is retrieved.
+ void CacheBucketUsage(const BucketLocator& bucket, int64_t usage);
+
+ // Gets cached `bucket` usage. Returns -1 if no usage is cached.
+ int64_t GetCachedBucketUsage(const BucketLocator& bucket) const;
+
+ // Retrieves `bucket` usage from the tracked QuotaClient and adds to the
+ // cache.
+ void GetBucketUsage(const BucketLocator& bucket, UsageCallback callback);
+ void DidGetBucketUsage(const BucketLocator& bucket,
+ UsageCallback callback,
+ int64_t usage);
+
+ // 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 blink::StorageKey& storage_key) const;
raw_ptr<mojom::QuotaClient> client_;
const blink::mojom::StorageType type_;
- int64_t global_limited_usage_;
- int64_t global_unlimited_usage_;
- bool global_usage_retrieved_;
- std::set<std::string> cached_hosts_;
- std::map<std::string, UsageMap> cached_usage_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)>,
- std::string,
- int64_t,
- int64_t>
- host_usage_accumulators_;
+ // The implementation relies on a collection whose erase() only invalidates
+ // iterators that point to the erased element. This comment is intended to
+ // prevent accidental conversion to other containers, such as base::flat_map.
+ std::map<BucketLocator, int64_t> cached_bucket_usage_;
+
+ // Storage Keys that are excluded from quota restrictions.
+ std::set<blink::StorageKey> non_cached_limited_storage_keys_;
+ std::set<blink::StorageKey> non_cached_unlimited_storage_keys_;
const scoped_refptr<SpecialStoragePolicy> special_storage_policy_;
diff --git a/chromium/storage/browser/quota/quota_callbacks.h b/chromium/storage/browser/quota/quota_callbacks.h
index d64ab3dc188..5598c143d84 100644
--- a/chromium/storage/browser/quota/quota_callbacks.h
+++ b/chromium/storage/browser/quota/quota_callbacks.h
@@ -30,17 +30,14 @@ using UsageInfoEntries = std::vector<UsageInfo>;
// Common callback types that are used throughout in the quota module.
using AddChangeListenerCallback = base::OnceCallback<void()>;
-using GlobalUsageCallback =
+using UsageCallback =
base::OnceCallback<void(int64_t usage, int64_t unlimited_usage)>;
using QuotaCallback =
base::OnceCallback<void(blink::mojom::QuotaStatusCode status,
int64_t quota)>;
-using UsageCallback = base::OnceCallback<void(int64_t usage)>;
using UsageWithBreakdownCallback =
base::OnceCallback<void(int64_t usage,
blink::mojom::UsageBreakdownPtr usage_breakdown)>;
-using AvailableSpaceCallback =
- base::OnceCallback<void(blink::mojom::QuotaStatusCode, int64_t)>;
using StatusCallback = base::OnceCallback<void(blink::mojom::QuotaStatusCode)>;
using GetBucketsCallback =
base::OnceCallback<void(const std::set<BucketLocator>& buckets,
diff --git a/chromium/storage/browser/quota/quota_database.cc b/chromium/storage/browser/quota/quota_database.cc
index a995b943c57..dc62026cc97 100644
--- a/chromium/storage/browser/quota/quota_database.cc
+++ b/chromium/storage/browser/quota/quota_database.cc
@@ -19,6 +19,7 @@
#include "base/metrics/histogram_functions.h"
#include "components/services/storage/public/cpp/buckets/constants.h"
#include "sql/database.h"
+#include "sql/error_metrics.h"
#include "sql/meta_table.h"
#include "sql/statement.h"
#include "sql/transaction.h"
@@ -52,7 +53,15 @@ const int kQuotaDatabaseCompatibleVersion = 8;
// Definitions for database schema.
const char kHostQuotaTable[] = "quota";
const char kBucketTable[] = "buckets";
+
+// Deprecated flag that ensured that the buckets table was bootstrapped
+// with existing storage key data for eviction logic.
+// TODO(crbug.com/1254535): Remove once enough time has passed to ensure that
+// this flag is no longer stored and supported in the QuotaDatabase.
const char kIsOriginTableBootstrapped[] = "IsOriginTableBootstrapped";
+// Flag to ensure that all existing data for storage keys have been
+// registered into the buckets table.
+const char kBucketsTableBootstrapped[] = "IsBucketsTableBootstrapped";
const int kCommitIntervalMs = 30000;
@@ -193,6 +202,26 @@ QuotaErrorOr<BucketInfo> QuotaDatabase::GetOrCreateBucket(
/*use_count=*/0, now, now);
}
+QuotaErrorOr<BucketInfo> QuotaDatabase::GetOrCreateBucketDeprecated(
+ const StorageKey& storage_key,
+ const std::string& bucket_name,
+ StorageType type) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ QuotaErrorOr<BucketInfo> bucket_result =
+ GetBucket(storage_key, bucket_name, type);
+
+ if (bucket_result.ok())
+ return bucket_result;
+
+ if (bucket_result.error() != QuotaError::kNotFound)
+ return bucket_result.error();
+
+ base::Time now = base::Time::Now();
+ return CreateBucketInternal(storage_key, type, bucket_name, /*use_count=*/0,
+ now, now);
+}
+
QuotaErrorOr<BucketInfo> QuotaDatabase::CreateBucketForTesting(
const StorageKey& storage_key,
const std::string& bucket_name,
@@ -326,7 +355,7 @@ QuotaError QuotaDatabase::SetStorageKeyLastAccessTime(
StorageType type,
base::Time last_accessed) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- QuotaError open_error = EnsureOpened(EnsureOpenedMode::kCreateIfNotFound);
+ QuotaError open_error = EnsureOpened(EnsureOpenedMode::kFailIfNotFound);
if (open_error != QuotaError::kNone)
return open_error;
@@ -335,15 +364,8 @@ QuotaError QuotaDatabase::SetStorageKeyLastAccessTime(
// TODO(crbug/1210252): Update to not execute 2 sql statements.
QuotaErrorOr<BucketInfo> result =
GetBucket(storage_key, kDefaultBucketName, type);
- if (!result.ok()) {
- if (result.error() != QuotaError::kNotFound)
- return result.error();
-
- QuotaErrorOr<BucketInfo> created_bucket =
- CreateBucketInternal(storage_key, type, kDefaultBucketName,
- /*use_count=*/1, last_accessed, last_accessed);
- return created_bucket.ok() ? QuotaError::kNone : created_bucket.error();
- }
+ if (!result.ok())
+ return result.error();
// clang-format off
static constexpr char kSql[] =
@@ -370,9 +392,12 @@ QuotaError QuotaDatabase::SetBucketLastAccessTime(BucketId bucket_id,
if (open_error != QuotaError::kNone)
return open_error;
- BucketTableEntry entry;
- if (!GetBucketInfo(bucket_id, &entry))
- return QuotaError::kNotFound;
+ // Check if bucket exists first. Running an update statement on a bucket that
+ // doesn't exist fails DCHECK and crashes.
+ // TODO(crbug/1210252): Update to not execute 2 sql statements.
+ QuotaErrorOr<BucketTableEntry> entry = GetBucketInfo(bucket_id);
+ if (!entry.ok())
+ return entry.error();
// clang-format off
static constexpr char kSql[] =
@@ -391,43 +416,6 @@ QuotaError QuotaDatabase::SetBucketLastAccessTime(BucketId bucket_id,
return QuotaError::kNone;
}
-QuotaError QuotaDatabase::SetStorageKeyLastModifiedTime(
- const StorageKey& storage_key,
- StorageType type,
- base::Time last_modified) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- QuotaError open_error = EnsureOpened(EnsureOpenedMode::kCreateIfNotFound);
- if (open_error != QuotaError::kNone)
- return open_error;
-
- // Check if bucket exists first. Running an update statement on a bucket that
- // doesn't exist fails DCHECK and crashes.
- // TODO(crbug/1210252): Update to not execute 2 sql statements.
- QuotaErrorOr<BucketInfo> result =
- GetBucket(storage_key, kDefaultBucketName, type);
- if (!result.ok()) {
- if (result.error() != QuotaError::kNotFound)
- return result.error();
-
- QuotaErrorOr<BucketInfo> created_bucket =
- CreateBucketInternal(storage_key, type, kDefaultBucketName,
- /*use_count=*/0, last_modified, last_modified);
- return created_bucket.ok() ? QuotaError::kNone : created_bucket.error();
- }
-
- static constexpr char kSql[] =
- "UPDATE buckets SET last_modified = ? WHERE id = ?";
- sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
- statement.BindTime(0, last_modified);
- statement.BindInt64(1, result->id.value());
-
- if (!statement.Run())
- return QuotaError::kDatabaseError;
-
- ScheduleCommit();
- return QuotaError::kNone;
-}
-
QuotaError QuotaDatabase::SetBucketLastModifiedTime(BucketId bucket_id,
base::Time last_modified) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -436,9 +424,12 @@ QuotaError QuotaDatabase::SetBucketLastModifiedTime(BucketId bucket_id,
if (open_error != QuotaError::kNone)
return open_error;
- BucketTableEntry entry;
- if (!GetBucketInfo(bucket_id, &entry))
- return QuotaError::kNotFound;
+ // Check if bucket exists first. Running an update statement on a bucket that
+ // doesn't exist fails DCHECK and crashes.
+ // TODO(crbug/1210252): Update to not execute 2 sql statements.
+ QuotaErrorOr<BucketTableEntry> entry = GetBucketInfo(bucket_id);
+ if (!entry.ok())
+ return entry.error();
static constexpr char kSql[] =
"UPDATE buckets SET last_modified = ? WHERE id = ?";
@@ -453,49 +444,52 @@ QuotaError QuotaDatabase::SetBucketLastModifiedTime(BucketId bucket_id,
return QuotaError::kNone;
}
-bool QuotaDatabase::RegisterInitialStorageKeyInfo(
- const std::set<StorageKey>& storage_keys,
- StorageType type) {
+QuotaError QuotaDatabase::RegisterInitialStorageKeyInfo(
+ base::flat_map<StorageType, std::set<StorageKey>> storage_keys_by_type) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (EnsureOpened(EnsureOpenedMode::kCreateIfNotFound) != QuotaError::kNone)
- return false;
+ QuotaError open_error = EnsureOpened(EnsureOpenedMode::kCreateIfNotFound);
+ if (open_error != QuotaError::kNone)
+ return open_error;
- for (const auto& storage_key : storage_keys) {
- static constexpr char kSql[] =
- // clang-format off
- "INSERT OR IGNORE INTO buckets("
- "storage_key,"
- "host,"
- "type,"
- "name,"
- "use_count,"
- "last_accessed,"
- "last_modified,"
- "expiration,"
- "quota) "
- "VALUES (?, ?, ?, ?, 0, 0, 0, ?, 0)";
- // clang-format on
- sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
- statement.BindString(0, storage_key.Serialize());
- statement.BindString(1, storage_key.origin().host());
- statement.BindInt(2, static_cast<int>(type));
- statement.BindString(3, kDefaultBucketName);
- statement.BindTime(4, base::Time::Max());
-
- if (!statement.Run())
- return false;
+ for (const auto& type_and_storage_keys : storage_keys_by_type) {
+ StorageType storage_type = type_and_storage_keys.first;
+ for (const auto& storage_key : type_and_storage_keys.second) {
+ static constexpr char kSql[] =
+ // clang-format off
+ "INSERT OR IGNORE INTO buckets("
+ "storage_key,"
+ "host,"
+ "type,"
+ "name,"
+ "use_count,"
+ "last_accessed,"
+ "last_modified,"
+ "expiration,"
+ "quota) "
+ "VALUES (?, ?, ?, ?, 0, 0, 0, ?, 0)";
+ // clang-format on
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindString(0, storage_key.Serialize());
+ statement.BindString(1, storage_key.origin().host());
+ statement.BindInt(2, static_cast<int>(storage_type));
+ statement.BindString(3, kDefaultBucketName);
+ statement.BindTime(4, base::Time::Max());
+
+ if (!statement.Run())
+ return QuotaError::kDatabaseError;
+ }
}
-
ScheduleCommit();
- return true;
+ return QuotaError::kNone;
}
-bool QuotaDatabase::GetBucketInfo(BucketId bucket_id,
- QuotaDatabase::BucketTableEntry* entry) {
+QuotaErrorOr<QuotaDatabase::BucketTableEntry> QuotaDatabase::GetBucketInfo(
+ BucketId bucket_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!bucket_id.is_null());
- if (EnsureOpened(EnsureOpenedMode::kFailIfNotFound) != QuotaError::kNone)
- return false;
+ QuotaError open_error = EnsureOpened(EnsureOpenedMode::kFailIfNotFound);
+ if (open_error != QuotaError::kNone)
+ return open_error;
static constexpr char kSql[] =
// clang-format off
@@ -512,19 +506,20 @@ bool QuotaDatabase::GetBucketInfo(BucketId bucket_id,
sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
statement.BindInt64(0, bucket_id.value());
- if (!statement.Step())
- return false;
+ if (!statement.Step()) {
+ return statement.Succeeded() ? QuotaError::kNotFound
+ : QuotaError::kDatabaseError;
+ }
absl::optional<StorageKey> storage_key =
StorageKey::Deserialize(statement.ColumnString(0));
if (!storage_key.has_value())
- return false;
+ return QuotaError::kNotFound;
- *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;
+ return 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));
}
QuotaError QuotaDatabase::DeleteHostQuota(const std::string& host,
@@ -547,26 +542,6 @@ QuotaError QuotaDatabase::DeleteHostQuota(const std::string& host,
return QuotaError::kNone;
}
-QuotaError QuotaDatabase::DeleteStorageKeyInfo(const StorageKey& storage_key,
- StorageType type) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- QuotaError open_error = EnsureOpened(EnsureOpenedMode::kFailIfNotFound);
- if (open_error != QuotaError::kNone)
- return open_error;
-
- static constexpr char kSql[] =
- "DELETE FROM buckets WHERE storage_key = ? AND type = ?";
- sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
- statement.BindString(0, storage_key.Serialize());
- statement.BindInt(1, static_cast<int>(type));
-
- if (!statement.Run())
- return QuotaError::kDatabaseError;
-
- ScheduleCommit();
- return QuotaError::kNone;
-}
-
QuotaError QuotaDatabase::DeleteBucketInfo(BucketId bucket_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!bucket_id.is_null());
@@ -687,21 +662,52 @@ QuotaErrorOr<std::set<BucketLocator>> QuotaDatabase::GetBucketsModifiedBetween(
return buckets;
}
-bool QuotaDatabase::IsBootstrappedForEviction() {
+bool QuotaDatabase::IsBootstrapped() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (EnsureOpened(EnsureOpenedMode::kCreateIfNotFound) != QuotaError::kNone)
return false;
int flag = 0;
- return meta_table_->GetValue(kIsOriginTableBootstrapped, &flag) && flag;
+ return meta_table_->GetValue(kBucketsTableBootstrapped, &flag) && flag;
}
-bool QuotaDatabase::SetBootstrappedForEviction(bool bootstrap_flag) {
+QuotaError QuotaDatabase::SetIsBootstrapped(bool bootstrap_flag) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (EnsureOpened(EnsureOpenedMode::kCreateIfNotFound) != QuotaError::kNone)
- return false;
+ QuotaError open_error = EnsureOpened(EnsureOpenedMode::kCreateIfNotFound);
+ if (open_error != QuotaError::kNone)
+ return open_error;
- return meta_table_->SetValue(kIsOriginTableBootstrapped, bootstrap_flag);
+ // Delete deprecated bootstrap flag if it still exists.
+ // TODO(crbug.com/1254535): Remove once enough time has passed to ensure that
+ // this flag is no longer stored and supported in the QuotaDatabase.
+ meta_table_->DeleteKey(kIsOriginTableBootstrapped);
+
+ return meta_table_->SetValue(kBucketsTableBootstrapped, bootstrap_flag)
+ ? QuotaError::kNone
+ : QuotaError::kDatabaseError;
+}
+
+QuotaError QuotaDatabase::CorruptForTesting(
+ base::OnceCallback<void(const base::FilePath&)> corrupter) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ if (db_) {
+ // Commit the long-running transaction.
+ db_->CommitTransaction();
+ db_->Close();
+ }
+
+ std::move(corrupter).Run(db_file_path_);
+
+ if (!db_)
+ return QuotaError::kDatabaseError;
+ if (!OpenDatabase())
+ return QuotaError::kDatabaseError;
+
+ // Begin a long-running transaction. This matches EnsureOpen().
+ if (!db_->BeginTransaction())
+ return QuotaError::kDatabaseError;
+ return QuotaError::kNone;
}
void QuotaDatabase::Commit() {
@@ -752,6 +758,13 @@ QuotaError QuotaDatabase::EnsureOpened(EnsureOpenedMode mode) {
db_->set_histogram_tag("Quota");
+ // UMA logging and don't crash on database errors in DCHECK builds.
+ db_->set_error_callback(
+ base::BindRepeating([](int sqlite_error_code, sql::Statement* statement) {
+ sql::UmaHistogramSqliteResult("Quota.QuotaDatabaseError",
+ sqlite_error_code);
+ }));
+
if (!OpenDatabase() || !EnsureDatabaseVersion()) {
LOG(ERROR) << "Could not open the quota database, resetting.";
if (!ResetSchema()) {
diff --git a/chromium/storage/browser/quota/quota_database.h b/chromium/storage/browser/quota/quota_database.h
index 84b0f5f22be..75de1871c82 100644
--- a/chromium/storage/browser/quota/quota_database.h
+++ b/chromium/storage/browser/quota/quota_database.h
@@ -13,7 +13,6 @@
#include <string>
#include "base/callback.h"
-#include "base/compiler_specific.h"
#include "base/component_export.h"
#include "base/files/file_path.h"
#include "base/sequence_checker.h"
@@ -56,7 +55,8 @@ enum class DatabaseResetReason {
//
// Instances are owned by QuotaManagerImpl. There is one instance per
// QuotaManagerImpl instance. All the methods of this class, except the
-// constructor, must called on the DB thread.
+// constructor, must called on the DB thread. QuotaDatabase should only be
+// subclassed in tests.
class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaDatabase {
public:
struct COMPONENT_EXPORT(STORAGE_BROWSER) BucketTableEntry {
@@ -88,7 +88,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaDatabase {
QuotaDatabase(const QuotaDatabase&) = delete;
QuotaDatabase& operator=(const QuotaDatabase&) = delete;
- ~QuotaDatabase();
+ virtual ~QuotaDatabase();
// Returns quota if entry is found. Returns QuotaError::kNotFound no entry if
// found.
@@ -111,6 +111,15 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaDatabase {
const blink::StorageKey& storage_key,
const std::string& bucket_name);
+ // Same as GetOrCreateBucket but takes in StorageType. This should only be
+ // used by FileSystem, and is expected to be removed when
+ // StorageType::kSyncable and StorageType::kPersistent are deprecated.
+ // (crbug.com/1233525, crbug.com/1286964).
+ QuotaErrorOr<BucketInfo> GetOrCreateBucketDeprecated(
+ const blink::StorageKey& storage_key,
+ const std::string& bucket_name,
+ blink::mojom::StorageType type);
+
// TODO(crbug.com/1208141): Remove `storage_type` when the only supported
// StorageType is kTemporary.
QuotaErrorOr<BucketInfo> CreateBucketForTesting(
@@ -144,49 +153,36 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaDatabase {
// TODO(crbug.com/1202167): Remove once all usages have updated to use
// SetBucketLastAccessTime.
- QuotaError SetStorageKeyLastAccessTime(const blink::StorageKey& storage_key,
- blink::mojom::StorageType type,
- base::Time last_accessed)
- WARN_UNUSED_RESULT;
+ [[nodiscard]] QuotaError 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. 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
// QuotaError::kNotFound. Returns QuotaError::kNone on a successful update.
- QuotaError SetBucketLastAccessTime(BucketId bucket_id,
- base::Time last_accessed)
- WARN_UNUSED_RESULT;
-
- // TODO(crbug.com/1202167): Remove once all usages have updated to use
- // SetBucketLastModifiedTime.
- QuotaError SetStorageKeyLastModifiedTime(const blink::StorageKey& storage_key,
- blink::mojom::StorageType type,
- base::Time last_modified)
- WARN_UNUSED_RESULT;
+ [[nodiscard]] QuotaError SetBucketLastAccessTime(BucketId bucket_id,
+ base::Time last_accessed);
// Called by QuotaClient implementers to update when the bucket was last
// modified. Returns QuotaError::kNone on a successful update.
- QuotaError SetBucketLastModifiedTime(BucketId bucket_id,
- base::Time last_modified)
- WARN_UNUSED_RESULT;
+ [[nodiscard]] QuotaError SetBucketLastModifiedTime(BucketId bucket_id,
+ base::Time last_modified);
- // Register initial `storage_keys` info `type` to the database.
+ // Register initial `storage_keys_by_type` into the database.
// This method is assumed to be called only after the installation or
// the database schema reset.
- bool RegisterInitialStorageKeyInfo(
- const std::set<blink::StorageKey>& storage_keys,
- blink::mojom::StorageType type);
-
- // Gets the table entry for `bucket`. Returns whether the record for an
- // origin bucket can be found.
- bool GetBucketInfo(BucketId bucket_id, BucketTableEntry* entry);
+ QuotaError RegisterInitialStorageKeyInfo(
+ base::flat_map<blink::mojom::StorageType, std::set<blink::StorageKey>>
+ storage_keys_by_type);
- // Removes all buckets for `storage_key` with `type`.
- QuotaError DeleteStorageKeyInfo(const blink::StorageKey& storage_key,
- blink::mojom::StorageType type);
+ // Returns the BucketTableEntry for `bucket` if one exists. Returns a
+ // QuotaError if not found or the operation has failed.
+ QuotaErrorOr<BucketTableEntry> GetBucketInfo(BucketId bucket_id);
- // Deletes the specified bucket.
- QuotaError DeleteBucketInfo(BucketId bucket_id);
+ // Deletes the specified bucket. This method is virtual for testing.
+ virtual QuotaError DeleteBucketInfo(BucketId bucket_id);
// Returns the BucketLocator for the least recently used bucket. Will exclude
// buckets with ids in `bucket_exceptions` and origins that have the special
@@ -207,11 +203,17 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaDatabase {
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 IsBootstrappedForEviction();
- bool SetBootstrappedForEviction(bool bootstrap_flag);
+ // Returns false if SetIsBootstrapped() has never been called before, which
+ // means existing storage keys may not have been registered. Bootstrapping
+ // ensures that there is a bucket entry in the buckets table for all storage
+ // keys that have stored data by quota managed Storage APIs.
+ bool IsBootstrapped();
+ QuotaError SetIsBootstrapped(bool bootstrap_flag);
+
+ // Returns QuotaError::kNone if the database was successfully reopened after
+ // `corrupter` was run, or QuotaError::kDatabaseError otherwise.
+ QuotaError CorruptForTesting(
+ base::OnceCallback<void(const base::FilePath&)> corrupter);
// Manually disable database to test database error scenarios for testing.
void SetDisabledForTesting(bool disable) { is_disabled_ = disable; }
diff --git a/chromium/storage/browser/quota/quota_database_unittest.cc b/chromium/storage/browser/quota/quota_database_unittest.cc
index 23c6820cae9..18f6f282e6d 100644
--- a/chromium/storage/browser/quota/quota_database_unittest.cc
+++ b/chromium/storage/browser/quota/quota_database_unittest.cc
@@ -12,6 +12,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/containers/contains.h"
+#include "base/containers/flat_map.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/test/metrics/histogram_tester.h"
@@ -20,6 +21,7 @@
#include "components/services/storage/public/cpp/buckets/bucket_locator.h"
#include "components/services/storage/public/cpp/buckets/constants.h"
#include "sql/database.h"
+#include "sql/error_metrics.h"
#include "sql/meta_table.h"
#include "sql/statement.h"
#include "sql/test/scoped_error_expecter.h"
@@ -44,10 +46,7 @@ static const blink::mojom::StorageType kPerm =
bool ContainsBucket(const std::set<BucketLocator>& buckets,
const BucketInfo& target_bucket) {
- BucketLocator target_bucket_locator(
- target_bucket.id, target_bucket.storage_key, target_bucket.type,
- target_bucket.name == kDefaultBucketName);
- auto it = buckets.find(target_bucket_locator);
+ auto it = buckets.find(target_bucket.ToBucketLocator());
return it != buckets.end();
}
@@ -250,6 +249,34 @@ TEST_P(QuotaDatabaseTest, GetOrCreateBucket) {
ASSERT_EQ(retrieved_bucket.type, created_bucket.type);
}
+TEST_P(QuotaDatabaseTest, GetOrCreateBucketDeprecated) {
+ QuotaDatabase db(use_in_memory_db() ? base::FilePath() : DbPath());
+ EXPECT_TRUE(EnsureOpened(&db, EnsureOpenedMode::kCreateIfNotFound));
+ StorageKey storage_key =
+ StorageKey::CreateFromStringForTesting("http://google/");
+ std::string bucket_name = "google_bucket";
+
+ QuotaErrorOr<BucketInfo> result =
+ db.GetOrCreateBucketDeprecated(storage_key, bucket_name, kPerm);
+ ASSERT_TRUE(result.ok());
+
+ 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);
+
+ // Should return the same bucket when querying again.
+ result = db.GetOrCreateBucketDeprecated(storage_key, bucket_name, kPerm);
+ 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, GetBucket) {
QuotaDatabase db(use_in_memory_db() ? base::FilePath() : DbPath());
EXPECT_TRUE(EnsureOpened(&db, EnsureOpenedMode::kCreateIfNotFound));
@@ -426,7 +453,7 @@ TEST_P(QuotaDatabaseTest, GetBucketWithNoDb) {
// 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)
+#if !BUILDFLAG(IS_FUCHSIA) && !BUILDFLAG(IS_WIN)
TEST_F(QuotaDatabaseTest, GetBucketWithOpenDatabaseError) {
base::HistogramTester histograms;
sql::test::ScopedErrorExpecter expecter;
@@ -449,66 +476,7 @@ TEST_F(QuotaDatabaseTest, GetBucketWithOpenDatabaseError) {
histograms.ExpectBucketCount("Quota.QuotaDatabaseReset",
DatabaseResetReason::kOpenDatabase, 1);
}
-#endif // !defined(OS_FUCHSIA) && !defined(OS_WIN)
-
-TEST_P(QuotaDatabaseTest, DeleteStorageKeyInfo) {
- QuotaDatabase db(use_in_memory_db() ? base::FilePath() : DbPath());
- EXPECT_TRUE(EnsureOpened(&db, EnsureOpenedMode::kCreateIfNotFound));
-
- 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);
-
- db.DeleteStorageKeyInfo(storage_key, kTemp);
-
- QuotaErrorOr<BucketInfo> result =
- db.GetBucket(storage_key, temp_bucket1->name, kTemp);
- ASSERT_FALSE(result.ok());
- ASSERT_EQ(result.error(), QuotaError::kNotFound);
-
- result = db.GetBucket(storage_key, temp_bucket2->name, kTemp);
- ASSERT_FALSE(result.ok());
- ASSERT_EQ(result.error(), QuotaError::kNotFound);
-
- result = db.GetBucket(storage_key, perm_bucket->name, kPerm);
- ASSERT_TRUE(result.ok());
-
- db.DeleteStorageKeyInfo(storage_key, kPerm);
-
- result = db.GetBucket(storage_key, perm_bucket->name, kPerm);
- ASSERT_FALSE(result.ok());
- ASSERT_EQ(result.error(), QuotaError::kNotFound);
-}
-
-TEST_P(QuotaDatabaseTest, SetStorageKeyLastModifiedTime) {
- QuotaDatabase db(use_in_memory_db() ? base::FilePath() : DbPath());
- EXPECT_TRUE(EnsureOpened(&db, EnsureOpenedMode::kCreateIfNotFound));
-
- const StorageKey storage_key =
- StorageKey::CreateFromStringForTesting("http://example/");
- base::Time now = base::Time::Now();
-
- // Should create a bucket if one doesn't exist.
- EXPECT_EQ(db.SetStorageKeyLastModifiedTime(storage_key, kTemp, now),
- QuotaError::kNone);
-
- QuotaErrorOr<BucketInfo> bucket =
- db.GetBucket(storage_key, kDefaultBucketName, kTemp);
- EXPECT_TRUE(bucket.ok());
-
- EXPECT_EQ(db.SetStorageKeyLastModifiedTime(storage_key, kTemp, now),
- QuotaError::kNone);
-
- QuotaDatabase::BucketTableEntry info;
- EXPECT_TRUE(db.GetBucketInfo(bucket->id, &info));
- EXPECT_EQ(now, info.last_modified);
- EXPECT_EQ(0, info.use_count);
-}
+#endif // !BUILDFLAG(IS_FUCHSIA) && !BUILDFLAG(IS_WIN)
TEST_P(QuotaDatabaseTest, BucketLastAccessTimeLRU) {
QuotaDatabase db(use_in_memory_db() ? base::FilePath() : DbPath());
@@ -616,21 +584,21 @@ TEST_P(QuotaDatabaseTest, SetStorageKeyLastAccessTime) {
StorageKey::CreateFromStringForTesting("http://example/");
base::Time now = base::Time::Now();
- // Should create a bucket if one doesn't exist.
+ // Should error if bucket doesn't exist.
EXPECT_EQ(db.SetStorageKeyLastAccessTime(storage_key, kTemp, now),
- QuotaError::kNone);
+ QuotaError::kNotFound);
QuotaErrorOr<BucketInfo> bucket =
- db.GetBucket(storage_key, kDefaultBucketName, kTemp);
- EXPECT_TRUE(bucket.ok());
+ db.CreateBucketForTesting(storage_key, kDefaultBucketName, kTemp);
EXPECT_EQ(db.SetStorageKeyLastAccessTime(storage_key, kTemp, now),
QuotaError::kNone);
- QuotaDatabase::BucketTableEntry info;
- EXPECT_TRUE(db.GetBucketInfo(bucket->id, &info));
- EXPECT_EQ(now, info.last_accessed);
- EXPECT_EQ(2, info.use_count);
+ QuotaErrorOr<QuotaDatabase::BucketTableEntry> info =
+ db.GetBucketInfo(bucket->id);
+ EXPECT_TRUE(info.ok());
+ EXPECT_EQ(now, info->last_accessed);
+ EXPECT_EQ(1, info->use_count);
}
TEST_P(QuotaDatabaseTest, GetStorageKeysForType) {
@@ -776,37 +744,44 @@ TEST_P(QuotaDatabaseTest, BucketLastModifiedBetween) {
TEST_P(QuotaDatabaseTest, RegisterInitialStorageKeyInfo) {
QuotaDatabase db(use_in_memory_db() ? base::FilePath() : DbPath());
+ base::flat_map<blink::mojom::StorageType, std::set<StorageKey>>
+ storage_keys_by_type;
const StorageKey kStorageKeys[] = {
StorageKey::CreateFromStringForTesting("http://a/"),
StorageKey::CreateFromStringForTesting("http://b/"),
StorageKey::CreateFromStringForTesting("http://c/")};
- std::set<StorageKey> storage_keys(kStorageKeys, std::end(kStorageKeys));
+ storage_keys_by_type.emplace(
+ kTemp, std::set<StorageKey>(kStorageKeys, std::end(kStorageKeys)));
+ storage_keys_by_type.emplace(
+ kPerm, std::set<StorageKey>(kStorageKeys, std::end(kStorageKeys)));
- EXPECT_TRUE(db.RegisterInitialStorageKeyInfo(storage_keys, kTemp));
+ EXPECT_EQ(db.RegisterInitialStorageKeyInfo(storage_keys_by_type),
+ QuotaError::kNone);
QuotaErrorOr<BucketInfo> bucket_result =
db.GetBucket(StorageKey::CreateFromStringForTesting("http://a/"),
kDefaultBucketName, kTemp);
ASSERT_TRUE(bucket_result.ok());
- QuotaDatabase::BucketTableEntry info;
- info.use_count = -1;
- EXPECT_TRUE(db.GetBucketInfo(bucket_result->id, &info));
- EXPECT_EQ(0, info.use_count);
+ QuotaErrorOr<QuotaDatabase::BucketTableEntry> info =
+ db.GetBucketInfo(bucket_result->id);
+ EXPECT_TRUE(info.ok());
+ EXPECT_EQ(0, info->use_count);
EXPECT_EQ(db.SetStorageKeyLastAccessTime(
StorageKey::CreateFromStringForTesting("http://a/"), kTemp,
base::Time::FromDoubleT(1.0)),
QuotaError::kNone);
- info.use_count = -1;
- EXPECT_TRUE(db.GetBucketInfo(bucket_result->id, &info));
- EXPECT_EQ(1, info.use_count);
+ info = db.GetBucketInfo(bucket_result->id);
+ EXPECT_TRUE(info.ok());
+ EXPECT_EQ(1, info->use_count);
- EXPECT_TRUE(db.RegisterInitialStorageKeyInfo(storage_keys, kTemp));
+ EXPECT_EQ(db.RegisterInitialStorageKeyInfo(storage_keys_by_type),
+ QuotaError::kNone);
- info.use_count = -1;
- EXPECT_TRUE(db.GetBucketInfo(bucket_result->id, &info));
- EXPECT_EQ(1, info.use_count);
+ info = db.GetBucketInfo(bucket_result->id);
+ EXPECT_TRUE(info.ok());
+ EXPECT_EQ(1, info->use_count);
}
TEST_P(QuotaDatabaseTest, DumpQuotaTable) {
@@ -864,33 +839,35 @@ TEST_P(QuotaDatabaseTest, GetBucketInfo) {
AssignBucketTable(&db, kTableEntries);
{
- Entry entry;
- 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].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);
- EXPECT_EQ(kTableEntries[0].last_modified, entry.last_modified);
+ QuotaErrorOr<QuotaDatabase::BucketTableEntry> entry =
+ db.GetBucketInfo(kTableEntries[0].bucket_id);
+ EXPECT_TRUE(entry.ok());
+ EXPECT_EQ(kTableEntries[0].bucket_id, entry->bucket_id);
+ EXPECT_EQ(kTableEntries[0].type, entry->type);
+ 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);
+ EXPECT_EQ(kTableEntries[0].last_modified, entry->last_modified);
}
{
// BucketId 456 is not in the database.
- Entry entry;
- EXPECT_FALSE(db.GetBucketInfo(BucketId(456), &entry));
+ QuotaErrorOr<QuotaDatabase::BucketTableEntry> entry =
+ db.GetBucketInfo(BucketId(456));
+ EXPECT_FALSE(entry.ok());
}
}
// Non-parameterized tests.
-TEST_F(QuotaDatabaseTest, BootstrapForEvictionFlag) {
+TEST_F(QuotaDatabaseTest, BootstrapFlag) {
QuotaDatabase db(DbPath());
- EXPECT_FALSE(db.IsBootstrappedForEviction());
- EXPECT_TRUE(db.SetBootstrappedForEviction(true));
- EXPECT_TRUE(db.IsBootstrappedForEviction());
- EXPECT_TRUE(db.SetBootstrappedForEviction(false));
- EXPECT_FALSE(db.IsBootstrappedForEviction());
+ EXPECT_FALSE(db.IsBootstrapped());
+ EXPECT_EQ(db.SetIsBootstrapped(true), QuotaError::kNone);
+ EXPECT_TRUE(db.IsBootstrapped());
+ EXPECT_EQ(db.SetIsBootstrapped(false), QuotaError::kNone);
+ EXPECT_FALSE(db.IsBootstrapped());
}
TEST_F(QuotaDatabaseTest, OpenCorruptedDatabase) {
@@ -913,6 +890,45 @@ TEST_F(QuotaDatabaseTest, OpenCorruptedDatabase) {
histograms.ExpectTotalCount("Quota.QuotaDatabaseReset", 1);
histograms.ExpectBucketCount("Quota.QuotaDatabaseReset",
DatabaseResetReason::kCreateSchema, 1);
+
+ EXPECT_GE(histograms.GetTotalSum("Quota.QuotaDatabaseError"), 1);
+ EXPECT_GE(histograms.GetBucketCount("Quota.QuotaDatabaseError",
+ sql::SqliteLoggedResultCode::kCorrupt),
+ 1);
+}
+
+TEST_F(QuotaDatabaseTest, GetOrCreateBucket_CorruptedDatabase) {
+ QuotaDatabase db(DbPath());
+ StorageKey storage_key =
+ StorageKey::CreateFromStringForTesting("http://google/");
+ std::string bucket_name = "google_bucket";
+
+ {
+ QuotaErrorOr<BucketInfo> result =
+ db.GetOrCreateBucket(storage_key, bucket_name);
+ ASSERT_TRUE(result.ok()) << "Failed to create bucket to be used in test";
+ }
+
+ // Bucket lookup uses the `buckets_by_storage_key` index.
+ QuotaError corruption_error =
+ db.CorruptForTesting(base::BindOnce([](const base::FilePath& db_path) {
+ ASSERT_TRUE(
+ sql::test::CorruptIndexRootPage(db_path, "buckets_by_storage_key"));
+ }));
+ ASSERT_EQ(QuotaError::kNone, corruption_error)
+ << "Failed to corrupt the database";
+
+ {
+ base::HistogramTester histograms;
+
+ QuotaErrorOr<BucketInfo> result =
+ db.GetOrCreateBucket(storage_key, bucket_name);
+ EXPECT_FALSE(result.ok());
+
+ histograms.ExpectTotalCount("Quota.QuotaDatabaseError", 1);
+ histograms.ExpectBucketCount("Quota.QuotaDatabaseError",
+ sql::SqliteLoggedResultCode::kCorrupt, 1);
+ }
}
INSTANTIATE_TEST_SUITE_P(All,
diff --git a/chromium/storage/browser/quota/quota_features.cc b/chromium/storage/browser/quota/quota_features.cc
index 04985ab9fc0..4d6dee2ee72 100644
--- a/chromium/storage/browser/quota/quota_features.cc
+++ b/chromium/storage/browser/quota/quota_features.cc
@@ -39,5 +39,10 @@ constexpr base::FeatureParam<double> kShouldRemainAvailableRatio{
&kStorageQuotaSettings, "ShouldRemainAvailableRatio", 0.1 /* 10% */
};
+// Whether the StoragePolicyObserver only sends updates for modified origins.
+const base::Feature kOnlySendStoragePolicyUpdatesForModifiedOrigins{
+ "OnlySendStoragePolicyUpdatesForModifiedOrigins",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
} // namespace features
} // namespace storage
diff --git a/chromium/storage/browser/quota/quota_features.h b/chromium/storage/browser/quota/quota_features.h
index 5cf4cb0b047..23bbafab57d 100644
--- a/chromium/storage/browser/quota/quota_features.h
+++ b/chromium/storage/browser/quota/quota_features.h
@@ -25,6 +25,9 @@ extern const base::FeatureParam<double> kPoolSizeRatio;
extern const base::FeatureParam<double> kShouldRemainAvailableBytes;
extern const base::FeatureParam<double> kShouldRemainAvailableRatio;
+COMPONENT_EXPORT(STORAGE_BROWSER)
+extern const base::Feature kOnlySendStoragePolicyUpdatesForModifiedOrigins;
+
} // namespace features
} // namespace storage
diff --git a/chromium/storage/browser/quota/quota_internals.mojom b/chromium/storage/browser/quota/quota_internals.mojom
new file mode 100644
index 00000000000..226b34d91b7
--- /dev/null
+++ b/chromium/storage/browser/quota/quota_internals.mojom
@@ -0,0 +1,24 @@
+// 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.
+
+module storage.mojom;
+
+import "url/mojom/origin.mojom";
+
+// Interface for controlling Quota Internals.
+// Hosted on chrome://quota-internals" for WebUI content::QuotaInternalsUI.
+interface QuotaInternalsHandler {
+ // Returns the total and available disk space in bits for a user,
+ // which is then converted to bytes and displayed on the Quota Internals UI.
+ GetDiskAvailability() => (uint64 total_space, uint64 available_space);
+
+ // Returns the following statistics:
+ // Errors on Getting Usage and Quota, Evicted Buckets, Evicted Rounds
+ // and Skipped Eviction Rounds.
+ GetStatistics() => (map<string, string> eviction_statistics);
+
+ // Used by the quota-internals page to test behavior of the storage pressure
+ // callback and trigger a storage pressure notification.
+ SimulateStoragePressure(url.mojom.Origin origin_url);
+}; \ No newline at end of file
diff --git a/chromium/storage/browser/quota/quota_manager_impl.cc b/chromium/storage/browser/quota/quota_manager_impl.cc
index 0ebb245ec41..cada5f89dd9 100644
--- a/chromium/storage/browser/quota/quota_manager_impl.cc
+++ b/chromium/storage/browser/quota/quota_manager_impl.cc
@@ -6,7 +6,6 @@
#include <stddef.h>
#include <stdint.h>
-#include <sstream>
#include <algorithm>
#include <functional>
@@ -16,16 +15,20 @@
#include "base/barrier_closure.h"
#include "base/bind.h"
+#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
+#include "base/containers/contains.h"
#include "base/files/file_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/rand_util.h"
#include "base/sequence_checker.h"
+#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/system/sys_info.h"
#include "base/task/post_task.h"
@@ -33,12 +36,14 @@
#include "base/task/single_thread_task_runner.h"
#include "base/task/task_runner_util.h"
#include "base/task/thread_pool.h"
+#include "base/thread_annotations.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "base/types/pass_key.h"
#include "components/services/storage/public/cpp/buckets/bucket_locator.h"
+#include "components/services/storage/public/cpp/buckets/constants.h"
#include "components/services/storage/public/mojom/quota_client.mojom.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "storage/browser/quota/client_usage_tracker.h"
@@ -103,6 +108,16 @@ QuotaErrorOr<BucketInfo> GetOrCreateBucketOnDBThread(
return database->GetOrCreateBucket(storage_key, bucket_name);
}
+QuotaErrorOr<BucketInfo> GetOrCreateBucketDeprecatedOnDBThread(
+ const StorageKey& storage_key,
+ const std::string& bucket_name,
+ blink::mojom::StorageType storage_type,
+ QuotaDatabase* database) {
+ DCHECK(database);
+ return database->GetOrCreateBucketDeprecated(storage_key, bucket_name,
+ storage_type);
+}
+
QuotaErrorOr<BucketInfo> CreateBucketOnDBThread(
const StorageKey& storage_key,
const std::string& bucket_name,
@@ -174,6 +189,11 @@ QuotaError SetPersistentHostQuotaOnDBThread(const std::string& host,
return database->SetHostQuota(host, StorageType::kPersistent, *new_quota);
}
+QuotaError SetDatabaseBootstrappedOnDBThread(QuotaDatabase* database) {
+ DCHECK(database);
+ return database->SetIsBootstrapped(true);
+}
+
QuotaErrorOr<BucketLocator> GetLRUBucketOnDBThread(
StorageType type,
const std::set<BucketId>& bucket_exceptions,
@@ -183,46 +203,26 @@ QuotaErrorOr<BucketLocator> GetLRUBucketOnDBThread(
return database->GetLRUBucket(type, bucket_exceptions, policy);
}
-QuotaError DeleteStorageKeyInfoOnDBThread(const StorageKey& storage_key,
- StorageType type,
- QuotaDatabase* database) {
- DCHECK(database);
- return database->DeleteStorageKeyInfo(storage_key, type);
-}
-
QuotaError DeleteBucketInfoOnDBThread(BucketId bucket_id,
- bool is_eviction,
QuotaDatabase* database) {
DCHECK(database);
-
- if (is_eviction) {
- base::Time now = base::Time::Now();
- QuotaDatabase::BucketTableEntry entry;
- database->GetBucketInfo(bucket_id, &entry);
- base::UmaHistogramCounts1M(
- QuotaManagerImpl::kEvictedBucketAccessedCountHistogram,
- entry.use_count);
- base::UmaHistogramCounts1000(
- QuotaManagerImpl::kEvictedBucketDaysSinceAccessHistogram,
- (now - entry.last_accessed).InDays());
- }
-
return database->DeleteBucketInfo(bucket_id);
}
-bool BootstrapDatabaseOnDBThread(std::set<StorageKey> storage_keys,
- QuotaDatabase* database) {
+QuotaErrorOr<QuotaDatabase::BucketTableEntry>
+GetBucketInfoForEvictionOnDBThread(BucketId bucket_id,
+ QuotaDatabase* database) {
DCHECK(database);
- if (database->IsBootstrappedForEviction())
- return true;
+ return database->GetBucketInfo(bucket_id);
+}
+QuotaError BootstrapDatabaseOnDBThread(
+ base::flat_map<StorageType, std::set<StorageKey>> storage_keys_by_type,
+ QuotaDatabase* database) {
+ DCHECK(database);
// Register existing storage keys with 0 last time access.
- if (database->RegisterInitialStorageKeyInfo(storage_keys,
- StorageType::kTemporary)) {
- database->SetBootstrappedForEviction(true);
- return true;
- }
- return false;
+ return database->RegisterInitialStorageKeyInfo(
+ std::move(storage_keys_by_type));
}
QuotaError UpdateAccessTimeOnDBThread(const StorageKey& storage_key,
@@ -241,15 +241,6 @@ QuotaError UpdateBucketAccessTimeOnDBThread(BucketId bucket_id,
return database->SetBucketLastAccessTime(bucket_id, accessed_time);
}
-QuotaError UpdateModifiedTimeOnDBThread(const StorageKey& storage_key,
- StorageType type,
- base::Time modified_time,
- QuotaDatabase* database) {
- DCHECK(database);
- return database->SetStorageKeyLastModifiedTime(storage_key, type,
- modified_time);
-}
-
QuotaError UpdateBucketModifiedTimeOnDBThread(BucketId bucket_id,
base::Time modified_time,
QuotaDatabase* database) {
@@ -263,6 +254,7 @@ void DidGetUsageAndQuotaStripBreakdown(
int64_t usage,
int64_t quota,
blink::mojom::UsageBreakdownPtr usage_breakdown) {
+ DCHECK(callback);
std::move(callback).Run(status, usage, quota);
}
@@ -273,6 +265,7 @@ void DidGetUsageAndQuotaStripOverride(
int64_t quota,
bool is_override_enabled,
blink::mojom::UsageBreakdownPtr usage_breakdown) {
+ DCHECK(callback);
std::move(callback).Run(status, usage, quota, std::move(usage_breakdown));
}
@@ -283,6 +276,7 @@ constexpr int64_t QuotaManagerImpl::kNoLimit;
constexpr int64_t QuotaManagerImpl::kPerHostPersistentQuotaLimit;
constexpr int QuotaManagerImpl::kEvictionIntervalInMilliSeconds;
constexpr int QuotaManagerImpl::kThresholdOfErrorsToBeDenylisted;
+constexpr int QuotaManagerImpl::kThresholdOfErrorsToDisableDatabase;
constexpr int QuotaManagerImpl::kThresholdRandomizationPercent;
constexpr char QuotaManagerImpl::kDatabaseName[];
constexpr char QuotaManagerImpl::kEvictedBucketAccessedCountHistogram[];
@@ -309,7 +303,10 @@ class QuotaManagerImpl::UsageAndQuotaInfoGatherer : public QuotaTask {
is_session_only_(is_session_only),
is_incognito_(is_incognito),
is_override_enabled_(quota_override_size.has_value()),
- quota_override_size_(quota_override_size) {}
+ quota_override_size_(quota_override_size) {
+ DCHECK(manager);
+ DCHECK(callback_);
+ }
protected:
void Run() override {
@@ -404,14 +401,16 @@ class QuotaManagerImpl::UsageAndQuotaInfoGatherer : public QuotaTask {
void OnGotSettings(base::RepeatingClosure barrier_closure,
const QuotaSettings& settings) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(barrier_closure);
+
settings_ = settings;
barrier_closure.Run();
if (type_ == StorageType::kTemporary && !is_unlimited_) {
int64_t host_quota = is_session_only_
? settings.session_only_per_host_quota
: settings.per_host_quota;
- SetDesiredHostQuota(barrier_closure, blink::mojom::QuotaStatusCode::kOk,
- host_quota);
+ SetDesiredHostQuota(std::move(barrier_closure),
+ blink::mojom::QuotaStatusCode::kOk, host_quota);
}
}
@@ -419,6 +418,10 @@ class QuotaManagerImpl::UsageAndQuotaInfoGatherer : public QuotaTask {
int64_t total_space,
int64_t available_space) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(barrier_closure);
+ DCHECK_GE(total_space, 0);
+ DCHECK_GE(available_space, 0);
+
total_space_ = total_space;
available_space_ = available_space;
std::move(barrier_closure).Run();
@@ -428,6 +431,16 @@ class QuotaManagerImpl::UsageAndQuotaInfoGatherer : public QuotaTask {
int64_t usage,
blink::mojom::UsageBreakdownPtr usage_breakdown) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(barrier_closure);
+ DCHECK_GE(usage, -1);
+ DCHECK(usage_breakdown);
+ DCHECK_GE(usage_breakdown->backgroundFetch, 0);
+ DCHECK_GE(usage_breakdown->fileSystem, 0);
+ DCHECK_GE(usage_breakdown->indexedDatabase, 0);
+ DCHECK_GE(usage_breakdown->serviceWorker, 0);
+ DCHECK_GE(usage_breakdown->serviceWorkerCache, 0);
+ DCHECK_GE(usage_breakdown->webSql, 0);
+
host_usage_ = usage;
host_usage_breakdown_ = std::move(usage_breakdown);
std::move(barrier_closure).Run();
@@ -437,6 +450,9 @@ class QuotaManagerImpl::UsageAndQuotaInfoGatherer : public QuotaTask {
blink::mojom::QuotaStatusCode status,
int64_t quota) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(barrier_closure);
+ DCHECK_GE(quota, 0);
+
desired_host_quota_ = quota;
std::move(barrier_closure).Run();
}
@@ -515,6 +531,8 @@ class QuotaManagerImpl::EvictionRoundInfoHelper {
void OnGotSettings(base::OnceClosure barrier_closure,
const QuotaSettings& settings) {
+ DCHECK(barrier_closure);
+
settings_ = settings;
std::move(barrier_closure).Run();
}
@@ -522,6 +540,10 @@ class QuotaManagerImpl::EvictionRoundInfoHelper {
void OnGotCapacity(base::OnceClosure barrier_closure,
int64_t total_space,
int64_t available_space) {
+ DCHECK(barrier_closure);
+ DCHECK_GE(total_space, 0);
+ DCHECK_GE(available_space, 0);
+
total_space_ = total_space;
available_space_ = available_space;
std::move(barrier_closure).Run();
@@ -572,7 +594,10 @@ class QuotaManagerImpl::EvictionRoundInfoHelper {
class QuotaManagerImpl::GetUsageInfoTask : public QuotaTask {
public:
GetUsageInfoTask(QuotaManagerImpl* manager, GetUsageInfoCallback callback)
- : QuotaTask(manager), callback_(std::move(callback)) {}
+ : QuotaTask(manager), callback_(std::move(callback)) {
+ DCHECK(manager);
+ DCHECK(callback_);
+ }
protected:
void Run() override {
@@ -601,8 +626,8 @@ class QuotaManagerImpl::GetUsageInfoTask : public QuotaTask {
}
private:
- void AddEntries(StorageType type, UsageTracker* tracker) {
- std::map<std::string, int64_t> host_usage = tracker->GetCachedHostsUsage();
+ void AddEntries(StorageType type, UsageTracker& tracker) {
+ std::map<std::string, int64_t> host_usage = tracker.GetCachedHostsUsage();
for (const auto& host_usage_pair : host_usage) {
entries_.emplace_back(host_usage_pair.first, type,
host_usage_pair.second);
@@ -612,8 +637,9 @@ class QuotaManagerImpl::GetUsageInfoTask : public QuotaTask {
}
void DidGetGlobalUsage(StorageType type, int64_t, int64_t) {
- DCHECK(manager()->GetUsageTracker(type));
- AddEntries(type, manager()->GetUsageTracker(type));
+ UsageTracker* tracker = manager()->GetUsageTracker(type);
+ DCHECK(tracker);
+ AddEntries(type, *tracker);
}
QuotaManagerImpl* manager() const {
@@ -626,152 +652,158 @@ class QuotaManagerImpl::GetUsageInfoTask : public QuotaTask {
base::WeakPtrFactory<GetUsageInfoTask> weak_factory_{this};
};
-// Calls each QuotaClient for `quota_client_types` to delete `storage_key` data.
-// If `storage_key` is delete for all registered client types, and there are no
-// deletion errors, StorageKeyDataDeleter will call to delete `storage_key` from
-// QuotaDatabase. It will return QuotaStatusCode::kOk to the `callback` on
-// success and will finish by making a call to delete itself.
-class QuotaManagerImpl::StorageKeyDataDeleter : public QuotaTask {
+class QuotaManagerImpl::StorageKeyGathererTask {
public:
- StorageKeyDataDeleter(QuotaManagerImpl* manager,
- const StorageKey& storage_key,
- StorageType type,
- QuotaClientTypes quota_client_types,
- StatusCallback callback)
- : QuotaTask(manager),
- storage_key_(storage_key),
- type_(type),
- quota_client_types_(std::move(quota_client_types)),
- callback_(std::move(callback)) {}
+ StorageKeyGathererTask(QuotaManagerImpl* manager,
+ base::OnceCallback<void(StorageKeysByType)> callback)
+ : manager_(manager), callback_(std::move(callback)) {
+ DCHECK(manager_);
+ DCHECK(callback_);
+ }
- protected:
- void Run() override {
- DCHECK(manager()->client_types_.contains(type_));
- remaining_clients_ = manager()->client_types_[type_].size();
+ void Run() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+#if DCHECK_IS_ON()
+ DCHECK(!run_called_) << __func__ << " already called";
+ run_called_ = true;
+#endif // DCHECK_IS_ON()
- for (const auto& client_and_type : manager()->client_types_[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;
- 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_;
- --remaining_clients_;
- }
+ size_t client_call_count = 0;
+ for (const auto& client_and_type : manager_->client_types_)
+ client_call_count += client_and_type.second.size();
+
+ // Registered clients can be empty in tests.
+ if (!client_call_count) {
+ Completed();
+ return;
}
- if (remaining_clients_ == 0)
- CallCompleted();
+ base::RepeatingClosure barrier = base::BarrierClosure(
+ client_call_count,
+ base::BindOnce(&QuotaManagerImpl::StorageKeyGathererTask::Completed,
+ weak_factory_.GetWeakPtr()));
+
+ GetStorageKeysForType(StorageType::kTemporary, barrier);
+ GetStorageKeysForType(StorageType::kPersistent, barrier);
+ GetStorageKeysForType(StorageType::kSyncable, barrier);
}
- void Completed() override {
- if (error_count_ == 0) {
- // Only remove the entire storage key if we didn't skip any client types.
- if (skipped_clients_ == 0)
- manager()->DeleteStorageKeyFromDatabase(storage_key_, type_);
- std::move(callback_).Run(blink::mojom::QuotaStatusCode::kOk);
- } else {
- std::move(callback_).Run(
- blink::mojom::QuotaStatusCode::kErrorInvalidModification);
+ private:
+ void GetStorageKeysForType(StorageType type, base::RepeatingClosure barrier) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ auto client_map_it = manager_->client_types_.find(type);
+ DCHECK(client_map_it != manager_->client_types_.end());
+ DCHECK(barrier);
+
+ for (const auto& client_and_type : client_map_it->second) {
+ client_and_type.first->GetStorageKeysForType(
+ type, base::BindOnce(&StorageKeyGathererTask::DidGetStorageKeys,
+ weak_factory_.GetWeakPtr(), type, barrier));
}
- DeleteSoon();
}
- void Aborted() override {
- std::move(callback_).Run(blink::mojom::QuotaStatusCode::kErrorAbort);
- DeleteSoon();
- }
+ void DidGetStorageKeys(StorageType type,
+ base::OnceClosure barrier,
+ const std::vector<StorageKey>& storage_keys) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(barrier);
- private:
- void DidDeleteStorageKeyData(int tracing_id,
- blink::mojom::QuotaStatusCode status) {
- DCHECK_GT(remaining_clients_, 0U);
- TRACE_EVENT_NESTABLE_ASYNC_END0(
- "browsing_data", "QuotaManagerImpl::StorageKeyDataDeleter", tracing_id);
+ storage_keys_by_type_[type].insert(storage_keys.begin(),
+ storage_keys.end());
+ std::move(barrier).Run();
+ }
- if (status != blink::mojom::QuotaStatusCode::kOk)
- ++error_count_;
+ void Completed() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+#if DCHECK_IS_ON()
+ DCHECK(!completed_called_) << __func__ << " already called";
+ completed_called_ = true;
+#endif // DCHECK_IS_ON()
- if (--remaining_clients_ == 0)
- CallCompleted();
+ // Deletes `this`.
+ std::move(callback_).Run(storage_keys_by_type_);
}
- QuotaManagerImpl* manager() const {
- return static_cast<QuotaManagerImpl*>(observer());
- }
+ SEQUENCE_CHECKER(sequence_checker_);
+ QuotaManagerImpl* manager_ GUARDED_BY_CONTEXT(sequence_checker_);
+ base::OnceCallback<void(StorageKeysByType)> callback_
+ GUARDED_BY_CONTEXT(sequence_checker_);
+ StorageKeysByType storage_keys_by_type_ GUARDED_BY_CONTEXT(sequence_checker_);
- const StorageKey storage_key_;
- const StorageType type_;
- const QuotaClientTypes quota_client_types_;
- int error_count_ = 0;
- size_t remaining_clients_ = 0;
- int skipped_clients_ = 0;
- StatusCallback callback_;
+#if DCHECK_IS_ON()
+ bool run_called_ = false;
+ bool completed_called_ = false;
+#endif // DCHECK_IS_ON()
- base::WeakPtrFactory<StorageKeyDataDeleter> weak_factory_{this};
+ base::WeakPtrFactory<StorageKeyGathererTask> weak_factory_
+ GUARDED_BY_CONTEXT(sequence_checker_){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 {
+// Calls QuotaClients in `quota_client_types` for the `bucket` to delete bucket
+// data. Will delete bucket entries from the QuotaDatabase if bucket data has
+// been successfully deleted from all registered QuotaClient.
+// This is currently only for the default bucket. If a non-default bucket is to
+// be deleted, it will immediately complete the task since non-default bucket
+// usage is not being tracked by QuotaClients yet.
+class QuotaManagerImpl::BucketDataDeleter {
public:
- BucketDataDeleter(QuotaManagerImpl* manager,
- const BucketLocator& bucket,
- QuotaClientTypes quota_client_types,
- bool is_eviction,
- StatusCallback callback)
- : QuotaTask(manager),
+ // `callback` will be run to report the status of the deletion on task
+ // completion. `callback` will only be called while this BucketDataDeleter
+ // instance is alive. `callback` may destroy this BucketDataDeleter instance.
+ BucketDataDeleter(
+ QuotaManagerImpl* manager,
+ const BucketLocator& bucket,
+ QuotaClientTypes quota_client_types,
+ base::OnceCallback<void(BucketDataDeleter*,
+ blink::mojom::QuotaStatusCode)> callback)
+ : manager_(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));
+ callback_(std::move(callback)) {
+ DCHECK(manager_);
+ // TODO(crbug/1292216): Convert back into DCHECKs once issue is resolved.
+ CHECK(callback_);
+ }
- // 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;
+ ~BucketDataDeleter() {
+ // `callback` is non-null if the deleter gets destroyed before completing.
+ if (callback_) {
+ std::move(callback_).Run(this,
+ blink::mojom::QuotaStatusCode::kErrorAbort);
}
+ }
+
+ void Run() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+#if DCHECK_IS_ON()
+ // TODO(crbug/1292216): Convert back into DCHECK once issue is resolved.
+ CHECK(!run_called_) << __func__ << " already called";
+ run_called_ = true;
+#endif // DCHECK_IS_ON()
+
+ DCHECK(manager_->client_types_.contains(bucket_.type));
- remaining_clients_ = manager()->client_types_[bucket_.type].size();
+ remaining_clients_ = manager_->client_types_[bucket_.type].size();
+ UsageTracker* usage_tracker = manager_->GetUsageTracker(bucket_.type);
- for (const auto& client_and_type : manager()->client_types_[bucket_.type]) {
+ 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)) {
+ // Delete cached usage.
+ usage_tracker->DeleteBucketCache(client_type, bucket_);
+
static int tracing_id = 0;
- std::ostringstream bucket_params;
- bucket_params << "storage_key: " << bucket_.storage_key.Serialize()
- << ", is_default: " << bucket_.is_default
- << ", id: " << bucket_.id;
+ std::string bucket_params = base::StrCat(
+ {"storage_key: ", bucket_.storage_key.Serialize(),
+ ", is_default: ", bucket_.is_default ? "true" : "false",
+ ", id: ", base::NumberToString(bucket_.id.value())});
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));
+ ++tracing_id, "client_type", client_type, "bucket", bucket_params);
+ client->DeleteBucketData(
+ bucket_, base::BindOnce(&BucketDataDeleter::DidDeleteBucketData,
+ weak_factory_.GetWeakPtr(), tracing_id));
} else {
++skipped_clients_;
--remaining_clients_;
@@ -779,31 +811,19 @@ class QuotaManagerImpl::BucketDataDeleter : public QuotaTask {
}
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();
+ FinishDeletion();
}
- void Aborted() override {
- std::move(callback_).Run(blink::mojom::QuotaStatusCode::kErrorAbort);
- DeleteSoon();
+ bool completed() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return !callback_;
}
private:
void DidDeleteBucketData(int tracing_id,
blink::mojom::QuotaStatusCode status) {
- DCHECK_GT(remaining_clients_, 0U);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_GT(remaining_clients_, 0u);
TRACE_EVENT_NESTABLE_ASYNC_END0(
"browsing_data", "QuotaManagerImpl::BucketDataDeleter", tracing_id);
@@ -811,115 +831,184 @@ class QuotaManagerImpl::BucketDataDeleter : public QuotaTask {
++error_count_;
if (--remaining_clients_ == 0)
- CallCompleted();
+ FinishDeletion();
}
- QuotaManagerImpl* manager() const {
- return static_cast<QuotaManagerImpl*>(observer());
+ void FinishDeletion() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // TODO(crbug/1292216): Convert back into DCHECKs once issue is resolved.
+ CHECK_EQ(remaining_clients_, 0u);
+ CHECK(callback_) << __func__ << " called after Complete";
+
+ // Only remove the bucket from the database if we didn't skip any client
+ // types.
+ if (skipped_clients_ == 0 && error_count_ == 0) {
+ manager_->DeleteBucketFromDatabase(
+ bucket_.id,
+ base::BindOnce(&BucketDataDeleter::DidDeleteBucketFromDatabase,
+ weak_factory_.GetWeakPtr()));
+ return;
+ }
+ Complete(/*success=*/error_count_ == 0);
+ }
+
+ void DidDeleteBucketFromDatabase(QuotaError result) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ manager_->DidDatabaseWork(result != QuotaError::kDatabaseError);
+ Complete(result == QuotaError::kNone);
+ }
+
+ void Complete(bool success) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // TODO(crbug/1292216): Convert back into DCHECKs once issue is resolved.
+ CHECK_EQ(remaining_clients_, 0u);
+ CHECK(callback_);
+
+ // May delete `this`.
+ std::move(callback_).Run(
+ this, success
+ ? blink::mojom::QuotaStatusCode::kOk
+ : blink::mojom::QuotaStatusCode::kErrorInvalidModification);
}
+ SEQUENCE_CHECKER(sequence_checker_);
+ QuotaManagerImpl* const manager_ GUARDED_BY_CONTEXT(sequence_checker_);
const BucketLocator 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_;
+ int error_count_ GUARDED_BY_CONTEXT(sequence_checker_) = 0;
+ size_t remaining_clients_ GUARDED_BY_CONTEXT(sequence_checker_) = 0;
+ int skipped_clients_ GUARDED_BY_CONTEXT(sequence_checker_) = 0;
+
+ // Running the callback may delete this instance.
+ base::OnceCallback<void(BucketDataDeleter*, blink::mojom::QuotaStatusCode)>
+ callback_ GUARDED_BY_CONTEXT(sequence_checker_);
+
+#if DCHECK_IS_ON()
+ bool run_called_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
+#endif // DCHECK_IS_ON()
- base::WeakPtrFactory<BucketDataDeleter> weak_factory_{this};
+ base::WeakPtrFactory<BucketDataDeleter> weak_factory_
+ GUARDED_BY_CONTEXT(sequence_checker_){this};
};
-class QuotaManagerImpl::HostDataDeleter : public QuotaTask {
+// Retrieves all buckets for `host` from QuotaDatabase and calls
+// BucketDataDeleter for all registered QuotaClientTypes.
+class QuotaManagerImpl::HostDataDeleter {
public:
- HostDataDeleter(QuotaManagerImpl* manager,
- const std::string& host,
- StorageType type,
- QuotaClientTypes quota_client_types,
- StatusCallback callback)
- : QuotaTask(manager),
+ // `callback` will be run to report the status of the deletion on task
+ // completion. `callback` will only be called while this HostDataDeleter
+ // instance is alive. `callback` may destroy this HostDataDeleter instance.
+ HostDataDeleter(
+ QuotaManagerImpl* manager,
+ const std::string& host,
+ StorageType type,
+ base::OnceCallback<void(HostDataDeleter*, blink::mojom::QuotaStatusCode)>
+ callback)
+ : manager_(manager),
host_(host),
type_(type),
- quota_client_types_(std::move(quota_client_types)),
- error_count_(0),
- remaining_clients_(0),
- remaining_deleters_(0),
- callback_(std::move(callback)) {}
-
- protected:
- void Run() override {
- DCHECK(manager()->client_types_.contains(type_));
- remaining_clients_ = manager()->client_types_[type_].size();
+ callback_(std::move(callback)) {
+ DCHECK(manager_);
+ DCHECK(callback_);
+ }
- for (const auto& client_and_type : manager()->client_types_[type_]) {
- client_and_type.first->GetStorageKeysForHost(
- type_, host_,
- base::BindOnce(&HostDataDeleter::DidGetStorageKeysForHost,
- weak_factory_.GetWeakPtr()));
+ ~HostDataDeleter() {
+ if (callback_) {
+ std::move(callback_).Run(this,
+ blink::mojom::QuotaStatusCode::kErrorAbort);
}
}
- void Completed() override {
- if (error_count_ == 0) {
- std::move(callback_).Run(blink::mojom::QuotaStatusCode::kOk);
- } else {
- std::move(callback_).Run(
- blink::mojom::QuotaStatusCode::kErrorInvalidModification);
- }
- DeleteSoon();
+ void Run() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+#if DCHECK_IS_ON()
+ DCHECK(!run_called_) << __func__ << " already called";
+ run_called_ = true;
+#endif // DCHECK_IS_ON()
+ manager_->GetBucketsForHost(
+ host_, type_,
+ base::BindOnce(&HostDataDeleter::DidGetBucketsForHost,
+ weak_factory_.GetWeakPtr()));
}
- void Aborted() override {
- std::move(callback_).Run(blink::mojom::QuotaStatusCode::kErrorAbort);
- DeleteSoon();
+ bool completed() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return !callback_;
}
private:
- void DidGetStorageKeysForHost(const std::vector<StorageKey>& storage_keys) {
- DCHECK_GT(remaining_clients_, 0U);
-
- storage_keys_.insert(storage_keys.begin(), storage_keys.end());
+ void DidGetBucketsForHost(QuotaErrorOr<std::set<BucketLocator>> result) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!result.ok()) {
+ Complete(/*success=*/false);
+ return;
+ }
- if (--remaining_clients_ == 0) {
- if (!storage_keys_.empty())
- ScheduleStorageKeysDeletion();
- else
- CallCompleted();
+ buckets_ = result.value();
+ if (!buckets_.empty()) {
+ ScheduleBucketsDeletion();
+ return;
}
+ Complete(/*success=*/true);
}
- 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 ScheduleBucketsDeletion() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ for (const auto& bucket : buckets_) {
+ // base::Unretained() is safe here because `this` is guaranteed to outlive
+ // the callback, thanks to an indirect ownership chain. `this` owns the
+ // BucketDataDeleter created here, which guarantees it will only use the
+ // callback when it's alive.
+ auto bucket_deleter = std::make_unique<BucketDataDeleter>(
+ manager_, bucket, AllQuotaClientTypes(),
+ base::BindOnce(&HostDataDeleter::DidDeleteBucketData,
+ base::Unretained(this)));
+ auto* bucket_deleter_ptr = bucket_deleter.get();
+ bucket_deleters_[bucket_deleter_ptr] = std::move(bucket_deleter);
+ bucket_deleter_ptr->Run();
}
}
- void DidDeleteStorageKeyData(blink::mojom::QuotaStatusCode status) {
- DCHECK_GT(remaining_deleters_, 0U);
+ void DidDeleteBucketData(BucketDataDeleter* deleter,
+ blink::mojom::QuotaStatusCode status) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(deleter->completed());
+
+ DCHECK(base::Contains(bucket_deleters_, deleter));
+ bucket_deleters_.erase(deleter);
if (status != blink::mojom::QuotaStatusCode::kOk)
++error_count_;
- if (--remaining_deleters_ == 0)
- CallCompleted();
+ if (bucket_deleters_.empty())
+ Complete(/*success=*/error_count_ == 0);
}
- QuotaManagerImpl* manager() const {
- return static_cast<QuotaManagerImpl*>(observer());
+ void Complete(bool success) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback_);
+
+ // May delete `this`.
+ std::move(callback_).Run(
+ this, success
+ ? blink::mojom::QuotaStatusCode::kOk
+ : blink::mojom::QuotaStatusCode::kErrorInvalidModification);
}
+ SEQUENCE_CHECKER(sequence_checker_);
+ QuotaManagerImpl* const manager_ GUARDED_BY_CONTEXT(sequence_checker_);
const std::string host_;
const StorageType type_;
- const QuotaClientTypes quota_client_types_;
- std::set<StorageKey> storage_keys_;
- int error_count_;
- size_t remaining_clients_;
- size_t remaining_deleters_;
- StatusCallback callback_;
+ std::map<BucketDataDeleter*, std::unique_ptr<BucketDataDeleter>>
+ bucket_deleters_;
+ std::set<BucketLocator> buckets_ GUARDED_BY_CONTEXT(sequence_checker_);
+ int error_count_ GUARDED_BY_CONTEXT(sequence_checker_) = 0;
+ base::OnceCallback<void(HostDataDeleter*, blink::mojom::QuotaStatusCode)>
+ callback_ GUARDED_BY_CONTEXT(sequence_checker_);
+
+#if DCHECK_IS_ON()
+ bool run_called_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
+#endif // DCHECK_IS_ON()
base::WeakPtrFactory<HostDataDeleter> weak_factory_{this};
};
@@ -934,7 +1023,9 @@ class QuotaManagerImpl::StorageCleanupHelper : public QuotaTask {
type_(type),
quota_client_types_(std::move(quota_client_types)),
callback_(std::move(callback)) {
+ DCHECK(manager);
DCHECK(manager->client_types_.contains(type_));
+ DCHECK(callback_);
}
protected:
@@ -1096,22 +1187,52 @@ void QuotaManagerImpl::GetOrCreateBucket(
const std::string& bucket_name,
base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
EnsureDatabaseOpened();
+ if (db_disabled_) {
+ std::move(callback).Run(QuotaError::kDatabaseError);
+ return;
+ }
PostTaskAndReplyWithResultForDBThread(
base::BindOnce(&GetOrCreateBucketOnDBThread, storage_key, bucket_name),
base::BindOnce(&QuotaManagerImpl::DidGetBucket,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
+void QuotaManagerImpl::GetOrCreateBucketDeprecated(
+ const StorageKey& storage_key,
+ const std::string& bucket_name,
+ blink::mojom::StorageType storage_type,
+ base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
+ EnsureDatabaseOpened();
+
+ if (db_disabled_) {
+ std::move(callback).Run(QuotaError::kDatabaseError);
+ return;
+ }
+ PostTaskAndReplyWithResultForDBThread(
+ base::BindOnce(&GetOrCreateBucketDeprecatedOnDBThread, storage_key,
+ bucket_name, storage_type),
+ base::BindOnce(&QuotaManagerImpl::DidGetBucket,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
+}
+
void QuotaManagerImpl::CreateBucketForTesting(
const StorageKey& storage_key,
const std::string& bucket_name,
blink::mojom::StorageType storage_type,
base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
EnsureDatabaseOpened();
+ if (db_disabled_) {
+ std::move(callback).Run(QuotaError::kDatabaseError);
+ return;
+ }
PostTaskAndReplyWithResultForDBThread(
base::BindOnce(&CreateBucketOnDBThread, storage_key, bucket_name,
storage_type),
@@ -1125,8 +1246,13 @@ void QuotaManagerImpl::GetBucket(
blink::mojom::StorageType type,
base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
EnsureDatabaseOpened();
+ if (db_disabled_) {
+ std::move(callback).Run(QuotaError::kDatabaseError);
+ return;
+ }
PostTaskAndReplyWithResultForDBThread(
base::BindOnce(&GetBucketOnDBThread, storage_key, bucket_name, type),
base::BindOnce(&QuotaManagerImpl::DidGetBucket,
@@ -1136,8 +1262,13 @@ void QuotaManagerImpl::GetBucket(
void QuotaManagerImpl::GetStorageKeysForType(blink::mojom::StorageType type,
GetStorageKeysCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
EnsureDatabaseOpened();
+ if (db_disabled_) {
+ std::move(callback).Run(std::set<StorageKey>());
+ return;
+ }
PostTaskAndReplyWithResultForDBThread(
base::BindOnce(&GetStorageKeysForTypeOnDBThread, type),
base::BindOnce(&QuotaManagerImpl::DidGetStorageKeys,
@@ -1148,8 +1279,13 @@ void QuotaManagerImpl::GetBucketsForType(
blink::mojom::StorageType type,
base::OnceCallback<void(QuotaErrorOr<std::set<BucketLocator>>)> callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
EnsureDatabaseOpened();
+ if (db_disabled_) {
+ std::move(callback).Run(QuotaError::kDatabaseError);
+ return;
+ }
PostTaskAndReplyWithResultForDBThread(
base::BindOnce(&GetBucketsForTypeOnDBThread, type),
base::BindOnce(&QuotaManagerImpl::DidGetBuckets,
@@ -1161,8 +1297,13 @@ void QuotaManagerImpl::GetBucketsForHost(
blink::mojom::StorageType type,
base::OnceCallback<void(QuotaErrorOr<std::set<BucketLocator>>)> callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
EnsureDatabaseOpened();
+ if (db_disabled_) {
+ std::move(callback).Run(QuotaError::kDatabaseError);
+ return;
+ }
PostTaskAndReplyWithResultForDBThread(
base::BindOnce(&GetBucketsForHostOnDBThread, host, type),
base::BindOnce(&QuotaManagerImpl::DidGetBuckets,
@@ -1174,8 +1315,13 @@ void QuotaManagerImpl::GetBucketsForStorageKey(
blink::mojom::StorageType type,
base::OnceCallback<void(QuotaErrorOr<std::set<BucketLocator>>)> callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
EnsureDatabaseOpened();
+ if (db_disabled_) {
+ std::move(callback).Run(QuotaError::kDatabaseError);
+ return;
+ }
PostTaskAndReplyWithResultForDBThread(
base::BindOnce(&GetBucketsForStorageKeyOnDBThread, storage_key, type),
base::BindOnce(&QuotaManagerImpl::DidGetBuckets,
@@ -1184,7 +1330,9 @@ void QuotaManagerImpl::GetBucketsForStorageKey(
void QuotaManagerImpl::GetUsageInfo(GetUsageInfoCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
EnsureDatabaseOpened();
+
GetUsageInfoTask* get_usage_info =
new GetUsageInfoTask(this, std::move(callback));
get_usage_info->Start();
@@ -1195,6 +1343,8 @@ void QuotaManagerImpl::GetUsageAndQuotaForWebApps(
StorageType type,
UsageAndQuotaCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
+
GetUsageAndQuotaWithBreakdown(
storage_key, type,
base::BindOnce(&DidGetUsageAndQuotaStripBreakdown, std::move(callback)));
@@ -1205,6 +1355,8 @@ void QuotaManagerImpl::GetUsageAndQuotaWithBreakdown(
StorageType type,
UsageAndQuotaWithBreakdownCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
+
GetUsageAndQuotaForDevtools(
storage_key, type,
base::BindOnce(&DidGetUsageAndQuotaStripOverride, std::move(callback)));
@@ -1215,6 +1367,8 @@ void QuotaManagerImpl::GetUsageAndQuotaForDevtools(
StorageType type,
UsageAndQuotaForDevtoolsCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
+
if (!IsSupportedType(type) ||
(is_incognito_ && !IsSupportedIncognitoType(type))) {
std::move(callback).Run(blink::mojom::QuotaStatusCode::kErrorNotSupported,
@@ -1244,6 +1398,8 @@ void QuotaManagerImpl::GetUsageAndQuota(const StorageKey& storage_key,
StorageType type,
UsageAndQuotaCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
+
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.
@@ -1304,15 +1460,20 @@ void QuotaManagerImpl::SetUsageCacheEnabled(QuotaClientType client_id,
bool enabled) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
EnsureDatabaseOpened();
- DCHECK(GetUsageTracker(type));
- GetUsageTracker(type)->SetUsageCacheEnabled(client_id, storage_key, enabled);
+
+ UsageTracker* usage_tracker = GetUsageTracker(type);
+ DCHECK(usage_tracker);
+
+ usage_tracker->SetUsageCacheEnabled(client_id, storage_key, enabled);
}
void QuotaManagerImpl::DeleteBucketData(const BucketLocator& bucket,
QuotaClientTypes quota_client_types,
StatusCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DeleteBucketDataInternal(bucket, std::move(quota_client_types), false,
+ DCHECK(callback);
+
+ DeleteBucketDataInternal(bucket, std::move(quota_client_types),
std::move(callback));
}
@@ -1320,8 +1481,13 @@ void QuotaManagerImpl::FindAndDeleteBucketData(const StorageKey& storage_key,
const std::string& bucket_name,
StatusCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
EnsureDatabaseOpened();
+ if (db_disabled_) {
+ std::move(callback).Run(blink::mojom::QuotaStatusCode::kErrorInvalidAccess);
+ return;
+ }
PostTaskAndReplyWithResultForDBThread(
base::BindOnce(&GetBucketOnDBThread, storage_key, bucket_name,
StorageType::kTemporary),
@@ -1334,6 +1500,7 @@ void QuotaManagerImpl::PerformStorageCleanup(
QuotaClientTypes quota_client_types,
base::OnceClosure callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
StorageCleanupHelper* deleter = new StorageCleanupHelper(
this, type, std::move(quota_client_types), std::move(callback));
deleter->Start();
@@ -1341,9 +1508,9 @@ void QuotaManagerImpl::PerformStorageCleanup(
void QuotaManagerImpl::DeleteHostData(const std::string& host,
StorageType type,
- QuotaClientTypes quota_client_types,
StatusCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
EnsureDatabaseOpened();
DCHECK(client_types_.contains(type));
@@ -1351,16 +1518,75 @@ void QuotaManagerImpl::DeleteHostData(const std::string& host,
std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk);
return;
}
+ auto host_deleter = std::make_unique<HostDataDeleter>(
+ this, host, type,
+ base::BindOnce(&QuotaManagerImpl::DidDeleteHostData,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
+ auto* host_deleter_ptr = host_deleter.get();
+ host_data_deleters_[host_deleter_ptr] = std::move(host_deleter);
+ host_deleter_ptr->Run();
+}
- HostDataDeleter* deleter = new HostDataDeleter(
- this, host, type, std::move(quota_client_types), std::move(callback));
- deleter->Start();
+// static
+void QuotaManagerImpl::DidDeleteHostData(
+ base::WeakPtr<QuotaManagerImpl> quota_manager,
+ StatusCallback delete_host_data_callback,
+ HostDataDeleter* deleter,
+ blink::mojom::QuotaStatusCode status_code) {
+ DCHECK(delete_host_data_callback);
+ DCHECK(deleter);
+ DCHECK(deleter->completed());
+
+ if (quota_manager)
+ quota_manager->host_data_deleters_.erase(deleter);
+
+ std::move(delete_host_data_callback).Run(status_code);
+}
+
+void QuotaManagerImpl::BindInternalsHandler(
+ mojo::PendingReceiver<mojom::QuotaInternalsHandler> receiver) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ internals_handlers_receivers_.Add(this, std::move(receiver));
+}
+
+void QuotaManagerImpl::GetDiskAvailability(
+ GetDiskAvailabilityCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
+
+ GetStorageCapacity(base::BindOnce(
+ [](GetDiskAvailabilityCallback callback, int64_t total_space,
+ int64_t available_space) {
+ DCHECK(callback);
+ DCHECK_GE(total_space, 0);
+ DCHECK_GE(available_space, 0);
+ std::move(callback).Run(total_space, available_space);
+ },
+ std::move(callback)));
+}
+
+void QuotaManagerImpl::GetStatistics(GetStatisticsCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
+
+ base::flat_map<std::string, std::string> statistics;
+ if (temporary_storage_evictor_) {
+ std::map<std::string, int64_t> stats;
+ temporary_storage_evictor_->GetStatistics(&stats);
+ for (const auto& storage_key_usage_pair : stats) {
+ statistics[storage_key_usage_pair.first] =
+ base::NumberToString(storage_key_usage_pair.second);
+ }
+ }
+ std::move(callback).Run(statistics);
}
void QuotaManagerImpl::GetPersistentHostQuota(const std::string& host,
QuotaCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
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
@@ -1382,7 +1608,10 @@ void QuotaManagerImpl::SetPersistentHostQuota(const std::string& host,
int64_t new_quota,
QuotaCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_GE(new_quota, 0);
+ DCHECK(callback);
EnsureDatabaseOpened();
+
if (host.empty()) {
// This could happen if we are called on file:///.
std::move(callback).Run(blink::mojom::QuotaStatusCode::kErrorNotSupported,
@@ -1404,7 +1633,6 @@ void QuotaManagerImpl::SetPersistentHostQuota(const std::string& host,
-1);
return;
}
-
int64_t* new_quota_ptr = new int64_t(new_quota);
PostTaskAndReplyWithResultForDBThread(
base::BindOnce(&SetPersistentHostQuotaOnDBThread, host,
@@ -1415,11 +1643,14 @@ void QuotaManagerImpl::SetPersistentHostQuota(const std::string& host,
}
void QuotaManagerImpl::GetGlobalUsage(StorageType type,
- GlobalUsageCallback callback) {
+ UsageCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
EnsureDatabaseOpened();
- DCHECK(GetUsageTracker(type));
- GetUsageTracker(type)->GetGlobalUsage(std::move(callback));
+
+ UsageTracker* usage_tracker = GetUsageTracker(type);
+ DCHECK(usage_tracker);
+ usage_tracker->GetGlobalUsage(std::move(callback));
}
void QuotaManagerImpl::GetHostUsageWithBreakdown(
@@ -1428,27 +1659,16 @@ void QuotaManagerImpl::GetHostUsageWithBreakdown(
UsageWithBreakdownCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
EnsureDatabaseOpened();
- DCHECK(GetUsageTracker(type));
- GetUsageTracker(type)->GetHostUsageWithBreakdown(host, std::move(callback));
-}
-std::map<std::string, std::string> QuotaManagerImpl::GetStatistics() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- std::map<std::string, std::string> statistics;
- if (temporary_storage_evictor_) {
- std::map<std::string, int64_t> stats;
- temporary_storage_evictor_->GetStatistics(&stats);
- for (const auto& storage_key_usage_pair : stats) {
- statistics[storage_key_usage_pair.first] =
- base::NumberToString(storage_key_usage_pair.second);
- }
- }
- return statistics;
+ UsageTracker* usage_tracker = GetUsageTracker(type);
+ DCHECK(usage_tracker);
+ usage_tracker->GetHostUsageWithBreakdown(host, std::move(callback));
}
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
// quota must be capped by the server limit).
if (type == StorageType::kSyncable)
@@ -1465,7 +1685,14 @@ void QuotaManagerImpl::GetBucketsModifiedBetween(StorageType type,
base::Time end,
GetBucketsCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
EnsureDatabaseOpened();
+
+ if (db_disabled_) {
+ std::move(callback).Run(std::set<BucketLocator>(), type);
+ return;
+ }
+
PostTaskAndReplyWithResultForDBThread(
base::BindOnce(&GetModifiedBetweenOnDBThread, type, begin, end),
base::BindOnce(&QuotaManagerImpl::DidGetModifiedBetween,
@@ -1474,12 +1701,14 @@ void QuotaManagerImpl::GetBucketsModifiedBetween(StorageType type,
bool QuotaManagerImpl::ResetUsageTracker(StorageType type) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(GetUsageTracker(type));
- if (GetUsageTracker(type)->IsWorking())
+
+ UsageTracker* previous_usage_tracker = GetUsageTracker(type);
+ DCHECK(previous_usage_tracker);
+ if (previous_usage_tracker->IsWorking())
return false;
auto usage_tracker = std::make_unique<UsageTracker>(
- client_types_[type], type, special_storage_policy_.get());
+ this, client_types_[type], type, special_storage_policy_.get());
switch (type) {
case StorageType::kTemporary:
temporary_usage_tracker_ = std::move(usage_tracker);
@@ -1520,13 +1749,13 @@ void QuotaManagerImpl::EnsureDatabaseOpened() {
: profile_path_.AppendASCII(kDatabaseName));
temporary_usage_tracker_ = std::make_unique<UsageTracker>(
- client_types_[StorageType::kTemporary], StorageType::kTemporary,
+ this, client_types_[StorageType::kTemporary], StorageType::kTemporary,
special_storage_policy_.get());
persistent_usage_tracker_ = std::make_unique<UsageTracker>(
- client_types_[StorageType::kPersistent], StorageType::kPersistent,
+ this, client_types_[StorageType::kPersistent], StorageType::kPersistent,
special_storage_policy_.get());
syncable_usage_tracker_ = std::make_unique<UsageTracker>(
- client_types_[StorageType::kSyncable], StorageType::kSyncable,
+ this, client_types_[StorageType::kSyncable], StorageType::kSyncable,
special_storage_policy_.get());
if (!is_incognito_) {
@@ -1535,44 +1764,80 @@ void QuotaManagerImpl::EnsureDatabaseOpened() {
&QuotaManagerImpl::ReportHistogram);
}
+ if (bootstrap_disabled_for_testing_)
+ return;
+
+ is_bootstrapping_database_ = true;
base::PostTaskAndReplyWithResult(
db_runner_.get(), FROM_HERE,
- base::BindOnce(&QuotaDatabase::IsBootstrappedForEviction,
+ base::BindOnce(&QuotaDatabase::IsBootstrapped,
base::Unretained(database_.get())),
- base::BindOnce(&QuotaManagerImpl::DidOpenDatabase,
+ base::BindOnce(&QuotaManagerImpl::DidGetBootstrapFlag,
weak_factory_.GetWeakPtr()));
}
-void QuotaManagerImpl::DidOpenDatabase(bool is_database_bootstrapped) {
+void QuotaManagerImpl::DidGetBootstrapFlag(bool is_database_bootstrapped) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- is_database_bootstrapped_for_eviction_ = is_database_bootstrapped;
+ DCHECK(is_bootstrapping_database_);
+ if (!is_database_bootstrapped) {
+ BootstrapDatabase();
+ return;
+ }
+ is_bootstrapping_database_ = false;
+ RunDatabaseCallbacks();
StartEviction();
}
-void QuotaManagerImpl::BootstrapDatabaseForEviction(
- GetBucketCallback did_get_bucket_callback,
- int64_t usage,
- int64_t unlimited_usage) {
+void QuotaManagerImpl::BootstrapDatabase() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!storage_key_gatherer_);
+ storage_key_gatherer_ = std::make_unique<StorageKeyGathererTask>(
+ this, base::BindOnce(&QuotaManagerImpl::DidGetStorageKeysForBootstrap,
+ weak_factory_.GetWeakPtr()));
+ storage_key_gatherer_->Run();
+}
+
+void QuotaManagerImpl::DidGetStorageKeysForBootstrap(
+ StorageKeysByType storage_keys_by_type) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // The usage cache should be fully populated now so we can
- // seed the database with storage keys we know about.
- std::set<StorageKey> storage_keys =
- temporary_usage_tracker_->GetCachedStorageKeys();
+ DCHECK(storage_key_gatherer_);
+ storage_key_gatherer_.reset();
+
PostTaskAndReplyWithResultForDBThread(
+ base::BindOnce(&BootstrapDatabaseOnDBThread,
+ std::move(storage_keys_by_type)),
+ base::BindOnce(&QuotaManagerImpl::DidBootstrapDatabase,
+ weak_factory_.GetWeakPtr()),
FROM_HERE,
- base::BindOnce(&BootstrapDatabaseOnDBThread, std::move(storage_keys)),
- base::BindOnce(&QuotaManagerImpl::DidBootstrapDatabaseForEviction,
- weak_factory_.GetWeakPtr(),
- std::move(did_get_bucket_callback)));
+ /*is_bootstrap_task=*/true);
}
-void QuotaManagerImpl::DidBootstrapDatabaseForEviction(
- GetBucketCallback did_get_bucket_callback,
- bool success) {
+void QuotaManagerImpl::DidBootstrapDatabase(QuotaError error) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- is_database_bootstrapped_for_eviction_ = success;
- DidDatabaseWork(success);
- GetLRUBucket(StorageType::kTemporary, std::move(did_get_bucket_callback));
+ DidDatabaseWork(error != QuotaError::kDatabaseError);
+
+ PostTaskAndReplyWithResultForDBThread(
+ base::BindOnce(&SetDatabaseBootstrappedOnDBThread),
+ base::BindOnce(&QuotaManagerImpl::DidSetDatabaseBootstrapped,
+ weak_factory_.GetWeakPtr()),
+ FROM_HERE,
+ /*is_bootstrap_task=*/true);
+}
+
+void QuotaManagerImpl::DidSetDatabaseBootstrapped(QuotaError error) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(is_bootstrapping_database_);
+ is_bootstrapping_database_ = false;
+ DidDatabaseWork(error != QuotaError::kDatabaseError);
+
+ RunDatabaseCallbacks();
+ StartEviction();
+}
+
+void QuotaManagerImpl::RunDatabaseCallbacks() {
+ for (auto& callback : database_callbacks_)
+ std::move(callback).Run();
+ database_callbacks_.clear();
}
void QuotaManagerImpl::RegisterClient(
@@ -1607,13 +1872,6 @@ UsageTracker* QuotaManagerImpl::GetUsageTracker(StorageType type) const {
return nullptr;
}
-std::set<StorageKey> QuotaManagerImpl::GetCachedStorageKeys(StorageType type) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- EnsureDatabaseOpened();
- DCHECK(GetUsageTracker(type));
- return GetUsageTracker(type)->GetCachedStorageKeys();
-}
-
void QuotaManagerImpl::NotifyStorageAccessed(const StorageKey& storage_key,
StorageType type,
base::Time access_time) {
@@ -1659,21 +1917,22 @@ void QuotaManagerImpl::NotifyStorageModified(QuotaClientType client_id,
base::Time modification_time,
base::OnceClosure callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
EnsureDatabaseOpened();
DCHECK(GetUsageTracker(type));
- GetUsageTracker(type)->UpdateUsageCache(client_id, storage_key, delta);
- if (callback)
- std::move(callback).Run();
-
- if (db_disabled_)
+ if (db_disabled_) {
+ if (callback)
+ std::move(callback).Run();
return;
+ }
PostTaskAndReplyWithResultForDBThread(
- base::BindOnce(&UpdateModifiedTimeOnDBThread, storage_key, type,
- modification_time),
- base::BindOnce(&QuotaManagerImpl::OnComplete,
- weak_factory_.GetWeakPtr()));
+ base::BindOnce(&GetBucketOnDBThread, storage_key, kDefaultBucketName,
+ type),
+ base::BindOnce(&QuotaManagerImpl::DidGetBucketForUsage,
+ weak_factory_.GetWeakPtr(), client_id, delta,
+ modification_time, std::move(callback)));
}
void QuotaManagerImpl::NotifyBucketModified(QuotaClientType client_id,
@@ -1682,17 +1941,20 @@ void QuotaManagerImpl::NotifyBucketModified(QuotaClientType client_id,
base::Time modification_time,
base::OnceClosure callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
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;
+ // TODO(crbug.com/1199417): Update bucket usage in UsageTracker once
+ // QuotaClient & UsageTracker operate by bucket. UsageTracker should be
+ // updated after ensuring there is a entry in the QuotaDatabase.
+ // Run `callback` on completion.
+
PostTaskAndReplyWithResultForDBThread(
base::BindOnce(&UpdateBucketModifiedTimeOnDBThread, bucket_id,
modification_time),
@@ -1702,6 +1964,13 @@ void QuotaManagerImpl::NotifyBucketModified(QuotaClientType client_id,
void QuotaManagerImpl::DumpQuotaTable(DumpQuotaTableCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
+
+ if (db_disabled_) {
+ std::move(callback).Run(QuotaTableEntries());
+ return;
+ }
+
DumpQuotaTableHelper* helper = new DumpQuotaTableHelper;
PostTaskAndReplyWithResultForDBThread(
base::BindOnce(&DumpQuotaTableHelper::DumpQuotaTableOnDBThread,
@@ -1713,6 +1982,12 @@ void QuotaManagerImpl::DumpQuotaTable(DumpQuotaTableCallback callback) {
void QuotaManagerImpl::DumpBucketTable(DumpBucketTableCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
+
+ if (db_disabled_) {
+ std::move(callback).Run(BucketTableEntries());
+ return;
+ }
DumpBucketTableHelper* helper = new DumpBucketTableHelper;
PostTaskAndReplyWithResultForDBThread(
base::BindOnce(&DumpBucketTableHelper::DumpBucketTableOnDBThread,
@@ -1725,6 +2000,7 @@ void QuotaManagerImpl::DumpBucketTable(DumpBucketTableCallback callback) {
void QuotaManagerImpl::StartEviction() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!temporary_storage_evictor_.get());
+
if (eviction_disabled_)
return;
temporary_storage_evictor_ = std::make_unique<QuotaTemporaryStorageEvictor>(
@@ -1732,34 +2008,25 @@ void QuotaManagerImpl::StartEviction() {
temporary_storage_evictor_->Start();
}
-void QuotaManagerImpl::DeleteStorageKeyFromDatabase(
- const StorageKey& storage_key,
- StorageType type) {
+void QuotaManagerImpl::DeleteBucketFromDatabase(
+ BucketId bucket_id,
+ base::OnceCallback<void(QuotaError)> callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
EnsureDatabaseOpened();
- if (db_disabled_)
- return;
- PostTaskAndReplyWithResultForDBThread(
- base::BindOnce(&DeleteStorageKeyInfoOnDBThread, storage_key, type),
- base::BindOnce(&QuotaManagerImpl::OnComplete,
- weak_factory_.GetWeakPtr()));
-}
-
-void QuotaManagerImpl::DeleteBucketFromDatabase(BucketId bucket_id,
- bool is_eviction) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- EnsureDatabaseOpened();
- if (db_disabled_)
+ if (db_disabled_) {
+ std::move(callback).Run(QuotaError::kDatabaseError);
return;
+ }
PostTaskAndReplyWithResultForDBThread(
- base::BindOnce(&DeleteBucketInfoOnDBThread, bucket_id, is_eviction),
- base::BindOnce(&QuotaManagerImpl::OnComplete,
- weak_factory_.GetWeakPtr()));
+ base::BindOnce(&DeleteBucketInfoOnDBThread, bucket_id),
+ std::move(callback));
}
void QuotaManagerImpl::DidBucketDataEvicted(
+ QuotaDatabase::BucketTableEntry entry,
blink::mojom::QuotaStatusCode status) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(io_thread_->BelongsToCurrentThread());
@@ -1771,21 +2038,54 @@ void QuotaManagerImpl::DidBucketDataEvicted(
if (status != blink::mojom::QuotaStatusCode::kOk)
buckets_in_error_[eviction_context_.evicted_bucket.id]++;
+ if (status == blink::mojom::QuotaStatusCode::kOk) {
+ base::Time now = base::Time::Now();
+ base::UmaHistogramCounts1M(
+ QuotaManagerImpl::kEvictedBucketAccessedCountHistogram,
+ entry.use_count);
+ base::UmaHistogramCounts1000(
+ QuotaManagerImpl::kEvictedBucketDaysSinceAccessHistogram,
+ (now - entry.last_accessed).InDays());
+ }
+
std::move(eviction_context_.evict_bucket_data_callback).Run(status);
}
void QuotaManagerImpl::DeleteBucketDataInternal(
const BucketLocator& bucket,
QuotaClientTypes quota_client_types,
- bool is_eviction,
StatusCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
EnsureDatabaseOpened();
- BucketDataDeleter* deleter =
- new BucketDataDeleter(this, bucket, std::move(quota_client_types),
- is_eviction, std::move(callback));
- deleter->Start();
+ if (db_disabled_) {
+ std::move(callback).Run(blink::mojom::QuotaStatusCode::kErrorInvalidAccess);
+ return;
+ }
+ auto bucket_deleter = std::make_unique<BucketDataDeleter>(
+ this, bucket, std::move(quota_client_types),
+ base::BindOnce(&QuotaManagerImpl::DidDeleteBucketData,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
+ auto* bucket_deleter_ptr = bucket_deleter.get();
+ bucket_data_deleters_[bucket_deleter_ptr] = std::move(bucket_deleter);
+ bucket_deleter_ptr->Run();
+}
+
+// static
+void QuotaManagerImpl::DidDeleteBucketData(
+ base::WeakPtr<QuotaManagerImpl> quota_manager,
+ StatusCallback delete_bucket_data_callback,
+ BucketDataDeleter* deleter,
+ blink::mojom::QuotaStatusCode status_code) {
+ DCHECK(delete_bucket_data_callback);
+ DCHECK(deleter);
+ DCHECK(deleter->completed());
+
+ if (quota_manager)
+ quota_manager->bucket_data_deleters_.erase(deleter);
+
+ std::move(delete_bucket_data_callback).Run(status_code);
}
void QuotaManagerImpl::MaybeRunStoragePressureCallback(
@@ -1793,6 +2093,9 @@ void QuotaManagerImpl::MaybeRunStoragePressureCallback(
int64_t total_space,
int64_t available_space) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_GE(total_space, 0);
+ DCHECK_GE(available_space, 0);
+
// TODO(https://crbug.com/1059560): Figure out what 0 total_space means
// and how to handle the storage pressure callback in these cases.
if (total_space == 0)
@@ -1810,13 +2113,17 @@ void QuotaManagerImpl::MaybeRunStoragePressureCallback(
}
}
-void QuotaManagerImpl::SimulateStoragePressure(const StorageKey& storage_key) {
- storage_pressure_callback_.Run(storage_key);
+void QuotaManagerImpl::SimulateStoragePressure(const url::Origin& origin_url) {
+ StorageKey key(origin_url);
+ storage_pressure_callback_.Run(key);
}
void QuotaManagerImpl::DetermineStoragePressure(int64_t total_space,
int64_t free_space) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_GE(total_space, 0);
+ DCHECK_GE(free_space, 0);
+
if (!base::FeatureList::IsEnabled(features::kStoragePressureEvent)) {
return;
}
@@ -1852,6 +2159,9 @@ void QuotaManagerImpl::OverrideQuotaForStorageKey(
const StorageKey& storage_key,
absl::optional<int64_t> quota_size) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_GE(quota_size.value_or(0), 0)
+ << "negative quota override: " << quota_size.value_or(0);
+
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
@@ -1898,9 +2208,27 @@ void QuotaManagerImpl::SetQuotaChangeCallbackForTesting(
quota_change_callback_ = std::move(storage_pressure_event_callback);
}
+void QuotaManagerImpl::SetQuotaDatabaseForTesting(
+ std::unique_ptr<QuotaDatabase> database) {
+ DCHECK(database);
+ database_ = std::move(database);
+
+ // Initialize usage trackers after database is set.
+ temporary_usage_tracker_ = std::make_unique<UsageTracker>(
+ this, client_types_[StorageType::kTemporary], StorageType::kTemporary,
+ special_storage_policy_.get());
+ persistent_usage_tracker_ = std::make_unique<UsageTracker>(
+ this, client_types_[StorageType::kPersistent], StorageType::kPersistent,
+ special_storage_policy_.get());
+ syncable_usage_tracker_ = std::make_unique<UsageTracker>(
+ this, client_types_[StorageType::kSyncable], StorageType::kSyncable,
+ special_storage_policy_.get());
+}
+
void QuotaManagerImpl::ReportHistogram() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!is_incognito_);
+
GetGlobalUsage(
StorageType::kTemporary,
base::BindOnce(&QuotaManagerImpl::DidGetTemporaryGlobalUsageForHistogram,
@@ -1910,6 +2238,9 @@ void QuotaManagerImpl::ReportHistogram() {
void QuotaManagerImpl::DidGetTemporaryGlobalUsageForHistogram(
int64_t usage,
int64_t unlimited_usage) {
+ DCHECK_GE(usage, -1);
+ DCHECK_GE(unlimited_usage, -1);
+
GetStorageCapacity(
base::BindOnce(&QuotaManagerImpl::DidGetStorageCapacityForHistogram,
weak_factory_.GetWeakPtr(), usage));
@@ -1920,6 +2251,10 @@ void QuotaManagerImpl::DidGetStorageCapacityForHistogram(
int64_t total_space,
int64_t available_space) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_GE(usage, -1);
+ DCHECK_GE(total_space, 0);
+ DCHECK_GE(available_space, 0);
+
UMA_HISTOGRAM_MBYTES("Quota.GlobalUsageOfTemporaryStorage", usage);
if (total_space > 0) {
UMA_HISTOGRAM_PERCENTAGE("Quota.PercentUsedForTemporaryStorage2",
@@ -1940,6 +2275,9 @@ void QuotaManagerImpl::DidGetPersistentGlobalUsageForHistogram(
int64_t usage,
int64_t unlimited_usage) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_GE(usage, -1);
+ DCHECK_GE(unlimited_usage, -1);
+
UMA_HISTOGRAM_MBYTES("Quota.GlobalUsageOfPersistentStorage", usage);
// We DumpBucketTable last to ensure the trackers caches are loaded.
@@ -1951,6 +2289,7 @@ void QuotaManagerImpl::DidGetPersistentGlobalUsageForHistogram(
void QuotaManagerImpl::DidDumpBucketTableForHistogram(
const BucketTableEntries& entries) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
std::map<StorageKey, int64_t> usage_map =
GetUsageTracker(StorageType::kTemporary)->GetCachedStorageKeysUsage();
base::Time now = base::Time::Now();
@@ -1979,6 +2318,7 @@ void QuotaManagerImpl::DidDumpBucketTableForHistogram(
std::set<BucketId> QuotaManagerImpl::GetEvictionBucketExceptions() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
std::set<BucketId> exceptions;
for (const auto& p : buckets_in_error_) {
if (p.second > QuotaManagerImpl::kThresholdOfErrorsToBeDenylisted)
@@ -1992,6 +2332,8 @@ void QuotaManagerImpl::DidGetEvictionBucket(
GetBucketCallback callback,
const absl::optional<BucketLocator>& bucket) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
+
// Make sure the returned bucket has not been accessed since we posted the
// eviction task.
DCHECK(!bucket.has_value() ||
@@ -2015,29 +2357,18 @@ void QuotaManagerImpl::DidGetEvictionBucket(
}
void QuotaManagerImpl::GetEvictionBucket(StorageType type,
- int64_t global_quota,
GetBucketCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
EnsureDatabaseOpened();
+
// This must not be called while there's an in-flight task.
DCHECK(!is_getting_eviction_bucket_);
is_getting_eviction_bucket_ = true;
- auto did_get_bucket_callback =
- base::BindOnce(&QuotaManagerImpl::DidGetEvictionBucket,
- weak_factory_.GetWeakPtr(), std::move(callback));
-
- 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_bucket_callback)));
- return;
- }
-
- GetLRUBucket(type, std::move(did_get_bucket_callback));
+ GetLRUBucket(type,
+ base::BindOnce(&QuotaManagerImpl::DidGetEvictionBucket,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
}
void QuotaManagerImpl::EvictBucketData(const BucketLocator& bucket,
@@ -2045,20 +2376,39 @@ void QuotaManagerImpl::EvictBucketData(const BucketLocator& bucket,
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(io_thread_->BelongsToCurrentThread());
DCHECK_EQ(bucket.type, StorageType::kTemporary);
+ DCHECK(callback);
eviction_context_.evicted_bucket = bucket;
eviction_context_.evict_bucket_data_callback = std::move(callback);
+ PostTaskAndReplyWithResultForDBThread(
+ base::BindOnce(&GetBucketInfoForEvictionOnDBThread, bucket.id),
+ base::BindOnce(&QuotaManagerImpl::DidGetBucketInfoForEviction,
+ weak_factory_.GetWeakPtr(), bucket));
+}
+
+void QuotaManagerImpl::DidGetBucketInfoForEviction(
+ const BucketLocator& bucket,
+ QuotaErrorOr<QuotaDatabase::BucketTableEntry> result) {
+ DidDatabaseWork(result.ok() || result.error() != QuotaError::kDatabaseError);
+
+ if (!result.ok()) {
+ std::move(eviction_context_.evict_bucket_data_callback)
+ .Run(blink::mojom::QuotaStatusCode::kErrorInvalidAccess);
+ return;
+ }
+
DeleteBucketDataInternal(
- bucket, AllQuotaClientTypes(), true,
+ bucket, AllQuotaClientTypes(),
base::BindOnce(&QuotaManagerImpl::DidBucketDataEvicted,
- weak_factory_.GetWeakPtr()));
+ weak_factory_.GetWeakPtr(), result.value()));
}
void QuotaManagerImpl::GetEvictionRoundInfo(
EvictionRoundInfoCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(io_thread_->BelongsToCurrentThread());
+ DCHECK(callback);
EnsureDatabaseOpened();
DCHECK(!eviction_helper_);
@@ -2077,7 +2427,9 @@ void QuotaManagerImpl::DidGetEvictionRoundInfo() {
void QuotaManagerImpl::GetLRUBucket(StorageType type,
GetBucketCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
EnsureDatabaseOpened();
+
// This must not be called while there's an in-flight task.
DCHECK(lru_bucket_callback_.is_null());
lru_bucket_callback_ = std::move(callback);
@@ -2114,6 +2466,8 @@ void QuotaManagerImpl::DidSetPersistentHostQuota(const std::string& host,
const int64_t* new_quota,
QuotaError error) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
+
DidDatabaseWork(error != QuotaError::kDatabaseError);
if (error == QuotaError::kNone) {
@@ -2147,6 +2501,8 @@ void DidGetSettingsThreadAdapter(base::TaskRunner* task_runner,
void QuotaManagerImpl::GetQuotaSettings(QuotaSettingsCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
+
if (base::TimeTicks::Now() - settings_timestamp_ <
settings_.refresh_interval) {
std::move(callback).Run(settings_);
@@ -2170,6 +2526,7 @@ void QuotaManagerImpl::GetQuotaSettings(QuotaSettingsCallback callback) {
void QuotaManagerImpl::DidGetSettings(absl::optional<QuotaSettings> settings) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
if (!settings) {
settings = settings_;
settings->refresh_interval = base::Minutes(1);
@@ -2183,6 +2540,8 @@ void QuotaManagerImpl::DidGetSettings(absl::optional<QuotaSettings> settings) {
void QuotaManagerImpl::GetStorageCapacity(StorageCapacityCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
+
if (!storage_capacity_callbacks_.Add(std::move(callback)))
return;
if (is_incognito_) {
@@ -2202,9 +2561,16 @@ void QuotaManagerImpl::GetStorageCapacity(StorageCapacityCallback callback) {
void QuotaManagerImpl::ContinueIncognitoGetStorageCapacity(
const QuotaSettings& settings) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- int64_t current_usage =
+
+ int64_t temporary_usage =
GetUsageTracker(StorageType::kTemporary)->GetCachedUsage();
- current_usage += GetUsageTracker(StorageType::kPersistent)->GetCachedUsage();
+ DCHECK_GE(temporary_usage, -1);
+
+ int64_t persistent_usage =
+ GetUsageTracker(StorageType::kPersistent)->GetCachedUsage();
+ DCHECK_GE(persistent_usage, -1);
+
+ int64_t current_usage = temporary_usage + persistent_usage;
int64_t available_space =
std::max(int64_t{0}, settings.pool_size - current_usage);
DidGetStorageCapacity(std::make_tuple(settings.pool_size, available_space));
@@ -2213,8 +2579,13 @@ void QuotaManagerImpl::ContinueIncognitoGetStorageCapacity(
void QuotaManagerImpl::DidGetStorageCapacity(
const std::tuple<int64_t, int64_t>& total_and_available) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
int64_t total_space = std::get<0>(total_and_available);
+ DCHECK_GE(total_space, 0);
+
int64_t available_space = std::get<1>(total_and_available);
+ DCHECK_GE(available_space, 0);
+
cached_disk_stats_for_storage_pressure_ =
std::make_tuple(base::TimeTicks::Now(), total_space, available_space);
storage_capacity_callbacks_.Run(total_space, available_space);
@@ -2223,7 +2594,12 @@ void QuotaManagerImpl::DidGetStorageCapacity(
void QuotaManagerImpl::DidDatabaseWork(bool success) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- db_disabled_ = !success;
+ if (success)
+ return;
+
+ db_error_count_++;
+ if (db_error_count_ >= QuotaManagerImpl::kThresholdOfErrorsToDisableDatabase)
+ db_disabled_ = true;
}
void QuotaManagerImpl::OnComplete(QuotaError result) {
@@ -2235,6 +2611,8 @@ void QuotaManagerImpl::DidGetBucket(
base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback,
QuotaErrorOr<BucketInfo> result) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
+
DidDatabaseWork(result.ok() || result.error() != QuotaError::kDatabaseError);
std::move(callback).Run(std::move(result));
}
@@ -2243,6 +2621,8 @@ void QuotaManagerImpl::DidGetBucketForDeletion(
StatusCallback callback,
QuotaErrorOr<BucketInfo> result) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
+
DidDatabaseWork(result.ok() || result.error() != QuotaError::kDatabaseError);
if (!result.ok()) {
@@ -2255,8 +2635,41 @@ void QuotaManagerImpl::DidGetBucketForDeletion(
BucketLocator bucket(result->id, result->storage_key, result->type,
result->name == kDefaultBucketName);
- DeleteBucketDataInternal(bucket, AllQuotaClientTypes(),
- /*is_eviction=*/false, std::move(callback));
+ DeleteBucketDataInternal(bucket, AllQuotaClientTypes(), std::move(callback));
+ return;
+}
+
+void QuotaManagerImpl::DidGetBucketForUsage(QuotaClientType client_type,
+ int64_t delta,
+ base::Time modification_time,
+ base::OnceClosure callback,
+ QuotaErrorOr<BucketInfo> result) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
+
+ DidDatabaseWork(result.ok() || result.error() != QuotaError::kDatabaseError);
+
+ if (!result.ok()) {
+ if (callback)
+ std::move(callback).Run();
+ return;
+ }
+
+ BucketLocator bucket(result->id, result->storage_key, result->type,
+ result->name == kDefaultBucketName);
+ GetUsageTracker(bucket.type)
+ ->UpdateBucketUsageCache(client_type, bucket, delta);
+
+ // Return once usage cache is updated for callers waiting for quota changes to
+ // be reflected before querying for usage.
+ if (callback)
+ std::move(callback).Run();
+
+ PostTaskAndReplyWithResultForDBThread(
+ base::BindOnce(&UpdateBucketModifiedTimeOnDBThread, bucket.id,
+ modification_time),
+ base::BindOnce(&QuotaManagerImpl::OnComplete,
+ weak_factory_.GetWeakPtr()));
return;
}
@@ -2264,6 +2677,8 @@ void QuotaManagerImpl::DidGetStorageKeys(
GetStorageKeysCallback callback,
QuotaErrorOr<std::set<StorageKey>> result) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
+
DidDatabaseWork(result.ok() || result.error() != QuotaError::kDatabaseError);
if (!result.ok()) {
std::move(callback).Run(std::set<StorageKey>());
@@ -2276,6 +2691,8 @@ void QuotaManagerImpl::DidGetBuckets(
base::OnceCallback<void(QuotaErrorOr<std::set<BucketLocator>>)> callback,
QuotaErrorOr<std::set<BucketLocator>> result) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
+
DidDatabaseWork(result.ok() || result.error() != QuotaError::kDatabaseError);
std::move(callback).Run(std::move(result));
}
@@ -2285,6 +2702,8 @@ void QuotaManagerImpl::DidGetModifiedBetween(
StorageType type,
QuotaErrorOr<std::set<BucketLocator>> result) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
+
DidDatabaseWork(result.ok() || result.error() != QuotaError::kDatabaseError);
if (!result.ok()) {
std::move(callback).Run(std::set<BucketLocator>(), type);
@@ -2293,29 +2712,27 @@ void QuotaManagerImpl::DidGetModifiedBetween(
std::move(callback).Run(result.value(), type);
}
-void QuotaManagerImpl::PostTaskAndReplyWithResultForDBThread(
- const base::Location& from_here,
- base::OnceCallback<bool(QuotaDatabase*)> task,
- base::OnceCallback<void(bool)> reply) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // Deleting manager will post another task to DB sequence to delete
- // |database_|, therefore we can be sure that database_ is alive when this
- // task runs.
- base::PostTaskAndReplyWithResult(
- db_runner_.get(), from_here,
- base::BindOnce(std::move(task), base::Unretained(database_.get())),
- std::move(reply));
-}
-
template <typename ValueType>
void QuotaManagerImpl::PostTaskAndReplyWithResultForDBThread(
base::OnceCallback<QuotaErrorOr<ValueType>(QuotaDatabase*)> task,
base::OnceCallback<void(QuotaErrorOr<ValueType>)> reply,
- const base::Location& from_here) {
+ const base::Location& from_here,
+ bool is_bootstrap_task) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(task);
+ DCHECK(reply);
// Deleting manager will post another task to DB sequence to delete
// |database_|, therefore we can be sure that database_ is alive when this
// task runs.
+
+ if (!is_bootstrap_task && is_bootstrapping_database_) {
+ database_callbacks_.push_back(base::BindOnce(
+ &QuotaManagerImpl::PostTaskAndReplyWithResultForDBThread<ValueType>,
+ weak_factory_.GetWeakPtr(), std::move(task), std::move(reply),
+ from_here, is_bootstrap_task));
+ return;
+ }
+
base::PostTaskAndReplyWithResult(
db_runner_.get(), from_here,
base::BindOnce(std::move(task), base::Unretained(database_.get())),
@@ -2325,11 +2742,26 @@ void QuotaManagerImpl::PostTaskAndReplyWithResultForDBThread(
void QuotaManagerImpl::PostTaskAndReplyWithResultForDBThread(
base::OnceCallback<QuotaError(QuotaDatabase*)> task,
base::OnceCallback<void(QuotaError)> reply,
- const base::Location& from_here) {
+ const base::Location& from_here,
+ bool is_bootstrap_task) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(task);
+ DCHECK(reply);
// Deleting manager will post another task to DB sequence to delete
// |database_|, therefore we can be sure that database_ is alive when this
// task runs.
+
+ if (!is_bootstrap_task && is_bootstrapping_database_) {
+ database_callbacks_.push_back(base::BindOnce(
+ static_cast<void (QuotaManagerImpl::*)(
+ base::OnceCallback<QuotaError(QuotaDatabase*)>,
+ base::OnceCallback<void(QuotaError)>, const base::Location&, bool)>(
+ &QuotaManagerImpl::PostTaskAndReplyWithResultForDBThread),
+ weak_factory_.GetWeakPtr(), std::move(task), std::move(reply),
+ from_here, is_bootstrap_task));
+ return;
+ }
+
base::PostTaskAndReplyWithResult(
db_runner_.get(), from_here,
base::BindOnce(std::move(task), base::Unretained(database_.get())),
@@ -2344,13 +2776,15 @@ std::tuple<int64_t, int64_t> QuotaManagerImpl::CallGetVolumeInfo(
LOG(WARNING) << "Create directory failed for path" << path.value();
return std::make_tuple<int64_t, int64_t>(0, 0);
}
- int64_t total;
- int64_t available;
- std::tie(total, available) = get_volume_info_fn(path);
+
+ const auto [total, available] = get_volume_info_fn(path);
if (total < 0 || available < 0) {
LOG(WARNING) << "Unable to get volume info: " << path.value();
return std::make_tuple<int64_t, int64_t>(0, 0);
}
+ DCHECK_GE(total, 0);
+ DCHECK_GE(available, 0);
+
UMA_HISTOGRAM_MBYTES("Quota.TotalDiskSpace", total);
UMA_HISTOGRAM_MBYTES("Quota.AvailableDiskSpace", available);
if (total > 0) {
diff --git a/chromium/storage/browser/quota/quota_manager_impl.h b/chromium/storage/browser/quota/quota_manager_impl.h
index 8762f546418..bc2eb685441 100644
--- a/chromium/storage/browser/quota/quota_manager_impl.h
+++ b/chromium/storage/browser/quota/quota_manager_impl.h
@@ -7,7 +7,6 @@
#include <stdint.h>
-#include <list>
#include <map>
#include <memory>
#include <set>
@@ -30,10 +29,12 @@
#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/receiver_set.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "storage/browser/quota/quota_callbacks.h"
#include "storage/browser/quota/quota_client_type.h"
#include "storage/browser/quota/quota_database.h"
+#include "storage/browser/quota/quota_internals.mojom.h"
#include "storage/browser/quota/quota_settings.h"
#include "storage/browser/quota/quota_task.h"
#include "storage/browser/quota/special_storage_policy.h"
@@ -48,10 +49,6 @@ class SingleThreadTaskRunner;
class TaskRunner;
} // namespace base
-namespace quota_internals {
-class QuotaInternalsProxy;
-} // namespace quota_internals
-
namespace storage {
class QuotaManagerProxy;
@@ -79,7 +76,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaEvictionHandler {
// 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,
GetBucketCallback callback) = 0;
// Called to evict a bucket.
@@ -125,7 +121,8 @@ struct UsageInfo {
class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl
: public QuotaTaskObserver,
public QuotaEvictionHandler,
- public base::RefCountedDeleteOnSequence<QuotaManagerImpl> {
+ public base::RefCountedDeleteOnSequence<QuotaManagerImpl>,
+ public storage::mojom::QuotaInternalsHandler {
public:
using UsageAndQuotaCallback = base::OnceCallback<
void(blink::mojom::QuotaStatusCode, int64_t usage, int64_t quota)>;
@@ -169,6 +166,9 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl
// Returns a proxy object that can be used on any thread.
QuotaManagerProxy* proxy() { return proxy_.get(); }
+ void BindInternalsHandler(
+ mojo::PendingReceiver<mojom::QuotaInternalsHandler> receiver);
+
// 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
@@ -178,6 +178,15 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl
const blink::StorageKey& storage_key,
const std::string& bucket_name,
base::OnceCallback<void(QuotaErrorOr<BucketInfo>)>);
+ // Same as GetOrCreateBucket but takes in StorageType. This should only be
+ // used by FileSystem, and is expected to be removed when
+ // StorageType::kSyncable and StorageType::kPersistent are deprecated.
+ // (crbug.com/1233525, crbug.com/1286964).
+ virtual void GetOrCreateBucketDeprecated(
+ const blink::StorageKey& storage_key,
+ const std::string& bucket_name,
+ blink::mojom::StorageType storage_type,
+ 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
@@ -309,19 +318,22 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl
blink::mojom::StorageType type,
bool enabled);
- // DeleteHostData (surprisingly enough) deletes data of a particular
- // blink::mojom::StorageType associated with a set of storage keys.
- // DeleteBucketData will only delete 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.
+ // Deletes `bucket` data for the specified `quota_client_types`. Pass in
+ // QuotaClientType::AllClients() to remove bucket data for all quota clients.
+ //
+ // `callback` is always called. If this QuotaManager gets destroyed during
+ // deletion, `callback` may be called with a kErrorAbort status.
virtual void DeleteBucketData(const BucketLocator& bucket,
QuotaClientTypes quota_client_types,
StatusCallback callback);
+
+ // Deletes buckets of a particular blink::mojom::StorageType with storage keys
+ // that match the specified host.
+ //
+ // `callback` is always called. If this QuotaManager gets destroyed during
+ // deletion, `callback` may be called with a kErrorAbort status.
void DeleteHostData(const std::string& host,
blink::mojom::StorageType type,
- QuotaClientTypes quota_client_types,
StatusCallback callback);
// Queries QuotaDatabase for the bucket with `storage_key` and `bucket_name`
@@ -339,19 +351,20 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl
QuotaClientTypes quota_client_types,
base::OnceClosure callback);
+ // storage::mojom::QuotaInternalsHandler implementation
+ void GetDiskAvailability(GetDiskAvailabilityCallback callback) override;
+ void GetStatistics(GetStatisticsCallback callback) override;
+
// Called by UI and internal modules.
void GetPersistentHostQuota(const std::string& host, QuotaCallback callback);
void SetPersistentHostQuota(const std::string& host,
int64_t new_quota,
QuotaCallback callback);
- void GetGlobalUsage(blink::mojom::StorageType type,
- GlobalUsageCallback callback);
+ void GetGlobalUsage(blink::mojom::StorageType type, UsageCallback callback);
void GetHostUsageWithBreakdown(const std::string& host,
blink::mojom::StorageType type,
UsageWithBreakdownCallback callback);
- std::map<std::string, std::string> GetStatistics();
-
bool IsStorageUnlimited(const blink::StorageKey& storage_key,
blink::mojom::StorageType type) const;
@@ -388,6 +401,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl
static constexpr int kEvictionIntervalInMilliSeconds =
30 * kMinutesInMilliSeconds;
static constexpr int kThresholdOfErrorsToBeDenylisted = 3;
+ static constexpr int kThresholdOfErrorsToDisableDatabase = 3;
static constexpr int kThresholdRandomizationPercent = 5;
static constexpr char kDatabaseName[] = "QuotaManager";
@@ -410,6 +424,12 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl
eviction_disabled_ = disable;
}
+ void SetQuotaDatabaseForTesting(std::unique_ptr<QuotaDatabase> database);
+
+ void SetBootstrapDisabledForTesting(bool disable) {
+ bootstrap_disabled_for_testing_ = disable;
+ }
+
protected:
~QuotaManagerImpl() override;
void SetQuotaChangeCallbackForTesting(
@@ -418,18 +438,18 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl
private:
friend class base::DeleteHelper<QuotaManagerImpl>;
friend class base::RefCountedDeleteOnSequence<QuotaManagerImpl>;
- friend class quota_internals::QuotaInternalsProxy;
friend class MockQuotaManager;
friend class MockQuotaClient;
friend class QuotaManagerProxy;
friend class QuotaManagerImplTest;
friend class QuotaTemporaryStorageEvictor;
+ friend class UsageTrackerTest;
class EvictionRoundInfoHelper;
class UsageAndQuotaInfoGatherer;
class GetUsageInfoTask;
+ class StorageKeyGathererTask;
class BucketDataDeleter;
- class StorageKeyDataDeleter;
class HostDataDeleter;
class DumpQuotaTableHelper;
class DumpBucketTableHelper;
@@ -452,6 +472,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl
using BucketTableEntry = QuotaDatabase::BucketTableEntry;
using QuotaTableEntries = std::vector<QuotaTableEntry>;
using BucketTableEntries = std::vector<BucketTableEntry>;
+ using StorageKeysByType =
+ base::flat_map<blink::mojom::StorageType, std::set<blink::StorageKey>>;
using QuotaSettingsCallback = base::OnceCallback<void(const QuotaSettings&)>;
@@ -475,13 +497,19 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl
// Initialize() must be called after all quota clients are added to the
// manager by RegisterClient().
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 DidBootstrapDatabaseForEviction(
- GetBucketCallback did_get_bucket_callback,
- bool success);
+
+ // Bootstraps database with storage keys that may not have been registered.
+ // Bootstrapping ensures that there is a bucket entry in the buckets table for
+ // all storage keys that have stored data by quota managed Storage APIs. Will
+ // queue calls to QuotaDatabase during bootstrap to be run after bootstrapping
+ // is complete.
+ void BootstrapDatabase();
+ void DidGetBootstrapFlag(bool is_database_bootstrapped);
+ void DidGetStorageKeysForBootstrap(StorageKeysByType storage_keys_by_type);
+ void DidBootstrapDatabase(QuotaError error);
+ void DidSetDatabaseBootstrapped(QuotaError error);
+ // Runs all callbacks to QuotaDatabase that have been queued during bootstrap.
+ void RunDatabaseCallbacks();
// Called by clients via proxy.
// Registers a quota client to the manager.
@@ -492,11 +520,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl
UsageTracker* GetUsageTracker(blink::mojom::StorageType type) const;
- // 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);
@@ -505,16 +528,33 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl
// bucket from the bucket table.
void DeleteBucketDataInternal(const BucketLocator& bucket,
QuotaClientTypes quota_client_types,
- bool is_eviction,
StatusCallback callback);
+ // Removes the HostDataDeleter that completed its work.
+ //
+ // This method is static because it must call `delete_host_data_callback` even
+ // if the QuotaManagerImpl was destroyed.
+ static void DidDeleteHostData(base::WeakPtr<QuotaManagerImpl> quota_manager,
+ StatusCallback delete_host_data_callback,
+ HostDataDeleter* deleter,
+ blink::mojom::QuotaStatusCode status_code);
+
+ // Removes the BucketDataDeleter that completed its work.
+ //
+ // This method is static because it must call `delete_bucket_data_callback`
+ // even if the QuotaManagerImpl was destroyed.
+ static void DidDeleteBucketData(base::WeakPtr<QuotaManagerImpl> quota_manager,
+ StatusCallback delete_bucket_data_callback,
+ BucketDataDeleter* deleter,
+ blink::mojom::QuotaStatusCode status_code);
+
// Methods for eviction logic.
void StartEviction();
- void DeleteStorageKeyFromDatabase(const blink::StorageKey& storage_key,
- blink::mojom::StorageType type);
- void DeleteBucketFromDatabase(BucketId bucket_id, bool is_eviction);
+ void DeleteBucketFromDatabase(BucketId bucket_id,
+ base::OnceCallback<void(QuotaError)> callback);
- void DidBucketDataEvicted(blink::mojom::QuotaStatusCode status);
+ void DidBucketDataEvicted(QuotaDatabase::BucketTableEntry entry,
+ blink::mojom::QuotaStatusCode status);
void ReportHistogram();
void DidGetTemporaryGlobalUsageForHistogram(int64_t usage,
@@ -534,12 +574,15 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl
// QuotaEvictionHandler.
void GetEvictionBucket(blink::mojom::StorageType type,
- int64_t global_quota,
GetBucketCallback callback) override;
void EvictBucketData(const BucketLocator& bucket,
StatusCallback callback) override;
void GetEvictionRoundInfo(EvictionRoundInfoCallback callback) override;
+ void DidGetBucketInfoForEviction(
+ const BucketLocator& bucket,
+ QuotaErrorOr<QuotaDatabase::BucketTableEntry> result);
+
void DidGetEvictionRoundInfo();
void GetLRUBucket(blink::mojom::StorageType type, GetBucketCallback callback);
@@ -565,6 +608,11 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl
QuotaErrorOr<BucketInfo> result);
void DidGetBucketForDeletion(StatusCallback callback,
QuotaErrorOr<BucketInfo> result);
+ void DidGetBucketForUsage(QuotaClientType client_type,
+ int64_t delta,
+ base::Time modification_time,
+ base::OnceClosure callback,
+ QuotaErrorOr<BucketInfo> result);
void DidGetStorageKeys(GetStorageKeysCallback callback,
QuotaErrorOr<std::set<blink::StorageKey>> result);
void DidGetBuckets(
@@ -581,7 +629,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl
int64_t available_space);
// Used from quota-internals page to test behavior of the storage pressure
// callback.
- void SimulateStoragePressure(const blink::StorageKey& storage_key);
+ void SimulateStoragePressure(const url::Origin& origin_url) override;
// Evaluates disk statistics to identify storage pressure
// (low disk space availability) and starts the storage
@@ -594,28 +642,28 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl
absl::optional<int64_t> GetQuotaOverrideForStorageKey(
const blink::StorageKey&);
- // TODO(ayui): Replace instances to use result with QuotaErrorOr.
- void PostTaskAndReplyWithResultForDBThread(
- const base::Location& from_here,
- base::OnceCallback<bool(QuotaDatabase*)> task,
- base::OnceCallback<void(bool)> reply);
-
template <typename ValueType>
void PostTaskAndReplyWithResultForDBThread(
base::OnceCallback<QuotaErrorOr<ValueType>(QuotaDatabase*)> task,
base::OnceCallback<void(QuotaErrorOr<ValueType>)> reply,
- const base::Location& from_here = base::Location::Current());
+ const base::Location& from_here = base::Location::Current(),
+ bool is_bootstrap_task = false);
void PostTaskAndReplyWithResultForDBThread(
base::OnceCallback<QuotaError(QuotaDatabase*)> task,
base::OnceCallback<void(QuotaError)> reply,
- const base::Location& from_here = base::Location::Current());
+ const base::Location& from_here = base::Location::Current(),
+ bool is_bootstrap_task = false);
static std::tuple<int64_t, int64_t> CallGetVolumeInfo(
GetVolumeInfoFn get_volume_info_fn,
const base::FilePath& path);
static std::tuple<int64_t, int64_t> GetVolumeInfo(const base::FilePath& path);
+ bool is_bootstrapping_database_for_testing() {
+ return is_bootstrapping_database_;
+ }
+
bool is_db_disabled_for_testing() { return db_disabled_; }
const bool is_incognito_;
@@ -625,14 +673,20 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl
// points to never changes), and the underlying object is thread-safe.
const scoped_refptr<QuotaManagerProxy> proxy_;
+ int db_error_count_ = 0;
bool db_disabled_ = false;
bool eviction_disabled_ = false;
+ bool bootstrap_disabled_for_testing_ = false;
+
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_for_eviction_ = false;
+ bool is_bootstrapping_database_ = false;
+ // Queued callbacks to QuotaDatabase that will run after database bootstrap is
+ // complete.
+ std::vector<base::OnceClosure> database_callbacks_;
GetQuotaSettingsFunc get_settings_function_;
scoped_refptr<base::TaskRunner> get_settings_task_runner_;
@@ -659,6 +713,10 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl
std::map<blink::StorageKey, QuotaOverride> devtools_overrides_;
int next_override_handle_id_ = 0;
+ // Serve mojo connections for chrome://quota-internals pages.
+ mojo::ReceiverSet<mojom::QuotaInternalsHandler> internals_handlers_receivers_
+ GUARDED_BY_CONTEXT(sequence_checker_);
+
// Owns the QuotaClient remotes registered via RegisterClient().
//
// Iterating over this list is almost always incorrect. Most algorithms should
@@ -707,6 +765,11 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl
GetVolumeInfoFn get_volume_info_fn_;
std::unique_ptr<EvictionRoundInfoHelper> eviction_helper_;
+ std::map<HostDataDeleter*, std::unique_ptr<HostDataDeleter>>
+ host_data_deleters_;
+ std::map<BucketDataDeleter*, std::unique_ptr<BucketDataDeleter>>
+ bucket_data_deleters_;
+ std::unique_ptr<StorageKeyGathererTask> storage_key_gatherer_;
SEQUENCE_CHECKER(sequence_checker_);
diff --git a/chromium/storage/browser/quota/quota_manager_proxy.cc b/chromium/storage/browser/quota/quota_manager_proxy.cc
index 196f97ca311..8cce82b9af9 100644
--- a/chromium/storage/browser/quota/quota_manager_proxy.cc
+++ b/chromium/storage/browser/quota/quota_manager_proxy.cc
@@ -35,6 +35,9 @@ namespace {
void DidGetBucket(scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback,
QuotaErrorOr<BucketInfo> result) {
+ DCHECK(callback_task_runner);
+ DCHECK(callback);
+
if (callback_task_runner->RunsTasksInCurrentSequence()) {
std::move(callback).Run(std::move(result));
return;
@@ -47,6 +50,9 @@ void DidGetStatus(
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
base::OnceCallback<void(blink::mojom::QuotaStatusCode)> callback,
blink::mojom::QuotaStatusCode status) {
+ DCHECK(callback_task_runner);
+ DCHECK(callback);
+
if (callback_task_runner->RunsTasksInCurrentSequence()) {
std::move(callback).Run(std::move(status));
return;
@@ -87,11 +93,27 @@ void QuotaManagerProxy::RegisterClient(
}
}
+void QuotaManagerProxy::BindInternalsHandler(
+ mojo::PendingReceiver<mojom::QuotaInternalsHandler> receiver) {
+ if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
+ quota_manager_impl_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&QuotaManagerProxy::BindInternalsHandler,
+ this, std::move(receiver)));
+ return;
+ }
+ DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_);
+ if (quota_manager_impl_)
+ quota_manager_impl_->BindInternalsHandler(std::move(receiver));
+}
+
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) {
+ DCHECK(callback_task_runner);
+ DCHECK(callback);
+
if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
quota_manager_impl_task_runner_->PostTask(
FROM_HERE,
@@ -114,12 +136,46 @@ void QuotaManagerProxy::GetOrCreateBucket(
std::move(callback)));
}
+void QuotaManagerProxy::GetOrCreateBucketDeprecated(
+ 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<BucketInfo>)> callback) {
+ DCHECK(callback_task_runner);
+ DCHECK(callback);
+
+ if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
+ quota_manager_impl_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&QuotaManagerProxy::GetOrCreateBucketDeprecated, 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_) {
+ DidGetBucket(std::move(callback_task_runner), std::move(callback),
+ QuotaErrorOr<BucketInfo>(QuotaError::kUnknownError));
+ return;
+ }
+
+ quota_manager_impl_->GetOrCreateBucketDeprecated(
+ storage_key, bucket_name, storage_type,
+ base::BindOnce(&DidGetBucket, std::move(callback_task_runner),
+ std::move(callback)));
+}
+
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<BucketInfo>)> callback) {
+ DCHECK(callback_task_runner);
+ DCHECK(callback);
+
if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
quota_manager_impl_task_runner_->PostTask(
FROM_HERE,
@@ -148,6 +204,9 @@ void QuotaManagerProxy::GetBucket(
blink::mojom::StorageType type,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback) {
+ DCHECK(callback_task_runner);
+ DCHECK(callback);
+
if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
quota_manager_impl_task_runner_->PostTask(
FROM_HERE,
@@ -175,6 +234,9 @@ void QuotaManagerProxy::DeleteBucket(
const std::string& bucket_name,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
base::OnceCallback<void(blink::mojom::QuotaStatusCode)> callback) {
+ DCHECK(callback_task_runner);
+ DCHECK(callback);
+
if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
quota_manager_impl_task_runner_->PostTask(
FROM_HERE,
@@ -234,7 +296,9 @@ void QuotaManagerProxy::NotifyStorageModified(
base::Time modification_time,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
base::OnceClosure callback) {
- DCHECK(!callback || callback_task_runner);
+ DCHECK(callback_task_runner);
+ DCHECK(callback);
+
if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
quota_manager_impl_task_runner_->PostTask(
FROM_HERE,
@@ -272,7 +336,9 @@ void QuotaManagerProxy::NotifyBucketModified(
base::Time modification_time,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
base::OnceClosure callback) {
- DCHECK(!callback || callback_task_runner);
+ DCHECK(callback_task_runner);
+ DCHECK(callback);
+
if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
quota_manager_impl_task_runner_->PostTask(
FROM_HERE,
@@ -341,6 +407,9 @@ void DidGetUsageAndQuota(
blink::mojom::QuotaStatusCode status,
int64_t usage,
int64_t quota) {
+ DCHECK(callback_task_runner);
+ DCHECK(callback);
+
if (callback_task_runner->RunsTasksInCurrentSequence()) {
std::move(callback).Run(status, usage, quota);
return;
@@ -356,6 +425,9 @@ void QuotaManagerProxy::GetUsageAndQuota(
blink::mojom::StorageType type,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
UsageAndQuotaCallback callback) {
+ DCHECK(callback_task_runner);
+ DCHECK(callback);
+
if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
quota_manager_impl_task_runner_->PostTask(
FROM_HERE,
@@ -383,6 +455,9 @@ void QuotaManagerProxy::IsStorageUnlimited(
blink::mojom::StorageType type,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
base::OnceCallback<void(bool)> callback) {
+ DCHECK(callback_task_runner);
+ DCHECK(callback);
+
if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
quota_manager_impl_task_runner_->PostTask(
FROM_HERE,
@@ -417,6 +492,9 @@ void QuotaManagerProxy::OverrideQuotaForStorageKey(
absl::optional<int64_t> quota_size,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
base::OnceClosure callback) {
+ DCHECK(callback_task_runner);
+ DCHECK(callback);
+
if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
quota_manager_impl_task_runner_->PostTask(
FROM_HERE,
diff --git a/chromium/storage/browser/quota/quota_manager_proxy.h b/chromium/storage/browser/quota/quota_manager_proxy.h
index a6f0648c1c7..1b68cc3e359 100644
--- a/chromium/storage/browser/quota/quota_manager_proxy.h
+++ b/chromium/storage/browser/quota/quota_manager_proxy.h
@@ -67,6 +67,9 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerProxy
QuotaClientType client_type,
const std::vector<blink::mojom::StorageType>& storage_types);
+ virtual void BindInternalsHandler(
+ mojo::PendingReceiver<mojom::QuotaInternalsHandler> receiver);
+
// 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
@@ -77,6 +80,17 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerProxy
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback);
+ // Same as GetOrCreateBucket but takes in StorageType. This should only be
+ // used by FileSystem, and is expected to be removed when
+ // StorageType::kSyncable and StorageType::kPersistent are deprecated.
+ // (crbug.com/1233525, crbug.com/1286964).
+ virtual void GetOrCreateBucketDeprecated(
+ 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<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.
@@ -132,8 +146,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerProxy
blink::mojom::StorageType type,
int64_t delta,
base::Time modification_time,
- scoped_refptr<base::SequencedTaskRunner> callback_task_runner = nullptr,
- base::OnceClosure callback = base::OnceClosure());
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+ base::OnceClosure callback);
// 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
@@ -146,8 +160,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerProxy
BucketId bucket_id,
int64_t delta,
base::Time modification_time,
- scoped_refptr<base::SequencedTaskRunner> callback_task_runner = nullptr,
- base::OnceClosure callback = base::OnceClosure());
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+ base::OnceClosure callback);
virtual void NotifyWriteFailed(const blink::StorageKey& storage_key);
diff --git a/chromium/storage/browser/quota/quota_manager_unittest.cc b/chromium/storage/browser/quota/quota_manager_unittest.cc
index 113ce82329e..96ab2a51517 100644
--- a/chromium/storage/browser/quota/quota_manager_unittest.cc
+++ b/chromium/storage/browser/quota/quota_manager_unittest.cc
@@ -6,6 +6,7 @@
#include <stdint.h>
#include <algorithm>
+#include <cstdint>
#include <memory>
#include <set>
#include <sstream>
@@ -27,6 +28,7 @@
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
+#include "base/test/test_future.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/services/storage/public/cpp/buckets/bucket_locator.h"
@@ -41,6 +43,7 @@
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/browser/quota/quota_override_handle.h"
#include "storage/browser/test/mock_quota_client.h"
+#include "storage/browser/test/mock_quota_database.h"
#include "storage/browser/test/mock_special_storage_policy.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -68,6 +71,29 @@ const int64_t kDefaultPoolSize = 1000;
const int64_t kDefaultPerHostQuota = 200;
const int64_t kGigabytes = QuotaManagerImpl::kGBytes;
+struct UsageAndQuotaResult {
+ QuotaStatusCode status;
+ int64_t usage;
+ int64_t quota;
+};
+
+struct GlobalUsageResult {
+ int64_t usage;
+ int64_t unlimited_usage;
+};
+
+struct StorageCapacityResult {
+ int64_t total_space;
+ int64_t available_space;
+};
+
+struct ClientBucketData {
+ const char* origin;
+ std::string name;
+ StorageType type;
+ int64_t usage;
+};
+
// Returns a deterministic value for the amount of available disk space.
int64_t GetAvailableDiskSpaceForTest() {
return kAvailableSpaceForApp + kMustRemainAvailableForSystem;
@@ -91,15 +117,6 @@ MATCHER_P3(MatchesBucketTableEntry, storage_key, type, use_count, "") {
testing::ExplainMatchResult(use_count, arg.use_count, result_listener);
}
-bool ContainsBucket(const std::set<BucketLocator>& buckets,
- const BucketInfo& target_bucket) {
- BucketLocator target_bucket_locator(
- target_bucket.id, target_bucket.storage_key, target_bucket.type,
- target_bucket.name == kDefaultBucketName);
- auto it = buckets.find(target_bucket_locator);
- return it != buckets.end();
-}
-
} // namespace
class QuotaManagerImplTest : public testing::Test {
@@ -145,11 +162,12 @@ class QuotaManagerImplTest : public testing::Test {
}
MockQuotaClient* CreateAndRegisterClient(
- base::span<const MockStorageKeyData> mock_data,
QuotaClientType client_type,
- const std::vector<blink::mojom::StorageType> storage_types) {
+ const std::vector<blink::mojom::StorageType> storage_types,
+ base::span<const UnmigratedStorageKeyData> unmigrated_data =
+ base::span<const UnmigratedStorageKeyData>()) {
auto mock_quota_client = std::make_unique<storage::MockQuotaClient>(
- quota_manager_impl_->proxy(), mock_data, client_type);
+ quota_manager_impl_->proxy(), client_type, unmigrated_data);
MockQuotaClient* mock_quota_client_ptr = mock_quota_client.get();
mojo::PendingRemote<storage::mojom::QuotaClient> quota_client;
@@ -160,115 +178,92 @@ class QuotaManagerImplTest : public testing::Test {
return mock_quota_client_ptr;
}
+ // Creates buckets in QuotaDatabase if they don't exist yet, and sets usage
+ // to the `client`.
+ void RegisterClientBucketData(MockQuotaClient* client,
+ base::span<const ClientBucketData> mock_data) {
+ std::map<BucketLocator, int64_t> buckets_data;
+ for (const ClientBucketData& data : mock_data) {
+ base::test::TestFuture<QuotaErrorOr<BucketInfo>> future;
+ quota_manager_impl_->GetOrCreateBucketDeprecated(
+ ToStorageKey(data.origin), data.name, data.type,
+ future.GetCallback());
+ auto bucket = future.Take();
+ EXPECT_TRUE(bucket.ok());
+ buckets_data.insert(std::pair<BucketLocator, int64_t>(
+ bucket->ToBucketLocator(), data.usage));
+ }
+ client->AddBucketsData(buckets_data);
+ }
+
void OpenDatabase() { quota_manager_impl_->EnsureDatabaseOpened(); }
- 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();
+ QuotaErrorOr<BucketInfo> GetOrCreateBucket(const StorageKey& storage_key,
+ const std::string& bucket_name) {
+ base::test::TestFuture<QuotaErrorOr<BucketInfo>> future;
+ quota_manager_impl_->GetOrCreateBucket(storage_key, bucket_name,
+ future.GetCallback());
+ return future.Take();
}
- void CreateBucketForTesting(const StorageKey& storage_key,
- const std::string& bucket_name,
- blink::mojom::StorageType storage_type) {
- base::RunLoop run_loop;
+ QuotaErrorOr<BucketInfo> CreateBucketForTesting(
+ const StorageKey& storage_key,
+ const std::string& bucket_name,
+ blink::mojom::StorageType storage_type) {
+ base::test::TestFuture<QuotaErrorOr<BucketInfo>> future;
quota_manager_impl_->CreateBucketForTesting(
- storage_key, bucket_name, storage_type,
- base::BindOnce(&QuotaManagerImplTest::DidGetBucket,
- weak_factory_.GetWeakPtr(), run_loop.QuitClosure()));
- run_loop.Run();
+ storage_key, bucket_name, storage_type, future.GetCallback());
+ return future.Take();
}
- 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();
+ QuotaErrorOr<BucketInfo> GetBucket(const StorageKey& storage_key,
+ const std::string& bucket_name,
+ blink::mojom::StorageType storage_type) {
+ base::test::TestFuture<QuotaErrorOr<BucketInfo>> future;
+ quota_manager_impl_->GetBucket(storage_key, bucket_name, storage_type,
+ future.GetCallback());
+ return future.Take();
}
- void GetStorageKeysForType(blink::mojom::StorageType storage_type) {
- base::RunLoop run_loop;
+ std::set<StorageKey> GetStorageKeysForType(
+ blink::mojom::StorageType storage_type) {
+ base::test::TestFuture<std::set<StorageKey>> future;
quota_manager_impl_->GetStorageKeysForType(
- storage_type,
- base::BindOnce(&QuotaManagerImplTest::DidGetStorageKeys,
- weak_factory_.GetWeakPtr(), run_loop.QuitClosure()));
- run_loop.Run();
+ storage_type, future.GetCallback<const std::set<StorageKey>&>());
+ return future.Take();
}
QuotaErrorOr<std::set<BucketLocator>> GetBucketsForType(
blink::mojom::StorageType storage_type) {
- base::RunLoop run_loop;
- QuotaErrorOr<std::set<BucketLocator>> buckets;
- quota_manager_impl_->GetBucketsForType(
- storage_type, base::BindLambdaForTesting(
- [&](QuotaErrorOr<std::set<BucketLocator>> result) {
- buckets = std::move(result);
- run_loop.Quit();
- }));
- run_loop.Run();
- return buckets;
+ base::test::TestFuture<QuotaErrorOr<std::set<BucketLocator>>> future;
+ quota_manager_impl_->GetBucketsForType(storage_type, future.GetCallback());
+ return future.Take();
}
QuotaErrorOr<std::set<BucketLocator>> GetBucketsForHost(
const std::string& host,
blink::mojom::StorageType storage_type) {
- base::RunLoop run_loop;
- QuotaErrorOr<std::set<BucketLocator>> buckets;
- quota_manager_impl_->GetBucketsForHost(
- host, storage_type,
- base::BindLambdaForTesting(
- [&](QuotaErrorOr<std::set<BucketLocator>> result) {
- buckets = std::move(result);
- run_loop.Quit();
- }));
- run_loop.Run();
- return buckets;
+ base::test::TestFuture<QuotaErrorOr<std::set<BucketLocator>>> future;
+ quota_manager_impl_->GetBucketsForHost(host, storage_type,
+ future.GetCallback());
+ return future.Take();
}
QuotaErrorOr<std::set<BucketLocator>> GetBucketsForStorageKey(
const StorageKey& storage_key,
blink::mojom::StorageType storage_type) {
- base::RunLoop run_loop;
- QuotaErrorOr<std::set<BucketLocator>> buckets;
- quota_manager_impl_->GetBucketsForStorageKey(
- storage_key, storage_type,
- base::BindLambdaForTesting(
- [&](QuotaErrorOr<std::set<BucketLocator>> result) {
- buckets = std::move(result);
- run_loop.Quit();
- }));
- run_loop.Run();
- return buckets;
- }
-
- void GetUsageInfo() {
- usage_info_.clear();
- base::RunLoop run_loop;
- quota_manager_impl_->GetUsageInfo(
- base::BindOnce(&QuotaManagerImplTest::DidGetUsageInfo,
- weak_factory_.GetWeakPtr(), run_loop.QuitClosure()));
- run_loop.Run();
+ base::test::TestFuture<QuotaErrorOr<std::set<BucketLocator>>> future;
+ quota_manager_impl_->GetBucketsForStorageKey(storage_key, storage_type,
+ future.GetCallback());
+ return future.Take();
}
- void GetUsageAndQuotaForWebApps(const StorageKey& storage_key,
- StorageType type) {
- base::RunLoop run_loop;
- quota_status_ = QuotaStatusCode::kUnknown;
- usage_ = -1;
- quota_ = -1;
- quota_manager_impl_->GetUsageAndQuotaForWebApps(
- storage_key, type,
- base::BindOnce(&QuotaManagerImplTest::DidGetUsageAndQuota,
- weak_factory_.GetWeakPtr(), run_loop.QuitClosure()));
- run_loop.Run();
+ UsageAndQuotaResult GetUsageAndQuotaForWebApps(const StorageKey& storage_key,
+ StorageType type) {
+ base::test::TestFuture<QuotaStatusCode, int64_t, int64_t> future;
+ quota_manager_impl_->GetUsageAndQuotaForWebApps(storage_key, type,
+ future.GetCallback());
+ return {future.Get<0>(), future.Get<1>(), future.Get<2>()};
}
void GetUsageAndQuotaWithBreakdown(const StorageKey& storage_key,
@@ -285,17 +280,13 @@ class QuotaManagerImplTest : public testing::Test {
run_loop.Run();
}
- void GetUsageAndQuotaForStorageClient(const StorageKey& storage_key,
- StorageType type) {
- base::RunLoop run_loop;
- quota_status_ = QuotaStatusCode::kUnknown;
- usage_ = -1;
- quota_ = -1;
- quota_manager_impl_->GetUsageAndQuota(
- storage_key, type,
- base::BindOnce(&QuotaManagerImplTest::DidGetUsageAndQuota,
- weak_factory_.GetWeakPtr(), run_loop.QuitClosure()));
- run_loop.Run();
+ UsageAndQuotaResult GetUsageAndQuotaForStorageClient(
+ const StorageKey& storage_key,
+ StorageType type) {
+ base::test::TestFuture<QuotaStatusCode, int64_t, int64_t> future;
+ quota_manager_impl_->GetUsageAndQuota(storage_key, type,
+ future.GetCallback());
+ return {future.Get<0>(), future.Get<1>(), future.Get<2>()};
}
void SetQuotaSettings(int64_t pool_size,
@@ -318,32 +309,25 @@ class QuotaManagerImplTest : public testing::Test {
quota_manager_impl_->SetGetVolumeInfoFnForTesting(fn);
}
- void GetPersistentHostQuota(const std::string& host) {
- quota_status_ = QuotaStatusCode::kUnknown;
- quota_ = -1;
- quota_manager_impl_->GetPersistentHostQuota(
- host, base::BindOnce(&QuotaManagerImplTest::DidGetHostQuota,
- weak_factory_.GetWeakPtr()));
+ int64_t GetPersistentHostQuota(const std::string& host) {
+ base::test::TestFuture<QuotaStatusCode, int64_t> future;
+ quota_manager_impl_->GetPersistentHostQuota(host, future.GetCallback());
+ EXPECT_EQ(future.Get<0>(), QuotaStatusCode::kOk);
+ return future.Get<1>();
}
- void SetPersistentHostQuota(const std::string& host, int64_t new_quota) {
- quota_status_ = QuotaStatusCode::kUnknown;
- quota_ = -1;
- quota_manager_impl_->SetPersistentHostQuota(
- host, new_quota,
- base::BindOnce(&QuotaManagerImplTest::DidGetHostQuota,
- weak_factory_.GetWeakPtr()));
+ int64_t SetPersistentHostQuota(const std::string& host, int64_t new_quota) {
+ base::test::TestFuture<QuotaStatusCode, int64_t> future;
+ quota_manager_impl_->SetPersistentHostQuota(host, new_quota,
+ future.GetCallback());
+ EXPECT_EQ(future.Get<0>(), QuotaStatusCode::kOk);
+ return future.Get<1>();
}
- void GetGlobalUsage(StorageType type) {
- usage_ = -1;
- unlimited_usage_ = -1;
- base::RunLoop run_loop;
- quota_manager_impl_->GetGlobalUsage(
- type,
- base::BindOnce(&QuotaManagerImplTest::DidGetGlobalUsage,
- weak_factory_.GetWeakPtr(), run_loop.QuitClosure()));
- run_loop.Run();
+ GlobalUsageResult GetGlobalUsage(StorageType type) {
+ base::test::TestFuture<int64_t, int64_t> future;
+ quota_manager_impl_->GetGlobalUsage(type, future.GetCallback());
+ return {future.Get<0>(), future.Get<1>()};
}
void GetHostUsageWithBreakdown(const std::string& host, StorageType type) {
@@ -364,60 +348,38 @@ class QuotaManagerImplTest : public testing::Test {
weak_factory_.GetWeakPtr()));
}
- void DeleteClientStorageKeyData(mojom::QuotaClient* client,
- const StorageKey& storage_key,
- StorageType type) {
- DCHECK(client);
- quota_status_ = QuotaStatusCode::kUnknown;
- client->DeleteStorageKeyData(
- storage_key, type,
- base::BindOnce(&QuotaManagerImplTest::StatusCallback,
- weak_factory_.GetWeakPtr()));
+ QuotaStatusCode EvictBucketData(const BucketLocator& bucket) {
+ base::test::TestFuture<QuotaStatusCode> future;
+ quota_manager_impl_->EvictBucketData(bucket, future.GetCallback());
+ return future.Get();
}
- void EvictBucketData(const BucketLocator& bucket) {
- quota_status_ = QuotaStatusCode::kUnknown;
- quota_manager_impl_->EvictBucketData(
- bucket, base::BindOnce(&QuotaManagerImplTest::StatusCallback,
- weak_factory_.GetWeakPtr()));
+ QuotaStatusCode DeleteBucketData(const BucketLocator& bucket,
+ QuotaClientTypes quota_client_types) {
+ base::test::TestFuture<QuotaStatusCode> future;
+ quota_manager_impl_->DeleteBucketData(bucket, std::move(quota_client_types),
+ future.GetCallback());
+ return future.Get();
}
- void DeleteBucketData(const BucketLocator& bucket,
- QuotaClientTypes quota_client_types) {
- quota_status_ = QuotaStatusCode::kUnknown;
- quota_manager_impl_->DeleteBucketData(
- bucket, std::move(quota_client_types),
- base::BindOnce(&QuotaManagerImplTest::StatusCallback,
- weak_factory_.GetWeakPtr()));
- }
-
- void DeleteHostData(const std::string& host,
- StorageType type,
- QuotaClientTypes quota_client_types) {
- quota_status_ = QuotaStatusCode::kUnknown;
- quota_manager_impl_->DeleteHostData(
- host, type, std::move(quota_client_types),
- base::BindOnce(&QuotaManagerImplTest::StatusCallback,
- weak_factory_.GetWeakPtr()));
+ QuotaStatusCode DeleteHostData(const std::string& host, StorageType type) {
+ base::test::TestFuture<QuotaStatusCode> future;
+ quota_manager_impl_->DeleteHostData(host, type, future.GetCallback());
+ return future.Get();
}
- void FindAndDeleteBucketData(const StorageKey& storage_key,
- const std::string& bucket_name) {
- base::RunLoop run_loop;
- quota_status_ = QuotaStatusCode::kUnknown;
- quota_manager_impl_->FindAndDeleteBucketData(
- storage_key, bucket_name,
- base::BindOnce(&QuotaManagerImplTest::StatusCallbackSync,
- weak_factory_.GetWeakPtr(), run_loop.QuitClosure()));
- run_loop.Run();
+ QuotaStatusCode FindAndDeleteBucketData(const StorageKey& storage_key,
+ const std::string& bucket_name) {
+ base::test::TestFuture<QuotaStatusCode> future;
+ quota_manager_impl_->FindAndDeleteBucketData(storage_key, bucket_name,
+ future.GetCallback());
+ return future.Get();
}
- void GetStorageCapacity() {
- available_space_ = -1;
- total_space_ = -1;
- quota_manager_impl_->GetStorageCapacity(
- base::BindOnce(&QuotaManagerImplTest::DidGetStorageCapacity,
- weak_factory_.GetWeakPtr()));
+ StorageCapacityResult GetStorageCapacity() {
+ base::test::TestFuture<int64_t, int64_t> future;
+ quota_manager_impl_->GetStorageCapacity(future.GetCallback());
+ return {future.Get<0>(), future.Get<1>()};
}
void GetEvictionRoundInfo() {
@@ -431,10 +393,6 @@ class QuotaManagerImplTest : public testing::Test {
weak_factory_.GetWeakPtr()));
}
- std::set<StorageKey> GetCachedStorageKeys(StorageType type) {
- return quota_manager_impl_->GetCachedStorageKeys(type);
- }
-
void NotifyStorageAccessed(const StorageKey& storage_key, StorageType type) {
quota_manager_impl_->NotifyStorageAccessed(storage_key, type,
IncrementMockTime());
@@ -444,71 +402,38 @@ class QuotaManagerImplTest : public testing::Test {
quota_manager_impl_->NotifyBucketAccessed(bucket_id, IncrementMockTime());
}
- void DeleteBucketFromDatabase(BucketId bucket_id) {
- quota_manager_impl_->DeleteBucketFromDatabase(bucket_id, false);
- }
-
void GetEvictionBucket(StorageType type) {
eviction_bucket_.reset();
// The quota manager's default eviction policy is to use an LRU eviction
// policy.
quota_manager_impl_->GetEvictionBucket(
- type, 0,
- base::BindOnce(&QuotaManagerImplTest::DidGetEvictionBucket,
- weak_factory_.GetWeakPtr()));
+ type, base::BindOnce(&QuotaManagerImplTest::DidGetEvictionBucket,
+ weak_factory_.GetWeakPtr()));
}
- void GetBucketsModifiedBetween(StorageType type,
- base::Time begin,
- base::Time end) {
- modified_buckets_.clear();
- modified_buckets_type_ = StorageType::kUnknown;
- base::RunLoop run_loop;
+ std::set<BucketLocator> GetBucketsModifiedBetween(StorageType type,
+ base::Time begin,
+ base::Time end) {
+ base::test::TestFuture<std::set<BucketLocator>, StorageType> future;
quota_manager_impl_->GetBucketsModifiedBetween(
type, begin, end,
- base::BindOnce(&QuotaManagerImplTest::DidGetModifiedBuckets,
- weak_factory_.GetWeakPtr(), run_loop.QuitClosure()));
- run_loop.Run();
+ future.GetCallback<const std::set<BucketLocator>&, StorageType>());
+ EXPECT_EQ(future.Get<1>(), type);
+ return future.Get<0>();
}
- void DumpQuotaTable() {
- quota_entries_.clear();
- quota_manager_impl_->DumpQuotaTable(base::BindOnce(
- &QuotaManagerImplTest::DidDumpQuotaTable, weak_factory_.GetWeakPtr()));
+ QuotaTableEntries DumpQuotaTable() {
+ base::test::TestFuture<QuotaTableEntries> future;
+ quota_manager_impl_->DumpQuotaTable(
+ future.GetCallback<const QuotaTableEntries&>());
+ return future.Get();
}
- void DumpBucketTable() {
- bucket_entries_.clear();
- quota_manager_impl_->DumpBucketTable(base::BindOnce(
- &QuotaManagerImplTest::DidDumpBucketTable, weak_factory_.GetWeakPtr()));
- }
-
- 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(base::OnceClosure quit_closure,
- UsageInfoEntries entries) {
- usage_info_ = std::move(entries);
- std::move(quit_closure).Run();
- }
-
- void DidGetUsageAndQuota(base::OnceClosure quit_closure,
- QuotaStatusCode status,
- int64_t usage,
- int64_t quota) {
- quota_status_ = status;
- usage_ = usage;
- quota_ = quota;
- std::move(quit_closure).Run();
+ BucketTableEntries DumpBucketTable() {
+ base::test::TestFuture<BucketTableEntries> future;
+ quota_manager_impl_->DumpBucketTable(
+ future.GetCallback<const BucketTableEntries&>());
+ return future.Get();
}
void DidGetUsageAndQuotaWithBreakdown(
@@ -524,43 +449,6 @@ class QuotaManagerImplTest : public testing::Test {
std::move(quit_closure).Run();
}
- void DidGetQuota(QuotaStatusCode status, int64_t quota) {
- quota_status_ = status;
- quota_ = quota;
- }
-
- void DidGetStorageCapacity(int64_t total_space, int64_t available_space) {
- total_space_ = total_space;
- available_space_ = available_space;
- }
-
- void DidGetHostQuota(QuotaStatusCode status, int64_t quota) {
- quota_status_ = status;
- quota_ = quota;
- }
-
- void DidGetGlobalUsage(base::OnceClosure quit_closure,
- int64_t usage,
- int64_t unlimited_usage) {
- usage_ = usage;
- unlimited_usage_ = unlimited_usage;
- std::move(quit_closure).Run();
- }
-
- void DidGetHostUsage(int64_t usage) { usage_ = usage; }
-
- void StatusCallback(QuotaStatusCode status) {
- ++status_callback_count_;
- quota_status_ = status;
- }
-
- void StatusCallbackSync(base::OnceClosure quit_closure,
- QuotaStatusCode status) {
- ++status_callback_count_;
- quota_status_ = status;
- std::move(quit_closure).Run();
- }
-
void DidGetHostUsageBreakdown(
base::OnceClosure quit_closure,
int64_t usage,
@@ -589,22 +477,6 @@ class QuotaManagerImplTest : public testing::Test {
!bucket->storage_key.origin().GetURL().is_empty());
}
- void DidGetModifiedBuckets(base::OnceClosure quit_closure,
- const std::set<BucketLocator>& buckets,
- StorageType type) {
- modified_buckets_ = buckets;
- modified_buckets_type_ = type;
- std::move(quit_closure).Run();
- }
-
- void DidDumpQuotaTable(const QuotaTableEntries& entries) {
- quota_entries_ = entries;
- }
-
- void DidDumpBucketTable(const BucketTableEntries& entries) {
- bucket_entries_ = entries;
- }
-
void GetUsage_WithModifyTestBody(const StorageType type);
void SetStoragePressureCallback(
@@ -630,6 +502,7 @@ class QuotaManagerImplTest : public testing::Test {
QuotaManagerImpl* quota_manager_impl() const {
return quota_manager_impl_.get();
}
+
void set_quota_manager_impl(QuotaManagerImpl* quota_manager_impl) {
quota_manager_impl_ = quota_manager_impl;
}
@@ -646,6 +519,14 @@ class QuotaManagerImplTest : public testing::Test {
quota_manager_impl_->SetQuotaChangeCallbackForTesting(std::move(cb));
}
+ void SetQuotaDatabase(std::unique_ptr<QuotaDatabase> database) {
+ quota_manager_impl_->SetQuotaDatabaseForTesting(std::move(database));
+ }
+
+ bool is_db_bootstrapping() {
+ return quota_manager_impl_->is_bootstrapping_database_for_testing();
+ }
+
bool is_db_disabled() {
return quota_manager_impl_->is_db_disabled_for_testing();
}
@@ -654,34 +535,28 @@ class QuotaManagerImplTest : public testing::Test {
quota_manager_impl_->database_->SetDisabledForTesting(disable);
}
+ void disable_database_bootstrap(bool disable) {
+ quota_manager_impl_->SetBootstrapDisabledForTesting(disable);
+ }
+
QuotaStatusCode status() const { return quota_status_; }
- const UsageInfoEntries& usage_info() const { return usage_info_; }
int64_t usage() const { return usage_; }
const blink::mojom::UsageBreakdown& usage_breakdown() const {
return *usage_breakdown_;
}
- int64_t unlimited_usage() const { return unlimited_usage_; }
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<BucketLocator>& eviction_bucket() const {
return eviction_bucket_;
}
- const std::set<BucketLocator>& modified_buckets() const {
- return modified_buckets_;
- }
- 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_; }
- int status_callback_count() const { return status_callback_count_; }
- void reset_status_callback_count() { status_callback_count_ = 0; }
protected:
base::test::ScopedFeatureList scoped_feature_list_;
base::test::TaskEnvironment task_environment_;
- QuotaErrorOr<BucketInfo> bucket_;
- QuotaErrorOr<std::set<StorageKey>> storage_keys_;
+ base::ScopedTempDir data_dir_;
+ scoped_refptr<QuotaManagerImpl> quota_manager_impl_;
private:
base::Time IncrementMockTime() {
@@ -689,26 +564,16 @@ class QuotaManagerImplTest : public testing::Test {
return base::Time::FromDoubleT(mock_time_counter_ * 10.0);
}
- base::ScopedTempDir data_dir_;
-
- scoped_refptr<QuotaManagerImpl> quota_manager_impl_;
scoped_refptr<MockSpecialStoragePolicy> mock_special_storage_policy_;
QuotaStatusCode quota_status_;
- UsageInfoEntries usage_info_;
int64_t usage_;
blink::mojom::UsageBreakdownPtr usage_breakdown_;
- int64_t unlimited_usage_;
int64_t quota_;
int64_t total_space_;
int64_t available_space_;
absl::optional<BucketLocator> eviction_bucket_;
- std::set<BucketLocator> modified_buckets_;
- StorageType modified_buckets_type_;
- QuotaTableEntries quota_entries_;
- BucketTableEntries bucket_entries_;
QuotaSettings settings_;
- int status_callback_count_;
int additional_callback_count_;
@@ -717,65 +582,136 @@ class QuotaManagerImplTest : public testing::Test {
base::WeakPtrFactory<QuotaManagerImplTest> weak_factory_{this};
};
-TEST_F(QuotaManagerImplTest, GetUsageInfo) {
- static const MockStorageKeyData kData1[] = {
+TEST_F(QuotaManagerImplTest, QuotaDatabaseBootstrap) {
+ static const UnmigratedStorageKeyData 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[] = {
+ static const UnmigratedStorageKeyData 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});
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm}, kData1);
+ CreateAndRegisterClient(QuotaClientType::kDatabase, {kTemp, kPerm}, kData2);
+
+ // OpenDatabase should trigger database bootstrapping.
+ OpenDatabase();
+ EXPECT_TRUE(is_db_bootstrapping());
- GetUsageInfo();
+ // When bootstrapping is complete, queued calls to the QuotaDatabase
+ // should return successfully and buckets for registered storage keys should
+ // already exist.
+ auto bucket =
+ GetBucket(ToStorageKey("http://foo.com/"), kDefaultBucketName, kTemp);
+ EXPECT_FALSE(is_db_bootstrapping());
+ ASSERT_TRUE(bucket.ok());
- 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)));
+ bucket = GetBucket(ToStorageKey("http://foo.com:8080/"), kDefaultBucketName,
+ kTemp);
+ ASSERT_TRUE(bucket.ok());
+
+ bucket = GetBucket(ToStorageKey("https://foo.com:8081/"), kDefaultBucketName,
+ kTemp);
+ ASSERT_TRUE(bucket.ok());
+
+ bucket =
+ GetBucket(ToStorageKey("http://bar.com/"), kDefaultBucketName, kPerm);
+ ASSERT_TRUE(bucket.ok());
+
+ bucket =
+ GetBucket(ToStorageKey("http://example.com/"), kDefaultBucketName, kPerm);
+ ASSERT_TRUE(bucket.ok());
+}
+
+TEST_F(QuotaManagerImplTest, GetUsageInfo) {
+ static const ClientBucketData kData1[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 10},
+ {"http://foo.com:8080/", kDefaultBucketName, kTemp, 15},
+ {"http://bar.com/", "logs", kTemp, 20},
+ {"http://bar.com/", kDefaultBucketName, kPerm, 50},
+ };
+ static const ClientBucketData kData2[] = {
+ {"https://foo.com/", kDefaultBucketName, kTemp, 30},
+ {"https://foo.com:8081/", kDefaultBucketName, kTemp, 35},
+ {"http://bar.com/", kDefaultBucketName, kPerm, 40},
+ {"http://example.com/", kDefaultBucketName, kPerm, 40},
+ };
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ MockQuotaClient* database_client =
+ CreateAndRegisterClient(QuotaClientType::kDatabase, {kTemp, kPerm});
+ RegisterClientBucketData(fs_client, kData1);
+ RegisterClientBucketData(database_client, kData2);
+
+ base::test::TestFuture<UsageInfoEntries> future;
+ quota_manager_impl()->GetUsageInfo(future.GetCallback());
+ auto entries = future.Get();
+
+ EXPECT_THAT(entries, 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, DatabaseDisabledAfterThreshold) {
+ disable_database_bootstrap(true);
+ OpenDatabase();
+
+ // Disable quota database for database error behavior.
+ disable_quota_database(true);
+
+ ASSERT_FALSE(is_db_disabled());
+
+ StorageKey storage_key = ToStorageKey("http://a.com/");
+ std::string bucket_name = "bucket_a";
+
+ auto bucket = GetOrCreateBucket(storage_key, bucket_name);
+ ASSERT_FALSE(bucket.ok());
+ ASSERT_FALSE(is_db_disabled());
+
+ bucket = GetOrCreateBucket(storage_key, bucket_name);
+ ASSERT_FALSE(bucket.ok());
+ ASSERT_FALSE(is_db_disabled());
+
+ // Disables access to QuotaDatabase after error counts passes threshold.
+ bucket = GetBucket(storage_key, bucket_name, kTemp);
+ ASSERT_FALSE(bucket.ok());
+ ASSERT_TRUE(is_db_disabled());
}
TEST_F(QuotaManagerImplTest, GetOrCreateBucket) {
StorageKey storage_key = ToStorageKey("http://a.com/");
std::string bucket_name = "bucket_a";
- GetOrCreateBucket(storage_key, bucket_name);
- ASSERT_TRUE(bucket_.ok());
+ auto bucket = GetOrCreateBucket(storage_key, bucket_name);
+ ASSERT_TRUE(bucket.ok());
- BucketId created_bucket_id = bucket_.value().id;
+ BucketId created_bucket_id = bucket.value().id;
- GetOrCreateBucket(storage_key, bucket_name);
- EXPECT_TRUE(bucket_.ok());
- EXPECT_EQ(bucket_.value().id, created_bucket_id);
+ bucket = GetOrCreateBucket(storage_key, bucket_name);
+ EXPECT_TRUE(bucket.ok());
+ EXPECT_EQ(bucket.value().id, created_bucket_id);
}
TEST_F(QuotaManagerImplTest, GetBucket) {
StorageKey storage_key = ToStorageKey("http://a.com/");
std::string bucket_name = "bucket_a";
- CreateBucketForTesting(storage_key, bucket_name, kTemp);
- ASSERT_TRUE(bucket_.ok());
- BucketInfo created_bucket = bucket_.value();
+ auto bucket = CreateBucketForTesting(storage_key, bucket_name, kTemp);
+ ASSERT_TRUE(bucket.ok());
+ BucketInfo created_bucket = bucket.value();
- GetBucket(storage_key, bucket_name, kTemp);
- ASSERT_TRUE(bucket_.ok());
- BucketInfo retrieved_bucket = bucket_.value();
+ bucket = GetBucket(storage_key, bucket_name, kTemp);
+ ASSERT_TRUE(bucket.ok());
+ BucketInfo retrieved_bucket = bucket.value();
EXPECT_EQ(created_bucket.id, retrieved_bucket.id);
- GetBucket(storage_key, "bucket_b", kTemp);
- ASSERT_FALSE(bucket_.ok());
- EXPECT_EQ(bucket_.error(), QuotaError::kNotFound);
+ bucket = GetBucket(storage_key, "bucket_b", kTemp);
+ ASSERT_FALSE(bucket.ok());
+ EXPECT_EQ(bucket.error(), QuotaError::kNotFound);
ASSERT_FALSE(is_db_disabled());
}
@@ -784,36 +720,36 @@ TEST_F(QuotaManagerImplTest, GetStorageKeysForType) {
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();
+ auto bucket = 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();
+ bucket = 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();
+ bucket = CreateBucketForTesting(storage_key_c, "bucket_c", kPerm);
+ EXPECT_TRUE(bucket.ok());
+ BucketInfo bucket_c = bucket.value();
- GetStorageKeysForType(kTemp);
- EXPECT_THAT(storage_keys_.value(),
+ std::set<StorageKey> storage_keys = GetStorageKeysForType(kTemp);
+ EXPECT_THAT(storage_keys,
testing::UnorderedElementsAre(storage_key_a, storage_key_b));
- GetStorageKeysForType(kPerm);
- EXPECT_THAT(storage_keys_.value(),
- testing::UnorderedElementsAre(storage_key_c));
+ storage_keys = GetStorageKeysForType(kPerm);
+ EXPECT_THAT(storage_keys, testing::UnorderedElementsAre(storage_key_c));
}
TEST_F(QuotaManagerImplTest, GetStorageKeysForTypeWithDatabaseError) {
+ disable_database_bootstrap(true);
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());
+ std::set<StorageKey> storage_keys = GetStorageKeysForType(kTemp);
+ EXPECT_TRUE(storage_keys.empty());
}
TEST_F(QuotaManagerImplTest, GetBucketsForType) {
@@ -821,30 +757,30 @@ TEST_F(QuotaManagerImplTest, GetBucketsForType) {
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();
+ auto bucket = 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();
+ bucket = 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();
+ bucket = CreateBucketForTesting(storage_key_c, kDefaultBucketName, kPerm);
+ EXPECT_TRUE(bucket.ok());
+ BucketInfo bucket_c = bucket.value();
QuotaErrorOr<std::set<BucketLocator>> result = GetBucketsForType(kTemp);
EXPECT_TRUE(result.ok());
std::set<BucketLocator> buckets = result.value();
EXPECT_EQ(2U, buckets.size());
- EXPECT_TRUE(ContainsBucket(buckets, bucket_a));
- EXPECT_TRUE(ContainsBucket(buckets, bucket_b));
+ EXPECT_THAT(buckets, testing::Contains(bucket_a.ToBucketLocator()));
+ EXPECT_THAT(buckets, testing::Contains(bucket_b.ToBucketLocator()));
result = GetBucketsForType(kPerm);
buckets = result.value();
EXPECT_EQ(1U, buckets.size());
- EXPECT_TRUE(ContainsBucket(buckets, bucket_c));
+ EXPECT_THAT(buckets, testing::Contains(bucket_c.ToBucketLocator()));
}
TEST_F(QuotaManagerImplTest, GetBucketsForHost) {
@@ -852,17 +788,19 @@ TEST_F(QuotaManagerImplTest, GetBucketsForHost) {
StorageKey host_a_storage_key_2 = ToStorageKey("https://a.com:123/");
StorageKey host_b_storage_key = ToStorageKey("http://b.com/");
- CreateBucketForTesting(host_a_storage_key_1, kDefaultBucketName, kTemp);
- EXPECT_TRUE(bucket_.ok());
- BucketInfo host_a_bucket_1 = bucket_.value();
+ auto bucket =
+ CreateBucketForTesting(host_a_storage_key_1, kDefaultBucketName, kTemp);
+ EXPECT_TRUE(bucket.ok());
+ BucketInfo host_a_bucket_1 = bucket.value();
- CreateBucketForTesting(host_a_storage_key_2, "test", kTemp);
- EXPECT_TRUE(bucket_.ok());
- BucketInfo host_a_bucket_2 = bucket_.value();
+ bucket = CreateBucketForTesting(host_a_storage_key_2, "test", kTemp);
+ EXPECT_TRUE(bucket.ok());
+ BucketInfo host_a_bucket_2 = bucket.value();
- CreateBucketForTesting(host_b_storage_key, kDefaultBucketName, kPerm);
- EXPECT_TRUE(bucket_.ok());
- BucketInfo host_b_bucket = bucket_.value();
+ bucket =
+ CreateBucketForTesting(host_b_storage_key, kDefaultBucketName, kPerm);
+ EXPECT_TRUE(bucket.ok());
+ BucketInfo host_b_bucket = bucket.value();
QuotaErrorOr<std::set<BucketLocator>> result =
GetBucketsForHost("a.com", kTemp);
@@ -870,13 +808,13 @@ TEST_F(QuotaManagerImplTest, GetBucketsForHost) {
std::set<BucketLocator> buckets = result.value();
EXPECT_EQ(2U, buckets.size());
- EXPECT_TRUE(ContainsBucket(buckets, host_a_bucket_1));
- EXPECT_TRUE(ContainsBucket(buckets, host_a_bucket_2));
+ EXPECT_THAT(buckets, testing::Contains(host_a_bucket_1.ToBucketLocator()));
+ EXPECT_THAT(buckets, testing::Contains(host_a_bucket_2.ToBucketLocator()));
result = GetBucketsForHost("b.com", kPerm);
buckets = result.value();
EXPECT_EQ(1U, buckets.size());
- EXPECT_TRUE(ContainsBucket(buckets, host_b_bucket));
+ EXPECT_THAT(buckets, testing::Contains(host_b_bucket.ToBucketLocator()));
}
TEST_F(QuotaManagerImplTest, GetBucketsForStorageKey) {
@@ -884,21 +822,21 @@ TEST_F(QuotaManagerImplTest, GetBucketsForStorageKey) {
StorageKey storage_key_b = ToStorageKey("http://b.com/");
StorageKey storage_key_c = ToStorageKey("http://c.com/");
- CreateBucketForTesting(storage_key_a, "bucket_a1", kTemp);
- EXPECT_TRUE(bucket_.ok());
- BucketInfo bucket_a1 = bucket_.value();
+ auto bucket = CreateBucketForTesting(storage_key_a, "bucket_a1", kTemp);
+ EXPECT_TRUE(bucket.ok());
+ BucketInfo bucket_a1 = bucket.value();
- CreateBucketForTesting(storage_key_a, "bucket_a2", kTemp);
- EXPECT_TRUE(bucket_.ok());
- BucketInfo bucket_a2 = bucket_.value();
+ bucket = CreateBucketForTesting(storage_key_a, "bucket_a2", kTemp);
+ EXPECT_TRUE(bucket.ok());
+ BucketInfo bucket_a2 = bucket.value();
- CreateBucketForTesting(storage_key_b, "bucket_b", kTemp);
- EXPECT_TRUE(bucket_.ok());
- BucketInfo bucket_b = bucket_.value();
+ bucket = 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();
+ bucket = CreateBucketForTesting(storage_key_c, kDefaultBucketName, kPerm);
+ EXPECT_TRUE(bucket.ok());
+ BucketInfo bucket_c = bucket.value();
QuotaErrorOr<std::set<BucketLocator>> result =
GetBucketsForStorageKey(storage_key_a, kTemp);
@@ -906,8 +844,8 @@ TEST_F(QuotaManagerImplTest, GetBucketsForStorageKey) {
std::set<BucketLocator> buckets = result.value();
EXPECT_EQ(2U, buckets.size());
- EXPECT_TRUE(ContainsBucket(buckets, bucket_a1));
- EXPECT_TRUE(ContainsBucket(buckets, bucket_a2));
+ EXPECT_THAT(buckets, testing::Contains(bucket_a1.ToBucketLocator()));
+ EXPECT_THAT(buckets, testing::Contains(bucket_a2.ToBucketLocator()));
result = GetBucketsForStorageKey(storage_key_a, kPerm);
EXPECT_TRUE(result.ok());
@@ -918,43 +856,45 @@ TEST_F(QuotaManagerImplTest, GetBucketsForStorageKey) {
buckets = result.value();
EXPECT_EQ(1U, buckets.size());
- EXPECT_TRUE(ContainsBucket(buckets, bucket_c));
+ EXPECT_THAT(buckets, testing::Contains(bucket_c.ToBucketLocator()));
}
TEST_F(QuotaManagerImplTest, GetUsageAndQuota_Simple) {
- static const MockStorageKeyData kData[] = {
- {"http://foo.com/", kTemp, 10},
- {"http://foo.com/", kPerm, 80},
+ static const ClientBucketData kData[] = {
+ {"http://foo.com/", "logs", kTemp, 10},
+ {"http://foo.com/", kDefaultBucketName, kPerm, 80},
};
- CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ RegisterClientBucketData(fs_client, kData);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(80, usage());
- EXPECT_EQ(0, quota());
+ auto result =
+ GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 80);
+ EXPECT_EQ(result.quota, 0);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(10, usage());
- EXPECT_LE(0, quota());
- int64_t quota_returned_for_foo = quota();
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 10);
+ EXPECT_GT(result.quota, 0);
+ int64_t quota_returned_for_foo = result.quota;
- GetUsageAndQuotaForWebApps(ToStorageKey("http://bar.com/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(0, usage());
- EXPECT_EQ(quota_returned_for_foo, quota());
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://bar.com/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 0);
+ EXPECT_EQ(result.quota, quota_returned_for_foo);
}
TEST_F(QuotaManagerImplTest, GetUsage_NoClient) {
- GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(0, usage());
+ auto result =
+ GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 0);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(0, usage());
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 0);
GetHostUsageWithBreakdown("foo.com", kTemp);
EXPECT_EQ(0, usage());
@@ -962,28 +902,26 @@ TEST_F(QuotaManagerImplTest, GetUsage_NoClient) {
GetHostUsageWithBreakdown("foo.com", kPerm);
EXPECT_EQ(0, usage());
- GetGlobalUsage(kTemp);
- EXPECT_EQ(0, usage());
- EXPECT_EQ(0, unlimited_usage());
+ auto global_usage_result = GetGlobalUsage(kTemp);
+ EXPECT_EQ(global_usage_result.usage, 0);
+ EXPECT_EQ(global_usage_result.unlimited_usage, 0);
- GetGlobalUsage(kPerm);
- EXPECT_EQ(0, usage());
- EXPECT_EQ(0, unlimited_usage());
+ global_usage_result = GetGlobalUsage(kPerm);
+ EXPECT_EQ(global_usage_result.usage, 0);
+ EXPECT_EQ(global_usage_result.unlimited_usage, 0);
}
TEST_F(QuotaManagerImplTest, GetUsage_EmptyClient) {
- CreateAndRegisterClient(base::span<MockStorageKeyData>(),
- QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
- GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(0, usage());
+ auto result =
+ GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 0);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(0, usage());
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 0);
GetHostUsageWithBreakdown("foo.com", kTemp);
EXPECT_EQ(0, usage());
@@ -991,121 +929,127 @@ TEST_F(QuotaManagerImplTest, GetUsage_EmptyClient) {
GetHostUsageWithBreakdown("foo.com", kPerm);
EXPECT_EQ(0, usage());
- GetGlobalUsage(kTemp);
- EXPECT_EQ(0, usage());
- EXPECT_EQ(0, unlimited_usage());
+ auto global_usage_result = GetGlobalUsage(kTemp);
+ EXPECT_EQ(global_usage_result.usage, 0);
+ EXPECT_EQ(global_usage_result.unlimited_usage, 0);
- GetGlobalUsage(kPerm);
- EXPECT_EQ(0, usage());
- EXPECT_EQ(0, unlimited_usage());
+ global_usage_result = GetGlobalUsage(kPerm);
+ EXPECT_EQ(global_usage_result.usage, 0);
+ EXPECT_EQ(global_usage_result.unlimited_usage, 0);
}
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},
+ static const ClientBucketData kData[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 10},
+ {"http://foo.com:8080/", kDefaultBucketName, kTemp, 20},
+ {"http://bar.com/", "logs", kTemp, 5},
+ {"https://bar.com/", "notes", kTemp, 7},
+ {"http://baz.com/", "songs", kTemp, 30},
+ {"http://foo.com/", kDefaultBucketName, kPerm, 40},
};
- CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ RegisterClientBucketData(fs_client, kData);
// This time explicitly sets a temporary global quota.
const int kPoolSize = 100;
const int kPerHostQuota = 20;
SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(10 + 20, usage());
+ auto result =
+ GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 10 + 20);
// The host's quota should be its full portion of the global quota
// since there's plenty of diskspace.
- EXPECT_EQ(kPerHostQuota, quota());
+ EXPECT_EQ(result.quota, kPerHostQuota);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://bar.com/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(5 + 7, usage());
- EXPECT_EQ(kPerHostQuota, quota());
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://bar.com/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 5 + 7);
+ EXPECT_EQ(result.quota, kPerHostQuota);
}
TEST_F(QuotaManagerImplTest, GetUsage_MultipleClients) {
- 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 ClientBucketData kData1[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 1},
+ {"http://bar.com/", kDefaultBucketName, kTemp, 2},
+ {"http://bar.com/", kDefaultBucketName, kPerm, 4},
+ {"http://unlimited/", kDefaultBucketName, kPerm, 8},
};
- static const MockStorageKeyData kData2[] = {
- {"https://foo.com/", kTemp, 128},
- {"http://example.com/", kPerm, 256},
- {"http://unlimited/", kTemp, 512},
+ static const ClientBucketData kData2[] = {
+ {"https://foo.com/", kDefaultBucketName, kTemp, 128},
+ {"http://example.com/", kDefaultBucketName, kPerm, 256},
+ {"http://unlimited/", "logs", kTemp, 512},
};
mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/"));
- GetStorageCapacity();
- CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
- CreateAndRegisterClient(kData2, QuotaClientType::kDatabase,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ auto storage_capacity = GetStorageCapacity();
+
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ MockQuotaClient* database_client =
+ CreateAndRegisterClient(QuotaClientType::kDatabase, {kTemp, kPerm});
+ RegisterClientBucketData(fs_client, kData1);
+ RegisterClientBucketData(database_client, kData2);
const int64_t kPoolSize = GetAvailableDiskSpaceForTest();
const int64_t kPerHostQuota = kPoolSize / 5;
SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(1 + 128, usage());
- EXPECT_EQ(kPerHostQuota, quota());
+ auto result =
+ GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 1 + 128);
+ EXPECT_EQ(result.quota, kPerHostQuota);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://bar.com/"), kPerm);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(4, usage());
- EXPECT_EQ(0, quota());
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://bar.com/"), kPerm);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 4);
+ EXPECT_EQ(result.quota, 0);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://unlimited/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(512, usage());
- EXPECT_EQ(available_space() + usage(), quota());
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://unlimited/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 512);
+ EXPECT_EQ(result.quota, storage_capacity.available_space + result.usage);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://unlimited/"), kPerm);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(8, usage());
- EXPECT_EQ(available_space() + usage(), quota());
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://unlimited/"), kPerm);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 8);
+ EXPECT_EQ(result.quota, storage_capacity.available_space + result.usage);
- GetGlobalUsage(kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(1 + 2 + 128 + 512, usage());
- EXPECT_EQ(512, unlimited_usage());
+ auto global_usage_result = GetGlobalUsage(kTemp);
+ EXPECT_EQ(global_usage_result.usage, 1 + 2 + 128 + 512);
+ EXPECT_EQ(global_usage_result.unlimited_usage, 512);
- GetGlobalUsage(kPerm);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(4 + 8 + 256, usage());
- EXPECT_EQ(8, unlimited_usage());
+ global_usage_result = GetGlobalUsage(kPerm);
+ EXPECT_EQ(global_usage_result.usage, 4 + 8 + 256);
+ EXPECT_EQ(global_usage_result.unlimited_usage, 8);
}
TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_Simple) {
- blink::mojom::UsageBreakdown usage_breakdown_expected =
- blink::mojom::UsageBreakdown();
- static const MockStorageKeyData kData1[] = {
- {"http://foo.com/", kTemp, 1},
- {"http://foo.com/", kPerm, 80},
+ static const ClientBucketData kData1[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 1},
+ {"http://foo.com/", kDefaultBucketName, kPerm, 80},
};
- static const MockStorageKeyData kData2[] = {
- {"http://foo.com/", kTemp, 4},
+ static const ClientBucketData kData2[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 4},
};
- static const MockStorageKeyData kData3[] = {
- {"http://foo.com/", kTemp, 8},
+ static const ClientBucketData kData3[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 8},
};
- CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
- CreateAndRegisterClient(kData2, QuotaClientType::kDatabase,
- {blink::mojom::StorageType::kTemporary});
- CreateAndRegisterClient(kData3, QuotaClientType::kServiceWorkerCache,
- {blink::mojom::StorageType::kTemporary});
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ MockQuotaClient* db_client =
+ CreateAndRegisterClient(QuotaClientType::kDatabase, {kTemp});
+ MockQuotaClient* sw_client =
+ CreateAndRegisterClient(QuotaClientType::kServiceWorkerCache, {kTemp});
+ RegisterClientBucketData(fs_client, kData1);
+ RegisterClientBucketData(db_client, kData2);
+ RegisterClientBucketData(sw_client, kData3);
+ blink::mojom::UsageBreakdown usage_breakdown_expected =
+ blink::mojom::UsageBreakdown();
GetUsageAndQuotaWithBreakdown(ToStorageKey("http://foo.com/"), kPerm);
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(80, usage());
@@ -1155,17 +1099,20 @@ TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_NoClient) {
}
TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_MultiStorageKeys) {
- blink::mojom::UsageBreakdown usage_breakdown_expected =
- blink::mojom::UsageBreakdown();
- 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},
+ static const ClientBucketData kData[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 10},
+ {"http://foo.com:8080/", "logs", kTemp, 20},
+ {"http://bar.com/", kDefaultBucketName, kTemp, 5},
+ {"https://bar.com/", kDefaultBucketName, kTemp, 7},
+ {"http://baz.com/", "logs", kTemp, 30},
+ {"http://foo.com/", kDefaultBucketName, kPerm, 40},
};
- CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ RegisterClientBucketData(fs_client, kData);
+ blink::mojom::UsageBreakdown usage_breakdown_expected =
+ blink::mojom::UsageBreakdown();
GetUsageAndQuotaWithBreakdown(ToStorageKey("http://foo.com/"), kTemp);
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(10 + 20, usage());
@@ -1180,27 +1127,27 @@ TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_MultiStorageKeys) {
}
TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_MultipleClients) {
- blink::mojom::UsageBreakdown usage_breakdown_expected =
- blink::mojom::UsageBreakdown();
- 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 ClientBucketData kData1[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 1},
+ {"http://bar.com/", kDefaultBucketName, kTemp, 2},
+ {"http://bar.com/", kDefaultBucketName, kPerm, 4},
+ {"http://unlimited/", kDefaultBucketName, kPerm, 8},
};
- static const MockStorageKeyData kData2[] = {
- {"https://foo.com/", kTemp, 128},
- {"http://example.com/", kPerm, 256},
- {"http://unlimited/", kTemp, 512},
+ static const ClientBucketData kData2[] = {
+ {"https://foo.com/", kDefaultBucketName, kTemp, 128},
+ {"http://example.com/", kDefaultBucketName, kPerm, 256},
+ {"http://unlimited/", "logs", kTemp, 512},
};
mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/"));
- CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
- CreateAndRegisterClient(kData2, QuotaClientType::kDatabase,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ MockQuotaClient* db_client =
+ CreateAndRegisterClient(QuotaClientType::kDatabase, {kTemp, kPerm});
+ RegisterClientBucketData(fs_client, kData1);
+ RegisterClientBucketData(db_client, kData2);
+ blink::mojom::UsageBreakdown usage_breakdown_expected =
+ blink::mojom::UsageBreakdown();
GetUsageAndQuotaWithBreakdown(ToStorageKey("http://foo.com/"), kTemp);
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(1 + 128, usage());
@@ -1231,35 +1178,46 @@ TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_MultipleClients) {
}
void QuotaManagerImplTest::GetUsage_WithModifyTestBody(const StorageType type) {
- const MockStorageKeyData data[] = {
- {"http://foo.com/", type, 10},
- {"http://foo.com:1/", type, 20},
+ const ClientBucketData kData[] = {
+ {"http://foo.com/", kDefaultBucketName, type, 10},
+ {"http://bar.com/", kDefaultBucketName, type, 0},
+ {"http://foo.com:1/", kDefaultBucketName, type, 20},
+ {"https://foo.com/", kDefaultBucketName, type, 0},
};
MockQuotaClient* client =
- CreateAndRegisterClient(data, QuotaClientType::kFileSystem, {type});
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {type});
+ RegisterClientBucketData(client, kData);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), type);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(10 + 20, usage());
+ auto result =
+ GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), type);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 10 + 20);
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);
+ client->ModifyStorageKeyAndNotify(ToStorageKey("https://foo.com/"), type, 1);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), type);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(10 + 20 + 30 - 5 + 1, usage());
- int foo_usage = usage();
+ // Database call to ensure modification calls have completed.
+ GetBucket(ToStorageKey("http://foo.com"), kDefaultBucketName, kTemp);
- client->AddStorageKeyAndNotify(ToStorageKey("http://bar.com/"), type, 40);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://bar.com/"), type);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(40, usage());
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), type);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 10 + 20 + 30 - 5 + 1);
+ int foo_usage = result.usage;
- GetGlobalUsage(type);
- EXPECT_EQ(foo_usage + 40, usage());
- EXPECT_EQ(0, unlimited_usage());
+ client->ModifyStorageKeyAndNotify(ToStorageKey("http://bar.com/"), type, 40);
+
+ // Database call to ensure modification calls have completed.
+ GetBucket(ToStorageKey("http://foo.com"), kDefaultBucketName, kTemp);
+
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://bar.com/"), type);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 40);
+
+ auto global_usage_result = GetGlobalUsage(type);
+ EXPECT_EQ(global_usage_result.usage, foo_usage + 40);
+ EXPECT_EQ(global_usage_result.unlimited_usage, 0);
}
TEST_F(QuotaManagerImplTest, GetTemporaryUsage_WithModify) {
@@ -1267,15 +1225,15 @@ TEST_F(QuotaManagerImplTest, GetTemporaryUsage_WithModify) {
}
TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_WithAdditionalTasks) {
- 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},
+ static const ClientBucketData kData[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 10},
+ {"http://foo.com:8080/", kDefaultBucketName, kTemp, 20},
+ {"http://bar.com/", "logs", kTemp, 13},
+ {"http://foo.com/", "inbox", kPerm, 40},
};
- CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ RegisterClientBucketData(fs_client, kData);
const int kPoolSize = 100;
const int kPerHostQuota = 20;
@@ -1283,32 +1241,34 @@ TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_WithAdditionalTasks) {
GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp);
GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(10 + 20, usage());
- EXPECT_EQ(kPerHostQuota, quota());
+ auto result =
+ GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 10 + 20);
+ EXPECT_EQ(result.quota, kPerHostQuota);
set_additional_callback_count(0);
RunAdditionalUsageAndQuotaTask(ToStorageKey("http://foo.com/"), kTemp);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp);
+ result = 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());
- EXPECT_EQ(kPerHostQuota, quota());
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 10 + 20);
+ EXPECT_EQ(result.quota, kPerHostQuota);
EXPECT_EQ(2, additional_callback_count());
}
TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_NukeManager) {
- 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},
+ static const ClientBucketData kData[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 10},
+ {"http://foo.com:8080/", kDefaultBucketName, kTemp, 20},
+ {"http://bar.com/", kDefaultBucketName, kTemp, 13},
+ {"http://foo.com/", kDefaultBucketName, kPerm, 40},
};
- CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ RegisterClientBucketData(fs_client, kData);
+
const int kPoolSize = 100;
const int kPerHostQuota = 20;
SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem);
@@ -1319,23 +1279,30 @@ TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_NukeManager) {
RunAdditionalUsageAndQuotaTask(ToStorageKey("http://foo.com/"), kTemp);
RunAdditionalUsageAndQuotaTask(ToStorageKey("http://bar.com/"), kTemp);
- DeleteHostData("foo.com", kTemp, AllQuotaClientTypes());
- DeleteHostData("bar.com", kTemp, AllQuotaClientTypes());
+ base::test::TestFuture<QuotaStatusCode> future_foo;
+ base::test::TestFuture<QuotaStatusCode> future_bar;
+ quota_manager_impl()->DeleteHostData("foo.com", kTemp,
+ future_foo.GetCallback());
+ quota_manager_impl()->DeleteHostData("bar.com", kTemp,
+ future_bar.GetCallback());
// Nuke before waiting for callbacks.
set_quota_manager_impl(nullptr);
- task_environment_.RunUntilIdle();
- EXPECT_EQ(QuotaStatusCode::kErrorAbort, status());
+
+ EXPECT_EQ(QuotaStatusCode::kErrorAbort, future_foo.Get());
+ EXPECT_EQ(QuotaStatusCode::kErrorAbort, future_bar.Get());
}
TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_Overbudget) {
- static const MockStorageKeyData kData[] = {
- {"http://usage1/", kTemp, 1},
- {"http://usage10/", kTemp, 10},
- {"http://usage200/", kTemp, 200},
+ static const ClientBucketData kData[] = {
+ {"http://usage1/", kDefaultBucketName, kTemp, 1},
+ {"http://usage10/", kDefaultBucketName, kTemp, 10},
+ {"http://usage200/", kDefaultBucketName, kTemp, 200},
};
- CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary});
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp});
+ RegisterClientBucketData(fs_client, kData);
+
const int kPoolSize = 100;
const int kPerHostQuota = 20;
SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem);
@@ -1343,187 +1310,187 @@ TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_Overbudget) {
// Provided diskspace is not tight, global usage does not affect the
// 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());
+ auto storage_capacity = GetStorageCapacity();
+ EXPECT_LE(kMustRemainAvailableForSystem, storage_capacity.available_space);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://usage1/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(1, usage());
- EXPECT_EQ(kPerHostQuota, quota());
+ auto result =
+ GetUsageAndQuotaForWebApps(ToStorageKey("http://usage1/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 1);
+ EXPECT_EQ(result.quota, kPerHostQuota);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://usage10/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(10, usage());
- EXPECT_EQ(kPerHostQuota, quota());
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://usage10/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 10);
+ EXPECT_EQ(result.quota, kPerHostQuota);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://usage200/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(200, usage());
- EXPECT_EQ(kPerHostQuota, quota()); // should be clamped to the nominal quota
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://usage200/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 200);
+ // Should be clamped to the nominal quota.
+ EXPECT_EQ(result.quota, kPerHostQuota);
}
TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_Unlimited) {
- static const MockStorageKeyData kData[] = {
- {"http://usage10/", kTemp, 10},
- {"http://usage50/", kTemp, 50},
- {"http://unlimited/", kTemp, 4000},
+ static const ClientBucketData kData[] = {
+ {"http://usage10/", kDefaultBucketName, kTemp, 10},
+ {"http://usage50/", kDefaultBucketName, kTemp, 50},
+ {"http://unlimited/", "inbox", kTemp, 4000},
};
mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/"));
- GetStorageCapacity();
- CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary});
+ auto storage_capacity = GetStorageCapacity();
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp});
+ RegisterClientBucketData(fs_client, kData);
// Test when not overbugdet.
const int kPerHostQuotaFor1000 = 200;
SetQuotaSettings(1000, kPerHostQuotaFor1000, kMustRemainAvailableForSystem);
- GetGlobalUsage(kTemp);
- EXPECT_EQ(10 + 50 + 4000, usage());
- EXPECT_EQ(4000, unlimited_usage());
-
- GetUsageAndQuotaForWebApps(ToStorageKey("http://usage10/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(10, usage());
- EXPECT_EQ(kPerHostQuotaFor1000, quota());
-
- GetUsageAndQuotaForWebApps(ToStorageKey("http://usage50/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(50, usage());
- EXPECT_EQ(kPerHostQuotaFor1000, quota());
-
- GetUsageAndQuotaForWebApps(ToStorageKey("http://unlimited/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(4000, usage());
- EXPECT_EQ(available_space() + usage(), quota());
-
- GetUsageAndQuotaForStorageClient(ToStorageKey("http://unlimited/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(0, usage());
- EXPECT_EQ(QuotaManagerImpl::kNoLimit, quota());
-
- // Test when overbugdet.
+ auto global_usage_result = GetGlobalUsage(kTemp);
+ EXPECT_EQ(global_usage_result.usage, 10 + 50 + 4000);
+ EXPECT_EQ(global_usage_result.unlimited_usage, 4000);
+
+ auto result =
+ GetUsageAndQuotaForWebApps(ToStorageKey("http://usage10/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 10);
+ EXPECT_EQ(result.quota, kPerHostQuotaFor1000);
+
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://usage50/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 50);
+ EXPECT_EQ(result.quota, kPerHostQuotaFor1000);
+
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://unlimited/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 4000);
+ EXPECT_EQ(result.quota, storage_capacity.available_space + result.usage);
+
+ result = GetUsageAndQuotaForStorageClient(ToStorageKey("http://unlimited/"),
+ kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 0);
+ EXPECT_EQ(result.quota, QuotaManagerImpl::kNoLimit);
+
+ // Test when overbudgeted.
const int kPerHostQuotaFor100 = 20;
SetQuotaSettings(100, kPerHostQuotaFor100, kMustRemainAvailableForSystem);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://usage10/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(10, usage());
- EXPECT_EQ(kPerHostQuotaFor100, quota());
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://usage10/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 10);
+ EXPECT_EQ(result.quota, kPerHostQuotaFor100);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://usage50/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(50, usage());
- EXPECT_EQ(kPerHostQuotaFor100, quota());
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://usage50/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 50);
+ EXPECT_EQ(result.quota, kPerHostQuotaFor100);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://unlimited/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(4000, usage());
- EXPECT_EQ(available_space() + usage(), quota());
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://unlimited/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 4000);
+ EXPECT_EQ(result.quota, storage_capacity.available_space + result.usage);
- GetUsageAndQuotaForStorageClient(ToStorageKey("http://unlimited/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(0, usage());
- EXPECT_EQ(QuotaManagerImpl::kNoLimit, quota());
+ result = GetUsageAndQuotaForStorageClient(ToStorageKey("http://unlimited/"),
+ kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 0);
+ EXPECT_EQ(result.quota, QuotaManagerImpl::kNoLimit);
// Revoke the unlimited rights and make sure the change is noticed.
mock_special_storage_policy()->Reset();
mock_special_storage_policy()->NotifyCleared();
- GetGlobalUsage(kTemp);
- EXPECT_EQ(10 + 50 + 4000, usage());
- EXPECT_EQ(0, unlimited_usage());
+ global_usage_result = GetGlobalUsage(kTemp);
+ EXPECT_EQ(global_usage_result.usage, 10 + 50 + 4000);
+ EXPECT_EQ(global_usage_result.unlimited_usage, 0);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://usage10/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(10, usage());
- EXPECT_EQ(kPerHostQuotaFor100, quota());
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://usage10/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 10);
+ EXPECT_EQ(result.quota, kPerHostQuotaFor100);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://usage50/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(50, usage());
- EXPECT_EQ(kPerHostQuotaFor100, quota());
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://usage50/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 50);
+ EXPECT_EQ(result.quota, kPerHostQuotaFor100);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://unlimited/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(4000, usage());
- EXPECT_EQ(kPerHostQuotaFor100, quota());
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://unlimited/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 4000);
+ EXPECT_EQ(result.quota, kPerHostQuotaFor100);
- GetUsageAndQuotaForStorageClient(ToStorageKey("http://unlimited/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(4000, usage());
- EXPECT_EQ(kPerHostQuotaFor100, quota());
+ result = GetUsageAndQuotaForStorageClient(ToStorageKey("http://unlimited/"),
+ kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 4000);
+ EXPECT_EQ(result.quota, kPerHostQuotaFor100);
}
TEST_F(QuotaManagerImplTest, GetAndSetPerststentHostQuota) {
- CreateAndRegisterClient(base::span<MockStorageKeyData>(),
- QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
-
- GetPersistentHostQuota("foo.com");
- task_environment_.RunUntilIdle();
- EXPECT_EQ(0, quota());
-
- SetPersistentHostQuota("foo.com", 100);
- task_environment_.RunUntilIdle();
- EXPECT_EQ(100, quota());
-
- GetPersistentHostQuota("foo.com");
- SetPersistentHostQuota("foo.com", 200);
- GetPersistentHostQuota("foo.com");
- SetPersistentHostQuota("foo.com",
- QuotaManagerImpl::kPerHostPersistentQuotaLimit);
- GetPersistentHostQuota("foo.com");
- task_environment_.RunUntilIdle();
- EXPECT_EQ(QuotaManagerImpl::kPerHostPersistentQuotaLimit, quota());
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+
+ EXPECT_EQ(GetPersistentHostQuota("foo.com"), 0);
+ EXPECT_EQ(SetPersistentHostQuota("foo.com", 100), 100);
+
+ // Should still succeed after multiple calls at once.
+ base::test::TestFuture<QuotaStatusCode, int64_t> future1;
+ base::test::TestFuture<QuotaStatusCode, int64_t> future2;
+ base::test::TestFuture<QuotaStatusCode, int64_t> future3;
+ quota_manager_impl()->SetPersistentHostQuota("foo.com", 200,
+ future1.GetCallback());
+ quota_manager_impl()->SetPersistentHostQuota("foo.com", 300,
+ future2.GetCallback());
+ quota_manager_impl()->SetPersistentHostQuota(
+ "foo.com", QuotaManagerImpl::kPerHostPersistentQuotaLimit,
+ future3.GetCallback());
+ EXPECT_EQ(GetPersistentHostQuota("foo.com"),
+ QuotaManagerImpl::kPerHostPersistentQuotaLimit);
// Persistent quota should be capped at the per-host quota limit.
SetPersistentHostQuota("foo.com",
QuotaManagerImpl::kPerHostPersistentQuotaLimit + 100);
- GetPersistentHostQuota("foo.com");
- task_environment_.RunUntilIdle();
- EXPECT_EQ(QuotaManagerImpl::kPerHostPersistentQuotaLimit, quota());
+ EXPECT_EQ(GetPersistentHostQuota("foo.com"),
+ QuotaManagerImpl::kPerHostPersistentQuotaLimit);
}
TEST_F(QuotaManagerImplTest, GetAndSetPersistentUsageAndQuota) {
- GetStorageCapacity();
- CreateAndRegisterClient(base::span<MockStorageKeyData>(),
- QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ auto storage_capacity = GetStorageCapacity();
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
- GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(0, usage());
- EXPECT_EQ(0, quota());
+ auto result =
+ GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 0);
+ EXPECT_EQ(result.quota, 0);
SetPersistentHostQuota("foo.com", 100);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(0, usage());
- EXPECT_EQ(100, quota());
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 0);
+ EXPECT_EQ(result.quota, 100);
// The actual space available is given to 'unlimited' storage keys as their
// quota.
mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/"));
- GetUsageAndQuotaForWebApps(ToStorageKey("http://unlimited/"), kPerm);
- EXPECT_EQ(available_space() + usage(), quota());
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://unlimited/"), kPerm);
+ EXPECT_EQ(result.quota, storage_capacity.available_space + result.usage);
- // GetUsageAndQuotaForStorageClient should just return 0 usage and
- // kNoLimit quota.
- GetUsageAndQuotaForStorageClient(ToStorageKey("http://unlimited/"), kPerm);
- EXPECT_EQ(0, usage());
- EXPECT_EQ(QuotaManagerImpl::kNoLimit, quota());
+ result = GetUsageAndQuotaForStorageClient(ToStorageKey("http://unlimited/"),
+ kPerm);
+ EXPECT_EQ(result.usage, 0);
+ EXPECT_EQ(result.quota, QuotaManagerImpl::kNoLimit);
}
TEST_F(QuotaManagerImplTest, GetQuotaLowAvailableDiskSpace) {
- static const MockStorageKeyData kData[] = {
- {"http://foo.com/", kTemp, 100000},
- {"http://unlimited/", kTemp, 4000000},
+ static const ClientBucketData kData[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 100000},
+ {"http://unlimited/", kDefaultBucketName, kTemp, 4000000},
};
- CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary});
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp});
+ RegisterClientBucketData(fs_client, kData);
const int kPoolSize = 10000000;
const int kPerHostQuota = kPoolSize / 5;
@@ -1536,17 +1503,15 @@ TEST_F(QuotaManagerImplTest, GetQuotaLowAvailableDiskSpace) {
static_cast<int>(GetAvailableDiskSpaceForTest() - 65536);
SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailable);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(100000, usage());
- EXPECT_EQ(kPerHostQuota, quota());
+ auto result =
+ GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 100000);
+ EXPECT_EQ(result.quota, kPerHostQuota);
}
TEST_F(QuotaManagerImplTest, GetSyncableQuota) {
- CreateAndRegisterClient(base::span<MockStorageKeyData>(),
- QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kSyncable});
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kSync});
// Pre-condition check: available disk space (for testing) is less than
// the default quota for syncable storage.
@@ -1560,28 +1525,34 @@ TEST_F(QuotaManagerImplTest, GetSyncableQuota) {
// storage, shall have their quota calculation take into account the amount of
// available disk space.
mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/"));
- GetUsageAndQuotaForWebApps(ToStorageKey("http://unlimited/"), kSync);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(0, usage());
- EXPECT_EQ(QuotaManagerImpl::kSyncableStorageDefaultHostQuota, quota());
+ auto result =
+ GetUsageAndQuotaForWebApps(ToStorageKey("http://unlimited/"), kSync);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 0);
+ EXPECT_EQ(result.quota, QuotaManagerImpl::kSyncableStorageDefaultHostQuota);
}
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},
+ static const ClientBucketData kData[] = {
+ {"http://foo.com/", kDefaultBucketName, kPerm, 10},
+ {"http://foo.com:8080/", kDefaultBucketName, kPerm, 20},
+ {"https://foo.com/", kDefaultBucketName, kPerm, 13},
+ {"https://foo.com:8081/", kDefaultBucketName, kPerm, 19},
+ {"http://bar.com/", kDefaultBucketName, kPerm, 5},
+ {"https://bar.com/", kDefaultBucketName, kPerm, 7},
+ {"http://baz.com/", kDefaultBucketName, kPerm, 30},
+ {"http://foo.com/", kDefaultBucketName, kTemp, 40},
};
- CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ RegisterClientBucketData(fs_client, kData);
SetPersistentHostQuota("foo.com", 100);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(10 + 20 + 13 + 19, usage());
- EXPECT_EQ(100, quota());
+ auto result =
+ GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 10 + 20 + 13 + 19);
+ EXPECT_EQ(result.quota, 100);
}
TEST_F(QuotaManagerImplTest, GetPersistentUsage_WithModify) {
@@ -1589,44 +1560,45 @@ TEST_F(QuotaManagerImplTest, GetPersistentUsage_WithModify) {
}
TEST_F(QuotaManagerImplTest, GetPersistentUsageAndQuota_WithAdditionalTasks) {
- 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},
+ static const ClientBucketData kData[] = {
+ {"http://foo.com/", kDefaultBucketName, kPerm, 10},
+ {"http://foo.com:8080/", kDefaultBucketName, kPerm, 20},
+ {"http://bar.com/", kDefaultBucketName, kPerm, 13},
+ {"http://foo.com/", kDefaultBucketName, kTemp, 40},
};
- CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ RegisterClientBucketData(fs_client, kData);
SetPersistentHostQuota("foo.com", 100);
GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm);
GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(10 + 20, usage());
- EXPECT_EQ(100, quota());
+ auto result =
+ GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 10 + 20);
+ EXPECT_EQ(result.quota, 100);
set_additional_callback_count(0);
RunAdditionalUsageAndQuotaTask(ToStorageKey("http://foo.com/"), kPerm);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm);
+ result = 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());
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 10 + 20);
+ EXPECT_EQ(additional_callback_count(), 2);
}
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},
+ static const ClientBucketData kData[] = {
+ {"http://foo.com/", kDefaultBucketName, kPerm, 10},
+ {"http://foo.com:8080/", kDefaultBucketName, kPerm, 20},
+ {"http://bar.com/", kDefaultBucketName, kPerm, 13},
+ {"http://foo.com/", kDefaultBucketName, kTemp, 40},
};
- CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ RegisterClientBucketData(fs_client, kData);
SetPersistentHostQuota("foo.com", 100);
set_additional_callback_count(0);
@@ -1649,23 +1621,26 @@ TEST_F(QuotaManagerImplTest, GetPersistentUsageAndQuota_NukeManager) {
}
TEST_F(QuotaManagerImplTest, GetUsage_Simple) {
- 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},
+ static const ClientBucketData kData[] = {
+ {"http://foo.com/", kDefaultBucketName, kPerm, 1},
+ {"http://foo.com:1/", kDefaultBucketName, kPerm, 20},
+ {"http://bar.com/", kDefaultBucketName, kTemp, 300},
+ {"https://buz.com/", kDefaultBucketName, kTemp, 4000},
+ {"http://buz.com/", kDefaultBucketName, kTemp, 50000},
+ {"http://bar.com:1/", kDefaultBucketName, kPerm, 600000},
+ {"http://foo.com/", kDefaultBucketName, kTemp, 7000000},
};
- CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ RegisterClientBucketData(fs_client, kData);
- GetGlobalUsage(kPerm);
- EXPECT_EQ(usage(), 1 + 20 + 600000);
- EXPECT_EQ(0, unlimited_usage());
+ auto global_usage_result = GetGlobalUsage(kPerm);
+ EXPECT_EQ(global_usage_result.usage, 1 + 20 + 600000);
+ EXPECT_EQ(global_usage_result.unlimited_usage, 0);
- GetGlobalUsage(kTemp);
- EXPECT_EQ(usage(), 300 + 4000 + 50000 + 7000000);
- EXPECT_EQ(0, unlimited_usage());
+ global_usage_result = GetGlobalUsage(kTemp);
+ EXPECT_EQ(300 + 4000 + 50000 + 7000000, global_usage_result.usage);
+ EXPECT_EQ(global_usage_result.unlimited_usage, 0);
GetHostUsageWithBreakdown("foo.com", kPerm);
EXPECT_EQ(usage(), 1 + 20);
@@ -1675,38 +1650,40 @@ TEST_F(QuotaManagerImplTest, GetUsage_Simple) {
}
TEST_F(QuotaManagerImplTest, GetUsage_WithModification) {
- 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},
+ static const ClientBucketData kData[] = {
+ {"http://foo.com/", kDefaultBucketName, kPerm, 1},
+ {"http://foo.com:1/", kDefaultBucketName, kPerm, 20},
+ {"http://bar.com/", kDefaultBucketName, kTemp, 300},
+ {"https://buz.com/", kDefaultBucketName, kTemp, 4000},
+ {"http://buz.com/", kDefaultBucketName, kTemp, 50000},
+ {"http://bar.com:1/", kDefaultBucketName, kPerm, 600000},
+ {"http://foo.com/", kDefaultBucketName, kTemp, 7000000},
};
MockQuotaClient* client =
- CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ RegisterClientBucketData(client, kData);
- GetGlobalUsage(kPerm);
- EXPECT_EQ(usage(), 1 + 20 + 600000);
- EXPECT_EQ(0, unlimited_usage());
+ auto global_usage_result = GetGlobalUsage(kPerm);
+ EXPECT_EQ(global_usage_result.usage, 1 + 20 + 600000);
+ EXPECT_EQ(global_usage_result.unlimited_usage, 0);
client->ModifyStorageKeyAndNotify(ToStorageKey("http://foo.com/"), kPerm,
80000000);
- GetGlobalUsage(kPerm);
- EXPECT_EQ(usage(), 1 + 20 + 600000 + 80000000);
- EXPECT_EQ(0, unlimited_usage());
+ global_usage_result = GetGlobalUsage(kPerm);
+ EXPECT_EQ(global_usage_result.usage, 1 + 20 + 600000 + 80000000);
+ EXPECT_EQ(global_usage_result.unlimited_usage, 0);
- GetGlobalUsage(kTemp);
- EXPECT_EQ(usage(), 300 + 4000 + 50000 + 7000000);
- EXPECT_EQ(0, unlimited_usage());
+ global_usage_result = GetGlobalUsage(kTemp);
+ EXPECT_EQ(global_usage_result.usage, 300 + 4000 + 50000 + 7000000);
+ EXPECT_EQ(global_usage_result.unlimited_usage, 0);
client->ModifyStorageKeyAndNotify(ToStorageKey("http://foo.com/"), kTemp, 1);
- GetGlobalUsage(kTemp);
- EXPECT_EQ(usage(), 300 + 4000 + 50000 + 7000000 + 1);
- EXPECT_EQ(0, unlimited_usage());
+ global_usage_result = GetGlobalUsage(kTemp);
+ EXPECT_EQ(global_usage_result.usage, 300 + 4000 + 50000 + 7000000 + 1);
+ EXPECT_EQ(global_usage_result.unlimited_usage, 0);
GetHostUsageWithBreakdown("buz.com", kTemp);
EXPECT_EQ(usage(), 4000 + 50000);
@@ -1718,20 +1695,19 @@ TEST_F(QuotaManagerImplTest, GetUsage_WithModification) {
EXPECT_EQ(usage(), 4000 + 50000 + 900000000);
}
-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},
+TEST_F(QuotaManagerImplTest, GetUsage_WithDeleteBucket) {
+ static const ClientBucketData kData[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 1},
+ {"http://foo.com:1/", kDefaultBucketName, kTemp, 20},
+ {"http://foo.com/", kDefaultBucketName, kPerm, 300},
+ {"http://bar.com/", kDefaultBucketName, kTemp, 4000},
};
MockQuotaClient* client =
- CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ RegisterClientBucketData(client, kData);
- GetGlobalUsage(kTemp);
- int64_t predelete_global_tmp = usage();
+ auto global_usage_result = GetGlobalUsage(kTemp);
+ int64_t predelete_global_tmp = global_usage_result.usage;
GetHostUsageWithBreakdown("foo.com", kTemp);
int64_t predelete_host_tmp = usage();
@@ -1739,12 +1715,16 @@ TEST_F(QuotaManagerImplTest, GetUsage_WithDeleteStorageKey) {
GetHostUsageWithBreakdown("foo.com", kPerm);
int64_t predelete_host_pers = usage();
- DeleteClientStorageKeyData(client, ToStorageKey("http://foo.com/"), kTemp);
- task_environment_.RunUntilIdle();
- EXPECT_EQ(QuotaStatusCode::kOk, status());
+ auto bucket =
+ GetBucket(ToStorageKey("http://foo.com/"), kDefaultBucketName, kTemp);
+ EXPECT_TRUE(bucket.ok());
- GetGlobalUsage(kTemp);
- EXPECT_EQ(predelete_global_tmp - 1, usage());
+ auto status = DeleteBucketData(bucket->ToBucketLocator(),
+ {QuotaClientType::kFileSystem});
+ EXPECT_EQ(status, QuotaStatusCode::kOk);
+
+ global_usage_result = GetGlobalUsage(kTemp);
+ EXPECT_EQ(global_usage_result.usage, predelete_global_tmp - 1);
GetHostUsageWithBreakdown("foo.com", kTemp);
EXPECT_EQ(predelete_host_tmp - 1, usage());
@@ -1754,33 +1734,34 @@ TEST_F(QuotaManagerImplTest, GetUsage_WithDeleteStorageKey) {
}
TEST_F(QuotaManagerImplTest, GetStorageCapacity) {
- GetStorageCapacity();
- task_environment_.RunUntilIdle();
- EXPECT_LE(0, total_space());
- EXPECT_LE(0, available_space());
+ auto storage_capacity = GetStorageCapacity();
+ EXPECT_GE(storage_capacity.total_space, 0);
+ EXPECT_GE(storage_capacity.available_space, 0);
}
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 ClientBucketData kData1[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 1},
+ {"http://foo.com:1/", "logs", kTemp, 20},
+ {"http://foo.com/", kDefaultBucketName, kPerm, 300},
+ {"http://bar.com/", kDefaultBucketName, 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},
+ static const ClientBucketData kData2[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 50000},
+ {"http://foo.com:1/", "logs", kTemp, 6000},
+ {"http://foo.com/", kDefaultBucketName, kPerm, 700},
+ {"https://foo.com/", kDefaultBucketName, kTemp, 80},
+ {"http://bar.com/", kDefaultBucketName, 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});
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ MockQuotaClient* db_client =
+ CreateAndRegisterClient(QuotaClientType::kDatabase, {kTemp, kPerm});
+ RegisterClientBucketData(fs_client, kData1);
+ RegisterClientBucketData(db_client, kData2);
- GetGlobalUsage(kTemp);
- int64_t predelete_global_tmp = usage();
+ auto global_usage_result = GetGlobalUsage(kTemp);
+ int64_t predelete_global_tmp = global_usage_result.usage;
GetHostUsageWithBreakdown("foo.com", kTemp);
int64_t predelete_host_tmp = usage();
@@ -1788,116 +1769,74 @@ TEST_F(QuotaManagerImplTest, EvictBucketData) {
GetHostUsageWithBreakdown("foo.com", kPerm);
int64_t predelete_host_pers = usage();
- for (const MockStorageKeyData& data : kData1) {
+ for (const ClientBucketData& data : kData1) {
quota_manager_impl()->NotifyStorageAccessed(ToStorageKey(data.origin),
data.type, base::Time::Now());
}
- for (const MockStorageKeyData& data : kData2) {
+ for (const ClientBucketData& data : kData2) {
quota_manager_impl()->NotifyStorageAccessed(ToStorageKey(data.origin),
data.type, base::Time::Now());
}
task_environment_.RunUntilIdle();
- GetBucket(ToStorageKey("http://foo.com/"), kDefaultBucketName, kTemp);
- ASSERT_TRUE(bucket_.ok());
-
- EvictBucketData(bucket_->ToBucketLocator());
- task_environment_.RunUntilIdle();
+ // Default bucket eviction.
+ auto bucket =
+ GetBucket(ToStorageKey("http://foo.com/"), kDefaultBucketName, kTemp);
+ ASSERT_TRUE(bucket.ok());
- DumpBucketTable();
- task_environment_.RunUntilIdle();
+ ASSERT_EQ(EvictBucketData(bucket->ToBucketLocator()), QuotaStatusCode::kOk);
- for (const auto& entry : bucket_entries()) {
- if (entry.type == kTemp) {
- EXPECT_NE(std::string("http://foo.com/"),
- entry.storage_key.origin().GetURL().spec());
- }
- }
+ bucket =
+ GetBucket(ToStorageKey("http://foo.com/"), kDefaultBucketName, kTemp);
+ ASSERT_FALSE(bucket.ok());
+ ASSERT_EQ(bucket.error(), QuotaError::kNotFound);
- GetGlobalUsage(kTemp);
- EXPECT_EQ(predelete_global_tmp - (1 + 50000), usage());
+ global_usage_result = GetGlobalUsage(kTemp);
+ EXPECT_EQ(predelete_global_tmp - (1 + 50000), global_usage_result.usage);
GetHostUsageWithBreakdown("foo.com", kTemp);
EXPECT_EQ(predelete_host_tmp - (1 + 50000), usage());
GetHostUsageWithBreakdown("foo.com", kPerm);
EXPECT_EQ(predelete_host_pers, usage());
-}
-
-TEST_F(QuotaManagerImplTest, EvictNonDefaultBucketData) {
- static const MockStorageKeyData kData[] = {{"http://foo.com/", kTemp, 100}};
- CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, {kTemp});
- GetGlobalUsage(kTemp);
- int64_t predelete_global_tmp = usage();
+ // Non default bucket eviction.
+ bucket = GetBucket(ToStorageKey("http://foo.com:1"), "logs", kTemp);
+ ASSERT_TRUE(bucket.ok());
- GetHostUsageWithBreakdown("foo.com", kTemp);
- int64_t predelete_host_tmp = usage();
+ ASSERT_EQ(EvictBucketData(bucket->ToBucketLocator()), QuotaStatusCode::kOk);
- StorageKey storage_key = ToStorageKey("http://foo.com/");
- quota_manager_impl()->NotifyStorageAccessed(storage_key, kTemp,
- base::Time::Now());
- task_environment_.RunUntilIdle();
+ bucket = GetBucket(ToStorageKey("http://foo.com:1"), "logs", kTemp);
+ EXPECT_EQ(bucket.error(), QuotaError::kNotFound);
- CreateBucketForTesting(storage_key, "foo_bucket", kTemp);
- ASSERT_TRUE(bucket_.ok());
- BucketInfo created_bucket = bucket_.value();
-
- EvictBucketData(created_bucket.ToBucketLocator());
- 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);
- EXPECT_EQ(predelete_global_tmp, usage());
+ global_usage_result = GetGlobalUsage(kTemp);
+ EXPECT_EQ(predelete_global_tmp - (1 + 20 + 50000 + 6000),
+ global_usage_result.usage);
GetHostUsageWithBreakdown("foo.com", kTemp);
- EXPECT_EQ(predelete_host_tmp, usage());
-
- GetBucket(storage_key, kDefaultBucketName, kTemp);
- ASSERT_TRUE(bucket_.ok());
- BucketInfo default_bucket = bucket_.value();
-
- EvictBucketData(default_bucket.ToBucketLocator());
- task_environment_.RunUntilIdle();
-
- EXPECT_EQ(QuotaStatusCode::kOk, status());
-
- // Evicting default bucket should remove usage.
- GetGlobalUsage(kTemp);
- EXPECT_EQ(usage(), 0);
+ EXPECT_EQ(predelete_host_tmp - (1 + 20 + 50000 + 6000), usage());
- GetHostUsageWithBreakdown("foo.com", kTemp);
- EXPECT_EQ(usage(), 0);
+ GetHostUsageWithBreakdown("foo.com", kPerm);
+ EXPECT_EQ(predelete_host_pers, usage());
}
TEST_F(QuotaManagerImplTest, EvictBucketDataHistogram) {
- const StorageKey kStorageKey = ToStorageKey("http://foo.com/");
- static const MockStorageKeyData kData[] = {
- {"http://foo.com/", kTemp, 1},
- };
-
base::HistogramTester histograms;
+ static const ClientBucketData kData[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 1},
+ {"http://bar.com/", kDefaultBucketName, kTemp, 1},
+ };
MockQuotaClient* client =
- CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary});
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp});
+ RegisterClientBucketData(client, kData);
GetGlobalUsage(kTemp);
- CreateBucketForTesting(kStorageKey, kDefaultBucketName, kTemp);
- ASSERT_TRUE(bucket_.ok());
+ auto bucket =
+ GetBucket(ToStorageKey("http://foo.com"), kDefaultBucketName, kTemp);
+ ASSERT_TRUE(bucket.ok());
- EvictBucketData(bucket_->ToBucketLocator());
- task_environment_.RunUntilIdle();
+ ASSERT_EQ(EvictBucketData(bucket->ToBucketLocator()), QuotaStatusCode::kOk);
// Ensure use count and time since access are recorded.
histograms.ExpectTotalCount(
@@ -1907,17 +1846,17 @@ TEST_F(QuotaManagerImplTest, EvictBucketDataHistogram) {
histograms.ExpectTotalCount(
QuotaManagerImpl::kEvictedBucketDaysSinceAccessHistogram, 1);
- client->AddStorageKeyAndNotify(kStorageKey, kTemp, 100);
-
- // Change the use count of the storage key.
- quota_manager_impl()->NotifyStorageAccessed(kStorageKey, kTemp,
- base::Time::Now());
+ // Change the use count.
+ quota_manager_impl()->NotifyStorageAccessed(ToStorageKey("http://bar.com/"),
+ kTemp, base::Time::Now());
task_environment_.RunUntilIdle();
GetGlobalUsage(kTemp);
- EvictBucketData(bucket_->ToBucketLocator());
- task_environment_.RunUntilIdle();
+ bucket = GetBucket(ToStorageKey("http://bar.com"), kDefaultBucketName, kTemp);
+ ASSERT_TRUE(bucket.ok());
+
+ ASSERT_EQ(EvictBucketData(bucket->ToBucketLocator()), QuotaStatusCode::kOk);
// The new use count should be logged.
histograms.ExpectTotalCount(
@@ -1929,56 +1868,45 @@ TEST_F(QuotaManagerImplTest, EvictBucketDataHistogram) {
}
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 ClientBucketData kData[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 1},
+ {"http://foo.com:1/", kDefaultBucketName, kTemp, 20},
+ {"http://foo.com/", kDefaultBucketName, kPerm, 300},
+ {"http://bar.com/", kDefaultBucketName, kTemp, 4000},
};
static const int kNumberOfTemporaryBuckets = 3;
MockQuotaClient* client =
- CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ RegisterClientBucketData(client, kData);
- GetGlobalUsage(kTemp);
- int64_t predelete_global_tmp = usage();
+ auto global_usage_result = GetGlobalUsage(kTemp);
+ EXPECT_EQ(global_usage_result.usage, (1 + 20 + 4000));
GetHostUsageWithBreakdown("foo.com", kTemp);
- int64_t predelete_host_tmp = usage();
+ EXPECT_EQ((1 + 20), usage());
GetHostUsageWithBreakdown("foo.com", kPerm);
- int64_t predelete_host_pers = usage();
+ EXPECT_EQ(300, usage());
- for (const MockStorageKeyData& data : kData)
+ for (const ClientBucketData& data : kData)
NotifyStorageAccessed(ToStorageKey(data.origin), data.type);
task_environment_.RunUntilIdle();
- client->AddStorageKeyToErrorSet(ToStorageKey("http://foo.com/"), kTemp);
-
- GetBucket(ToStorageKey("http://foo.com/"), kDefaultBucketName, kTemp);
- ASSERT_TRUE(bucket_.ok());
+ auto bucket =
+ GetBucket(ToStorageKey("http://foo.com/"), kDefaultBucketName, kTemp);
+ ASSERT_TRUE(bucket.ok());
+ client->AddBucketToErrorSet(bucket->ToBucketLocator());
for (int i = 0; i < QuotaManagerImpl::kThresholdOfErrorsToBeDenylisted + 1;
++i) {
- EvictBucketData(bucket_->ToBucketLocator());
- task_environment_.RunUntilIdle();
- EXPECT_EQ(QuotaStatusCode::kErrorInvalidModification, status());
+ ASSERT_EQ(EvictBucketData(bucket->ToBucketLocator()),
+ QuotaStatusCode::kErrorInvalidModification);
}
- DumpBucketTable();
- task_environment_.RunUntilIdle();
-
- bool found_storage_key_in_database = false;
- for (const auto& entry : bucket_entries()) {
- if (entry.type == kTemp && entry.name == kDefaultBucketName &&
- entry.storage_key == ToStorageKey("http://foo.com/")) {
- found_storage_key_in_database = true;
- break;
- }
- }
- // The default bucket for "http://foo.com/" should be in the database.
- EXPECT_TRUE(found_storage_key_in_database);
+ // The default bucket for "http://foo.com/" should still be in the database.
+ bucket =
+ GetBucket(ToStorageKey("http://foo.com/"), kDefaultBucketName, kTemp);
+ EXPECT_TRUE(bucket.ok());
for (size_t i = 0; i < kNumberOfTemporaryBuckets - 1; ++i) {
GetEvictionBucket(kTemp);
@@ -1987,8 +1915,7 @@ TEST_F(QuotaManagerImplTest, EvictBucketDataWithDeletionError) {
// "http://foo.com/" should not be in the LRU list.
EXPECT_NE(std::string("http://foo.com/"),
eviction_bucket()->storage_key.origin().GetURL().spec());
- DeleteBucketFromDatabase(eviction_bucket()->id);
- task_environment_.RunUntilIdle();
+ DeleteBucketData(*eviction_bucket(), AllQuotaClientTypes());
}
// Now the LRU list must be empty.
@@ -1996,30 +1923,28 @@ TEST_F(QuotaManagerImplTest, EvictBucketDataWithDeletionError) {
task_environment_.RunUntilIdle();
EXPECT_FALSE(eviction_bucket().has_value());
- // Deleting buckets from the database should not affect the results of the
- // following checks.
- GetGlobalUsage(kTemp);
- EXPECT_EQ(predelete_global_tmp, usage());
+ global_usage_result = GetGlobalUsage(kTemp);
+ EXPECT_EQ(global_usage_result.usage, 1);
GetHostUsageWithBreakdown("foo.com", kTemp);
- EXPECT_EQ(predelete_host_tmp, usage());
+ EXPECT_EQ(1, usage());
GetHostUsageWithBreakdown("foo.com", kPerm);
- EXPECT_EQ(predelete_host_pers, usage());
+ EXPECT_EQ(300, usage());
}
TEST_F(QuotaManagerImplTest, GetEvictionRoundInfo) {
- static const MockStorageKeyData kData[] = {
- {"http://foo.com/", kTemp, 1},
- {"http://foo.com:1/", kTemp, 20},
- {"http://foo.com/", kPerm, 300},
- {"http://unlimited/", kTemp, 4000},
+ static const ClientBucketData kData[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 1},
+ {"http://foo.com:1/", kDefaultBucketName, kTemp, 20},
+ {"http://foo.com/", kDefaultBucketName, kPerm, 300},
+ {"http://unlimited/", kDefaultBucketName, kTemp, 4000},
};
mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/"));
- CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ MockQuotaClient* client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ RegisterClientBucketData(client, kData);
const int kPoolSize = 10000000;
const int kPerHostQuota = kPoolSize / 5;
@@ -2034,21 +1959,19 @@ TEST_F(QuotaManagerImplTest, GetEvictionRoundInfo) {
}
TEST_F(QuotaManagerImplTest, DeleteHostDataNoClients) {
- DeleteHostData(std::string(), kTemp, AllQuotaClientTypes());
- task_environment_.RunUntilIdle();
- EXPECT_EQ(QuotaStatusCode::kOk, status());
+ EXPECT_EQ(DeleteHostData(std::string(), kTemp), QuotaStatusCode::kOk);
}
TEST_F(QuotaManagerImplTest, DeleteHostDataSimple) {
- static const MockStorageKeyData kData[] = {
- {"http://foo.com/", kTemp, 1},
+ static const ClientBucketData kData[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 1},
};
- CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ MockQuotaClient* client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ RegisterClientBucketData(client, kData);
- GetGlobalUsage(kTemp);
- const int64_t predelete_global_tmp = usage();
+ auto global_usage_result = GetGlobalUsage(kTemp);
+ const int64_t predelete_global_tmp = global_usage_result.usage;
GetHostUsageWithBreakdown("foo.com", kTemp);
int64_t predelete_host_tmp = usage();
@@ -2056,12 +1979,10 @@ TEST_F(QuotaManagerImplTest, DeleteHostDataSimple) {
GetHostUsageWithBreakdown("foo.com", kPerm);
int64_t predelete_host_pers = usage();
- DeleteHostData(std::string(), kTemp, AllQuotaClientTypes());
- task_environment_.RunUntilIdle();
- EXPECT_EQ(QuotaStatusCode::kOk, status());
+ EXPECT_EQ(DeleteHostData(std::string(), kTemp), QuotaStatusCode::kOk);
- GetGlobalUsage(kTemp);
- EXPECT_EQ(predelete_global_tmp, usage());
+ global_usage_result = GetGlobalUsage(kTemp);
+ EXPECT_EQ(global_usage_result.usage, predelete_global_tmp);
GetHostUsageWithBreakdown("foo.com", kTemp);
EXPECT_EQ(predelete_host_tmp, usage());
@@ -2069,12 +1990,10 @@ TEST_F(QuotaManagerImplTest, DeleteHostDataSimple) {
GetHostUsageWithBreakdown("foo.com", kPerm);
EXPECT_EQ(predelete_host_pers, usage());
- DeleteHostData("foo.com", kTemp, AllQuotaClientTypes());
- task_environment_.RunUntilIdle();
- EXPECT_EQ(QuotaStatusCode::kOk, status());
+ EXPECT_EQ(DeleteHostData("foo.com", kTemp), QuotaStatusCode::kOk);
- GetGlobalUsage(kTemp);
- EXPECT_EQ(predelete_global_tmp - 1, usage());
+ global_usage_result = GetGlobalUsage(kTemp);
+ EXPECT_EQ(predelete_global_tmp - 1, global_usage_result.usage);
GetHostUsageWithBreakdown("foo.com", kTemp);
EXPECT_EQ(predelete_host_tmp - 1, usage());
@@ -2084,26 +2003,28 @@ TEST_F(QuotaManagerImplTest, DeleteHostDataSimple) {
}
TEST_F(QuotaManagerImplTest, DeleteHostDataMultiple) {
- 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 ClientBucketData kData1[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 1},
+ {"http://foo.com:1/", kDefaultBucketName, kTemp, 20},
+ {"http://foo.com/", kDefaultBucketName, kPerm, 300},
+ {"http://bar.com/", kDefaultBucketName, 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},
+ static const ClientBucketData kData2[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 50000},
+ {"http://foo.com:1/", kDefaultBucketName, kTemp, 6000},
+ {"http://foo.com/", kDefaultBucketName, kPerm, 700},
+ {"https://foo.com/", kDefaultBucketName, kTemp, 80},
+ {"http://bar.com/", kDefaultBucketName, 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});
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ MockQuotaClient* db_client =
+ CreateAndRegisterClient(QuotaClientType::kDatabase, {kTemp, kPerm});
+ RegisterClientBucketData(fs_client, kData1);
+ RegisterClientBucketData(db_client, kData2);
- GetGlobalUsage(kTemp);
- const int64_t predelete_global_tmp = usage();
+ auto global_usage_result = GetGlobalUsage(kTemp);
+ const int64_t predelete_global_tmp = global_usage_result.usage;
GetHostUsageWithBreakdown("foo.com", kTemp);
const int64_t predelete_foo_tmp = usage();
@@ -2117,18 +2038,12 @@ TEST_F(QuotaManagerImplTest, DeleteHostDataMultiple) {
GetHostUsageWithBreakdown("bar.com", kPerm);
const int64_t predelete_bar_pers = usage();
- reset_status_callback_count();
- DeleteHostData("foo.com", kTemp, AllQuotaClientTypes());
- DeleteHostData("bar.com", kTemp, AllQuotaClientTypes());
- DeleteHostData("foo.com", kTemp, AllQuotaClientTypes());
- task_environment_.RunUntilIdle();
+ EXPECT_EQ(DeleteHostData("foo.com", kTemp), QuotaStatusCode::kOk);
+ EXPECT_EQ(DeleteHostData("bar.com", kTemp), QuotaStatusCode::kOk);
+ EXPECT_EQ(DeleteHostData("foo.com", kTemp), QuotaStatusCode::kOk);
- EXPECT_EQ(3, status_callback_count());
-
- DumpBucketTable();
- task_environment_.RunUntilIdle();
-
- for (const auto& entry : bucket_entries()) {
+ const BucketTableEntries& entries = DumpBucketTable();
+ for (const auto& entry : entries) {
if (entry.type != kTemp)
continue;
@@ -2142,9 +2057,9 @@ TEST_F(QuotaManagerImplTest, DeleteHostDataMultiple) {
entry.storage_key.origin().GetURL().spec());
}
- GetGlobalUsage(kTemp);
- EXPECT_EQ(predelete_global_tmp - (1 + 20 + 4000 + 50000 + 6000 + 80 + 9),
- usage());
+ global_usage_result = GetGlobalUsage(kTemp);
+ EXPECT_EQ(global_usage_result.usage,
+ predelete_global_tmp - (1 + 20 + 4000 + 50000 + 6000 + 80 + 9));
GetHostUsageWithBreakdown("foo.com", kTemp);
EXPECT_EQ(predelete_foo_tmp - (1 + 20 + 50000 + 6000 + 80), usage());
@@ -2160,26 +2075,27 @@ TEST_F(QuotaManagerImplTest, DeleteHostDataMultiple) {
}
TEST_F(QuotaManagerImplTest, DeleteHostDataMultipleClientsDifferentTypes) {
- 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 ClientBucketData kData1[] = {
+ {"http://foo.com/", kDefaultBucketName, kPerm, 1},
+ {"http://foo.com:1/", kDefaultBucketName, kPerm, 10},
+ {"http://foo.com/", kDefaultBucketName, kTemp, 100},
+ {"http://bar.com/", kDefaultBucketName, 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},
+ static const ClientBucketData kData2[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 10000},
+ {"http://foo.com:1/", kDefaultBucketName, kTemp, 100000},
+ {"https://foo.com/", kDefaultBucketName, kTemp, 1000000},
+ {"http://bar.com/", kDefaultBucketName, kTemp, 10000000},
};
- CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
- CreateAndRegisterClient(kData2, QuotaClientType::kDatabase,
- {blink::mojom::StorageType::kTemporary});
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ MockQuotaClient* db_client =
+ CreateAndRegisterClient(QuotaClientType::kDatabase, {kTemp});
+ RegisterClientBucketData(fs_client, kData1);
+ RegisterClientBucketData(db_client, kData2);
- GetGlobalUsage(kTemp);
- const int64_t predelete_global_tmp = usage();
+ auto global_usage_result = GetGlobalUsage(kTemp);
+ const int64_t predelete_global_tmp = global_usage_result.usage;
GetHostUsageWithBreakdown("foo.com", kTemp);
const int64_t predelete_foo_tmp = usage();
@@ -2187,27 +2103,21 @@ TEST_F(QuotaManagerImplTest, DeleteHostDataMultipleClientsDifferentTypes) {
GetHostUsageWithBreakdown("bar.com", kTemp);
const int64_t predelete_bar_tmp = usage();
- GetGlobalUsage(kPerm);
- const int64_t predelete_global_pers = usage();
+ global_usage_result = GetGlobalUsage(kPerm);
+ EXPECT_EQ(global_usage_result.usage, (1000 + 10 + 1));
GetHostUsageWithBreakdown("foo.com", kPerm);
- const int64_t predelete_foo_pers = usage();
+ EXPECT_EQ((10 + 1), usage());
GetHostUsageWithBreakdown("bar.com", kPerm);
- const int64_t predelete_bar_pers = usage();
-
- reset_status_callback_count();
- DeleteHostData("foo.com", kPerm, AllQuotaClientTypes());
- DeleteHostData("bar.com", kPerm, AllQuotaClientTypes());
- task_environment_.RunUntilIdle();
-
- EXPECT_EQ(2, status_callback_count());
+ EXPECT_EQ(1000, usage());
- DumpBucketTable();
- task_environment_.RunUntilIdle();
+ EXPECT_EQ(DeleteHostData("foo.com", kPerm), QuotaStatusCode::kOk);
+ EXPECT_EQ(DeleteHostData("bar.com", kPerm), QuotaStatusCode::kOk);
- for (const auto& entry : bucket_entries()) {
- if (entry.type != kTemp)
+ const BucketTableEntries& entries = DumpBucketTable();
+ for (const auto& entry : entries) {
+ if (entry.type != kPerm)
continue;
EXPECT_NE(std::string("http://foo.com/"),
@@ -2220,8 +2130,8 @@ TEST_F(QuotaManagerImplTest, DeleteHostDataMultipleClientsDifferentTypes) {
entry.storage_key.origin().GetURL().spec());
}
- GetGlobalUsage(kTemp);
- EXPECT_EQ(predelete_global_tmp, usage());
+ global_usage_result = GetGlobalUsage(kTemp);
+ EXPECT_EQ(global_usage_result.usage, predelete_global_tmp);
GetHostUsageWithBreakdown("foo.com", kTemp);
EXPECT_EQ(predelete_foo_tmp, usage());
@@ -2229,57 +2139,56 @@ TEST_F(QuotaManagerImplTest, DeleteHostDataMultipleClientsDifferentTypes) {
GetHostUsageWithBreakdown("bar.com", kTemp);
EXPECT_EQ(predelete_bar_tmp, usage());
- GetGlobalUsage(kPerm);
- EXPECT_EQ(predelete_global_pers - (1 + 10 + 1000), usage());
+ global_usage_result = GetGlobalUsage(kPerm);
+ EXPECT_EQ(global_usage_result.usage, 0);
GetHostUsageWithBreakdown("foo.com", kPerm);
- EXPECT_EQ(predelete_foo_pers - (1 + 10), usage());
+ EXPECT_EQ(0, usage());
GetHostUsageWithBreakdown("bar.com", kPerm);
- EXPECT_EQ(predelete_bar_pers - 1000, usage());
+ EXPECT_EQ(0, usage());
}
TEST_F(QuotaManagerImplTest, DeleteBucketNoClients) {
- CreateBucketForTesting(ToStorageKey("http://foo.com"), kDefaultBucketName,
- kTemp);
- ASSERT_TRUE(bucket_.ok());
+ auto bucket = CreateBucketForTesting(ToStorageKey("http://foo.com"),
+ kDefaultBucketName, kTemp);
+ ASSERT_TRUE(bucket.ok());
- DeleteBucketData(bucket_->ToBucketLocator(), AllQuotaClientTypes());
- task_environment_.RunUntilIdle();
- EXPECT_EQ(QuotaStatusCode::kOk, status());
+ EXPECT_EQ(DeleteBucketData(bucket->ToBucketLocator(), AllQuotaClientTypes()),
+ QuotaStatusCode::kOk);
}
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},
+ static const ClientBucketData kData1[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 1},
+ {"http://foo.com:1/", kDefaultBucketName, kTemp, 20},
+ {"http://foo.com/", kDefaultBucketName, kPerm, 300},
+ {"http://bar.com/", kDefaultBucketName, 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},
+ static const ClientBucketData kData2[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 50000},
+ {"http://foo.com:1/", kDefaultBucketName, kTemp, 6000},
+ {"http://foo.com/", kDefaultBucketName, kPerm, 700},
+ {"https://foo.com/", kDefaultBucketName, kTemp, 80},
+ {"http://bar.com/", kDefaultBucketName, 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});
-
- CreateBucketForTesting(ToStorageKey("http://foo.com"), kDefaultBucketName,
- kTemp);
- ASSERT_TRUE(bucket_.ok());
- BucketInfo foo_temp_bucket = bucket_.value();
-
- CreateBucketForTesting(ToStorageKey("http://bar.com"), kDefaultBucketName,
- kTemp);
- ASSERT_TRUE(bucket_.ok());
- BucketInfo bar_temp_bucket = bucket_.value();
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ MockQuotaClient* db_client =
+ CreateAndRegisterClient(QuotaClientType::kDatabase, {kTemp, kPerm});
+ RegisterClientBucketData(fs_client, kData1);
+ RegisterClientBucketData(db_client, kData2);
- GetGlobalUsage(kTemp);
- const int64_t predelete_global_tmp = usage();
+ auto foo_temp_bucket =
+ GetBucket(ToStorageKey("http://foo.com"), kDefaultBucketName, kTemp);
+ ASSERT_TRUE(foo_temp_bucket.ok());
+
+ auto bar_temp_bucket =
+ GetBucket(ToStorageKey("http://bar.com"), kDefaultBucketName, kTemp);
+ ASSERT_TRUE(bar_temp_bucket.ok());
+
+ auto global_usage_result = GetGlobalUsage(kTemp);
+ const int64_t predelete_global_tmp = global_usage_result.usage;
GetHostUsageWithBreakdown("foo.com", kTemp);
const int64_t predelete_foo_tmp = usage();
@@ -2293,39 +2202,35 @@ TEST_F(QuotaManagerImplTest, DeleteBucketDataMultiple) {
GetHostUsageWithBreakdown("bar.com", kPerm);
const int64_t predelete_bar_pers = usage();
- for (const MockStorageKeyData& data : kData1) {
+ for (const ClientBucketData& data : kData1) {
quota_manager_impl()->NotifyStorageAccessed(ToStorageKey(data.origin),
data.type, base::Time::Now());
}
- for (const MockStorageKeyData& data : kData2) {
+ for (const ClientBucketData& 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.ToBucketLocator(), AllQuotaClientTypes());
- DeleteBucketData(bar_temp_bucket.ToBucketLocator(), AllQuotaClientTypes());
- DeleteBucketData(foo_temp_bucket.ToBucketLocator(), AllQuotaClientTypes());
- task_environment_.RunUntilIdle();
+ EXPECT_EQ(DeleteBucketData(foo_temp_bucket->ToBucketLocator(),
+ AllQuotaClientTypes()),
+ QuotaStatusCode::kOk);
+ EXPECT_EQ(DeleteBucketData(bar_temp_bucket->ToBucketLocator(),
+ AllQuotaClientTypes()),
+ QuotaStatusCode::kOk);
- EXPECT_EQ(3, status_callback_count());
+ QuotaErrorOr<BucketInfo> bucket;
+ bucket = GetBucket(foo_temp_bucket->storage_key, foo_temp_bucket->name,
+ foo_temp_bucket->type);
+ EXPECT_EQ(bucket.error(), QuotaError::kNotFound);
- 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());
- }
+ bucket = GetBucket(bar_temp_bucket->storage_key, bar_temp_bucket->name,
+ bar_temp_bucket->type);
+ EXPECT_EQ(bucket.error(), QuotaError::kNotFound);
- GetGlobalUsage(kTemp);
- EXPECT_EQ(predelete_global_tmp - (1 + 4000 + 50000 + 9), usage());
+ global_usage_result = GetGlobalUsage(kTemp);
+ EXPECT_EQ(global_usage_result.usage,
+ predelete_global_tmp - (1 + 4000 + 50000 + 9));
GetHostUsageWithBreakdown("foo.com", kTemp);
EXPECT_EQ(predelete_foo_tmp - (1 + 50000), usage());
@@ -2341,36 +2246,35 @@ TEST_F(QuotaManagerImplTest, DeleteBucketDataMultiple) {
}
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 ClientBucketData kData1[] = {
+ {"http://foo.com/", kDefaultBucketName, kPerm, 1},
+ {"http://foo.com:1/", kDefaultBucketName, kPerm, 10},
+ {"http://foo.com/", kDefaultBucketName, kTemp, 100},
+ {"http://bar.com/", kDefaultBucketName, 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},
+ static const ClientBucketData kData2[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 10000},
+ {"http://foo.com:1/", kDefaultBucketName, kTemp, 100000},
+ {"https://foo.com/", kDefaultBucketName, kTemp, 1000000},
+ {"http://bar.com/", kDefaultBucketName, 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();
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ MockQuotaClient* db_client =
+ CreateAndRegisterClient(QuotaClientType::kDatabase, {kTemp});
+ RegisterClientBucketData(fs_client, kData1);
+ RegisterClientBucketData(db_client, kData2);
- GetGlobalUsage(kTemp);
- const int64_t predelete_global_tmp = usage();
+ auto foo_perm_bucket =
+ GetBucket(ToStorageKey("http://foo.com/"), kDefaultBucketName, kPerm);
+ ASSERT_TRUE(foo_perm_bucket.ok());
+
+ auto bar_perm_bucket =
+ GetBucket(ToStorageKey("http://bar.com/"), kDefaultBucketName, kPerm);
+ ASSERT_TRUE(bar_perm_bucket.ok());
+
+ auto global_usage_result = GetGlobalUsage(kTemp);
+ const int64_t predelete_global_tmp = global_usage_result.usage;
GetHostUsageWithBreakdown("foo.com", kTemp);
const int64_t predelete_foo_tmp = usage();
@@ -2378,8 +2282,8 @@ TEST_F(QuotaManagerImplTest, DeleteBucketDataMultipleClientsDifferentTypes) {
GetHostUsageWithBreakdown("bar.com", kTemp);
const int64_t predelete_bar_tmp = usage();
- GetGlobalUsage(kPerm);
- const int64_t predelete_global_pers = usage();
+ global_usage_result = GetGlobalUsage(kPerm);
+ const int64_t predelete_global_pers = global_usage_result.usage;
GetHostUsageWithBreakdown("foo.com", kPerm);
const int64_t predelete_foo_pers = usage();
@@ -2387,38 +2291,34 @@ TEST_F(QuotaManagerImplTest, DeleteBucketDataMultipleClientsDifferentTypes) {
GetHostUsageWithBreakdown("bar.com", kPerm);
const int64_t predelete_bar_pers = usage();
- for (const MockStorageKeyData& data : kData1) {
+ for (const ClientBucketData& data : kData1) {
quota_manager_impl()->NotifyStorageAccessed(ToStorageKey(data.origin),
data.type, base::Time::Now());
}
- for (const MockStorageKeyData& data : kData2) {
+ for (const ClientBucketData& 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.ToBucketLocator(), AllQuotaClientTypes());
- DeleteBucketData(bar_perm_bucket.ToBucketLocator(), AllQuotaClientTypes());
- task_environment_.RunUntilIdle();
+ EXPECT_EQ(DeleteBucketData(foo_perm_bucket->ToBucketLocator(),
+ AllQuotaClientTypes()),
+ QuotaStatusCode::kOk);
+ EXPECT_EQ(DeleteBucketData(bar_perm_bucket->ToBucketLocator(),
+ AllQuotaClientTypes()),
+ QuotaStatusCode::kOk);
- EXPECT_EQ(2, status_callback_count());
+ QuotaErrorOr<BucketInfo> bucket;
+ bucket = GetBucket(foo_perm_bucket->storage_key, foo_perm_bucket->name,
+ foo_perm_bucket->type);
+ EXPECT_EQ(bucket.error(), QuotaError::kNotFound);
- DumpBucketTable();
- task_environment_.RunUntilIdle();
+ bucket = GetBucket(bar_perm_bucket->storage_key, bar_perm_bucket->name,
+ bar_perm_bucket->type);
+ EXPECT_EQ(bucket.error(), QuotaError::kNotFound);
- 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);
- EXPECT_EQ(predelete_global_tmp, usage());
+ global_usage_result = GetGlobalUsage(kTemp);
+ EXPECT_EQ(global_usage_result.usage, predelete_global_tmp);
GetHostUsageWithBreakdown("foo.com", kTemp);
EXPECT_EQ(predelete_foo_tmp, usage());
@@ -2426,8 +2326,8 @@ TEST_F(QuotaManagerImplTest, DeleteBucketDataMultipleClientsDifferentTypes) {
GetHostUsageWithBreakdown("bar.com", kTemp);
EXPECT_EQ(predelete_bar_tmp, usage());
- GetGlobalUsage(kPerm);
- EXPECT_EQ(predelete_global_pers - (1 + 1000), usage());
+ global_usage_result = GetGlobalUsage(kPerm);
+ EXPECT_EQ(global_usage_result.usage, predelete_global_pers - (1 + 1000));
GetHostUsageWithBreakdown("foo.com", kPerm);
EXPECT_EQ(predelete_foo_pers - 1, usage());
@@ -2437,35 +2337,33 @@ TEST_F(QuotaManagerImplTest, DeleteBucketDataMultipleClientsDifferentTypes) {
}
TEST_F(QuotaManagerImplTest, FindAndDeleteBucketData) {
- static const MockStorageKeyData kData1[] = {
- {"http://foo.com/", kTemp, 1},
- {"http://bar.com/", kTemp, 4000},
+ static const ClientBucketData kData1[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 1},
+ {"http://bar.com/", kDefaultBucketName, kTemp, 4000},
};
- static const MockStorageKeyData kData2[] = {
- {"http://foo.com/", kTemp, 50000},
- {"http://bar.com/", kTemp, 9},
+ static const ClientBucketData kData2[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 50000},
+ {"http://bar.com/", kDefaultBucketName, 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});
-
- CreateBucketForTesting(ToStorageKey("http://foo.com"), kDefaultBucketName,
- kTemp);
- ASSERT_TRUE(bucket_.ok());
- BucketInfo foo_bucket = bucket_.value();
-
- CreateBucketForTesting(ToStorageKey("http://bar.com"), kDefaultBucketName,
- kTemp);
- ASSERT_TRUE(bucket_.ok());
- BucketInfo bar_bucket = bucket_.value();
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ MockQuotaClient* db_client =
+ CreateAndRegisterClient(QuotaClientType::kDatabase, {kTemp, kPerm});
+ RegisterClientBucketData(fs_client, kData1);
+ RegisterClientBucketData(db_client, kData2);
+
+ auto foo_bucket =
+ GetBucket(ToStorageKey("http://foo.com"), kDefaultBucketName, kTemp);
+ ASSERT_TRUE(foo_bucket.ok());
+
+ auto bar_bucket =
+ GetBucket(ToStorageKey("http://bar.com"), kDefaultBucketName, kTemp);
+ ASSERT_TRUE(bar_bucket.ok());
// Check usage data before deletion.
- GetGlobalUsage(kTemp);
- const int64_t predelete_global_tmp = usage();
- ASSERT_EQ((1 + 9 + 4000 + 50000), usage());
+ auto global_usage_result = GetGlobalUsage(kTemp);
+ ASSERT_EQ((1 + 9 + 4000 + 50000), global_usage_result.usage);
+ const int64_t predelete_global_tmp = global_usage_result.usage;
GetHostUsageWithBreakdown("foo.com", kTemp);
ASSERT_EQ((1 + 50000), usage());
@@ -2474,110 +2372,101 @@ TEST_F(QuotaManagerImplTest, FindAndDeleteBucketData) {
ASSERT_EQ((9 + 4000), usage());
// Delete bucket for "http://foo.com/".
- reset_status_callback_count();
- FindAndDeleteBucketData(foo_bucket.storage_key, foo_bucket.name);
- EXPECT_EQ(1, status_callback_count());
+ EXPECT_EQ(FindAndDeleteBucketData(foo_bucket->storage_key, foo_bucket->name),
+ QuotaStatusCode::kOk);
- GetBucket(foo_bucket.storage_key, foo_bucket.name, foo_bucket.type);
- ASSERT_FALSE(bucket_.ok());
- EXPECT_EQ(bucket_.error(), QuotaError::kNotFound);
+ auto bucket =
+ GetBucket(foo_bucket->storage_key, foo_bucket->name, foo_bucket->type);
+ ASSERT_FALSE(bucket.ok());
+ EXPECT_EQ(bucket.error(), QuotaError::kNotFound);
- GetGlobalUsage(kTemp);
- EXPECT_EQ(predelete_global_tmp - (1 + 50000), usage());
+ global_usage_result = GetGlobalUsage(kTemp);
+ EXPECT_EQ(global_usage_result.usage, predelete_global_tmp - (1 + 50000));
GetHostUsageWithBreakdown("foo.com", kTemp);
EXPECT_EQ(0, usage());
// Delete bucket for "http://bar.com/".
- reset_status_callback_count();
- FindAndDeleteBucketData(bar_bucket.storage_key, bar_bucket.name);
- EXPECT_EQ(1, status_callback_count());
+ EXPECT_EQ(FindAndDeleteBucketData(bar_bucket->storage_key, bar_bucket->name),
+ QuotaStatusCode::kOk);
- GetBucket(bar_bucket.storage_key, bar_bucket.name, bar_bucket.type);
- ASSERT_FALSE(bucket_.ok());
- EXPECT_EQ(bucket_.error(), QuotaError::kNotFound);
+ bucket =
+ GetBucket(bar_bucket->storage_key, bar_bucket->name, bar_bucket->type);
+ ASSERT_FALSE(bucket.ok());
+ EXPECT_EQ(bucket.error(), QuotaError::kNotFound);
- GetGlobalUsage(kTemp);
- EXPECT_EQ(0, usage());
+ global_usage_result = GetGlobalUsage(kTemp);
+ EXPECT_EQ(global_usage_result.usage, 0);
GetHostUsageWithBreakdown("bar.com", kTemp);
EXPECT_EQ(0, usage());
}
-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},
+TEST_F(QuotaManagerImplTest, FindAndDeleteBucketDataWithDBError) {
+ static const ClientBucketData kData[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 123},
};
- CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
- // TODO(kinuko): Be careful when we add cache pruner.
+ auto quota_db = std::make_unique<MockQuotaDatabase>(
+ data_dir_.GetPath().AppendASCII("QuotaManager"));
+ MockQuotaDatabase* mock_database = quota_db.get();
+ SetQuotaDatabase(std::move(quota_db));
- std::set<StorageKey> storage_keys = GetCachedStorageKeys(kTemp);
- EXPECT_TRUE(storage_keys.empty());
+ RegisterClientBucketData(fs_client, kData);
- GetHostUsageWithBreakdown("a.com", kTemp);
- storage_keys = GetCachedStorageKeys(kTemp);
- EXPECT_EQ(2U, storage_keys.size());
+ // Check usage data before deletion.
+ GetHostUsageWithBreakdown("foo.com", kTemp);
+ ASSERT_EQ(123, usage());
- GetHostUsageWithBreakdown("b.com", kTemp);
- storage_keys = GetCachedStorageKeys(kTemp);
- EXPECT_EQ(2U, storage_keys.size());
+ EXPECT_CALL(*mock_database, DeleteBucketInfo)
+ .Times(1)
+ .WillOnce(testing::Return(QuotaError::kDatabaseError));
- GetHostUsageWithBreakdown("c.com", kTemp);
- storage_keys = GetCachedStorageKeys(kTemp);
- EXPECT_EQ(3U, storage_keys.size());
+ // Trying to delete bucket for "http://foo.com/" should return error.
+ EXPECT_EQ(FindAndDeleteBucketData(ToStorageKey("http://foo.com"),
+ kDefaultBucketName),
+ QuotaStatusCode::kErrorInvalidModification);
- storage_keys = GetCachedStorageKeys(kPerm);
- EXPECT_TRUE(storage_keys.empty());
+ auto global_usage_result = GetGlobalUsage(kTemp);
+ EXPECT_EQ(global_usage_result.usage, 0);
- GetGlobalUsage(kTemp);
- storage_keys = GetCachedStorageKeys(kTemp);
- EXPECT_THAT(storage_keys,
- testing::UnorderedElementsAre(ToStorageKey("http://a.com"),
- ToStorageKey("http://c.com"),
- ToStorageKey("http://a.com:1")));
+ GetHostUsageWithBreakdown("foo.com", kTemp);
+ EXPECT_EQ(0, usage());
}
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},
+ static const ClientBucketData kData[] = {
+ {"http://a.com/", kDefaultBucketName, kTemp, 0},
+ {"http://a.com:1/", kDefaultBucketName, kTemp, 0},
+ {"http://b.com/", kDefaultBucketName, kPerm, 0},
+ {"http://c.com/", kDefaultBucketName, kTemp, 0},
};
- CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ RegisterClientBucketData(fs_client, kData);
- GetEvictionBucket(kTemp);
+ quota_manager_impl()->NotifyStorageAccessed(ToStorageKey("http://b.com/"),
+ kPerm, base::Time::Now());
+ quota_manager_impl()->NotifyStorageAccessed(ToStorageKey("http://a.com/"),
+ kTemp, base::Time::Now());
+ quota_manager_impl()->NotifyStorageAccessed(ToStorageKey("http://c.com/"),
+ kTemp, base::Time::Now());
task_environment_.RunUntilIdle();
- EXPECT_FALSE(eviction_bucket().has_value());
- NotifyStorageAccessed(ToStorageKey("http://a.com/"), kTemp);
GetEvictionBucket(kTemp);
task_environment_.RunUntilIdle();
- EXPECT_EQ("http://a.com/",
+ EXPECT_EQ("http://a.com:1/",
eviction_bucket()->storage_key.origin().GetURL().spec());
- NotifyStorageAccessed(ToStorageKey("http://b.com/"), kPerm);
- NotifyStorageAccessed(ToStorageKey("https://a.com/"), kTemp);
- NotifyStorageAccessed(ToStorageKey("http://c.com/"), kTemp);
+ DeleteBucketData(*eviction_bucket(), AllQuotaClientTypes());
GetEvictionBucket(kTemp);
task_environment_.RunUntilIdle();
EXPECT_EQ("http://a.com/",
eviction_bucket()->storage_key.origin().GetURL().spec());
- DeleteBucketFromDatabase(eviction_bucket()->id);
- GetEvictionBucket(kTemp);
- task_environment_.RunUntilIdle();
- EXPECT_EQ("https://a.com/",
- eviction_bucket()->storage_key.origin().GetURL().spec());
-
- DeleteBucketFromDatabase(eviction_bucket()->id);
+ DeleteBucketData(*eviction_bucket(), AllQuotaClientTypes());
GetEvictionBucket(kTemp);
task_environment_.RunUntilIdle();
EXPECT_EQ("http://c.com/",
@@ -2589,18 +2478,19 @@ TEST_F(QuotaManagerImplTest, GetLRUBucket) {
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();
+ auto bucket =
+ 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();
+ bucket = 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();
+ bucket = CreateBucketForTesting(storage_key_c, kDefaultBucketName, kPerm);
+ ASSERT_TRUE(bucket.ok());
+ BucketInfo bucket_c = bucket.value();
NotifyBucketAccessed(bucket_a.id);
NotifyBucketAccessed(bucket_b.id);
@@ -2626,19 +2516,20 @@ TEST_F(QuotaManagerImplTest, GetLRUBucket) {
}
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},
+ static const ClientBucketData kData[] = {
+ {"http://a.com/", kDefaultBucketName, kTemp, 0},
+ {"http://a.com:1/", kDefaultBucketName, kTemp, 0},
+ {"https://a.com/", kDefaultBucketName, kTemp, 0},
+ {"http://b.com/", kDefaultBucketName, kPerm, 0}, // persistent
+ {"http://c.com/", kDefaultBucketName, kTemp, 0},
};
MockQuotaClient* client =
- CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ RegisterClientBucketData(client, kData);
- GetBucketsModifiedBetween(kTemp, base::Time(), base::Time::Max());
- EXPECT_TRUE(modified_buckets().empty());
- EXPECT_EQ(modified_buckets_type(), kTemp);
+ auto buckets =
+ GetBucketsModifiedBetween(kTemp, base::Time(), base::Time::Max());
+ EXPECT_EQ(4U, buckets.size());
base::Time time1 = client->IncrementMockTime();
client->ModifyStorageKeyAndNotify(ToStorageKey("http://a.com/"), kTemp, 10);
@@ -2649,46 +2540,49 @@ TEST_F(QuotaManagerImplTest, GetBucketsModifiedBetween) {
client->ModifyStorageKeyAndNotify(ToStorageKey("http://c.com/"), kTemp, 10);
base::Time time3 = client->IncrementMockTime();
- GetBucketsModifiedBetween(kTemp, time1, base::Time::Max());
- EXPECT_EQ(modified_buckets_type(), kTemp);
- EXPECT_THAT(modified_buckets(),
- testing::UnorderedElementsAre(
- testing::Field(&BucketLocator::storage_key,
- ToStorageKey("http://a.com")),
- testing::Field(&BucketLocator::storage_key,
- ToStorageKey("http://a.com:1")),
- testing::Field(&BucketLocator::storage_key,
- ToStorageKey("https://a.com")),
- testing::Field(&BucketLocator::storage_key,
- ToStorageKey("http://c.com"))));
-
- GetBucketsModifiedBetween(kTemp, time2, base::Time::Max());
- EXPECT_EQ(2U, modified_buckets().size());
-
- GetBucketsModifiedBetween(kTemp, time3, base::Time::Max());
- EXPECT_TRUE(modified_buckets().empty());
- EXPECT_EQ(modified_buckets_type(), kTemp);
+ // Database call to ensure modification calls have completed.
+ GetBucket(ToStorageKey("http://a.com"), kDefaultBucketName, kTemp);
+
+ buckets = GetBucketsModifiedBetween(kTemp, time1, base::Time::Max());
+ EXPECT_THAT(buckets, testing::UnorderedElementsAre(
+ testing::Field(&BucketLocator::storage_key,
+ ToStorageKey("http://a.com")),
+ testing::Field(&BucketLocator::storage_key,
+ ToStorageKey("http://a.com:1")),
+ testing::Field(&BucketLocator::storage_key,
+ ToStorageKey("https://a.com")),
+ testing::Field(&BucketLocator::storage_key,
+ ToStorageKey("http://c.com"))));
+
+ buckets = GetBucketsModifiedBetween(kTemp, time2, base::Time::Max());
+ EXPECT_EQ(2U, buckets.size());
+
+ buckets = GetBucketsModifiedBetween(kTemp, time3, base::Time::Max());
+ EXPECT_TRUE(buckets.empty());
client->ModifyStorageKeyAndNotify(ToStorageKey("http://a.com/"), kTemp, 10);
- GetBucketsModifiedBetween(kTemp, time3, base::Time::Max());
- EXPECT_THAT(modified_buckets(),
+ // Database call to ensure modification calls have completed.
+ GetBucket(ToStorageKey("http://a.com"), kDefaultBucketName, kTemp);
+
+ buckets = GetBucketsModifiedBetween(kTemp, time3, base::Time::Max());
+ EXPECT_THAT(buckets,
testing::UnorderedElementsAre(testing::Field(
&BucketLocator::storage_key, ToStorageKey("http://a.com/"))));
- EXPECT_EQ(modified_buckets_type(), kTemp);
}
TEST_F(QuotaManagerImplTest, GetBucketsModifiedBetweenWithDatabaseError) {
+ disable_database_bootstrap(true);
OpenDatabase();
// Disable quota database for database error behavior.
disable_quota_database(true);
- GetBucketsModifiedBetween(kTemp, base::Time(), base::Time::Max());
+ auto buckets =
+ GetBucketsModifiedBetween(kTemp, base::Time(), base::Time::Max());
// Return empty set when error is encountered.
- EXPECT_TRUE(modified_buckets().empty());
- EXPECT_EQ(modified_buckets_type(), kTemp);
+ EXPECT_TRUE(buckets.empty());
}
TEST_F(QuotaManagerImplTest, DumpQuotaTable) {
@@ -2697,11 +2591,9 @@ TEST_F(QuotaManagerImplTest, DumpQuotaTable) {
SetPersistentHostQuota("example3.com", 300);
task_environment_.RunUntilIdle();
- DumpQuotaTable();
- task_environment_.RunUntilIdle();
-
+ const QuotaTableEntries& entries = DumpQuotaTable();
EXPECT_THAT(
- quota_entries(),
+ entries,
testing::UnorderedElementsAre(
QuotaTableEntry{.host = "example1.com", .type = kPerm, .quota = 1},
QuotaTableEntry{.host = "example2.com", .type = kPerm, .quota = 20},
@@ -2710,216 +2602,127 @@ TEST_F(QuotaManagerImplTest, DumpQuotaTable) {
}
TEST_F(QuotaManagerImplTest, DumpBucketTable) {
- 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();
+ const StorageKey kStorageKey = ToStorageKey("http://example.com/");
+ CreateBucketForTesting(kStorageKey, kDefaultBucketName, kTemp);
+ CreateBucketForTesting(kStorageKey, kDefaultBucketName, kPerm);
- DumpBucketTable();
+ quota_manager_impl()->NotifyStorageAccessed(kStorageKey, kTemp,
+ base::Time::Now());
+ quota_manager_impl()->NotifyStorageAccessed(kStorageKey, kPerm,
+ base::Time::Now());
+ quota_manager_impl()->NotifyStorageAccessed(kStorageKey, kPerm,
+ base::Time::Now());
task_environment_.RunUntilIdle();
- EXPECT_THAT(bucket_entries(),
- testing::UnorderedElementsAre(
- MatchesBucketTableEntry(ToStorageKey("http://example.com/"),
- kTemp, 1),
- MatchesBucketTableEntry(ToStorageKey("http://example.com/"),
- kPerm, 2)));
+ const BucketTableEntries& entries = DumpBucketTable();
+ EXPECT_THAT(entries, testing::UnorderedElementsAre(
+ MatchesBucketTableEntry(kStorageKey, kTemp, 1),
+ MatchesBucketTableEntry(kStorageKey, kPerm, 2)));
}
TEST_F(QuotaManagerImplTest, QuotaForEmptyHost) {
- GetPersistentHostQuota(std::string());
- task_environment_.RunUntilIdle();
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(0, quota());
+ EXPECT_EQ(GetPersistentHostQuota(std::string()), 0);
- SetPersistentHostQuota(std::string(), 10);
- task_environment_.RunUntilIdle();
- EXPECT_EQ(QuotaStatusCode::kErrorNotSupported, status());
+ base::test::TestFuture<QuotaStatusCode, int64_t> future;
+ quota_manager_impl()->SetPersistentHostQuota(std::string(), 10,
+ future.GetCallback());
+ EXPECT_EQ(future.Get<0>(), QuotaStatusCode::kErrorNotSupported);
}
TEST_F(QuotaManagerImplTest, DeleteSpecificClientTypeSingleBucket) {
- static const MockStorageKeyData kData1[] = {
- {"http://foo.com/", kTemp, 1},
+ static const ClientBucketData kData1[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 1},
};
- static const MockStorageKeyData kData2[] = {
- {"http://foo.com/", kTemp, 2},
+ static const ClientBucketData kData2[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 2},
};
- static const MockStorageKeyData kData3[] = {
- {"http://foo.com/", kTemp, 4},
+ static const ClientBucketData kData3[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 4},
};
- static const MockStorageKeyData kData4[] = {
- {"http://foo.com/", kTemp, 8},
+ static const ClientBucketData kData4[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 8},
};
- CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary});
- CreateAndRegisterClient(kData2, QuotaClientType::kServiceWorkerCache,
- {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();
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp});
+ MockQuotaClient* sw_client =
+ CreateAndRegisterClient(QuotaClientType::kServiceWorkerCache, {kTemp});
+ MockQuotaClient* db_client =
+ CreateAndRegisterClient(QuotaClientType::kDatabase, {kTemp});
+ MockQuotaClient* idb_client =
+ CreateAndRegisterClient(QuotaClientType::kIndexedDatabase, {kTemp});
+ RegisterClientBucketData(fs_client, kData1);
+ RegisterClientBucketData(sw_client, kData2);
+ RegisterClientBucketData(db_client, kData3);
+ RegisterClientBucketData(idb_client, kData4);
+
+ auto foo_bucket =
+ GetBucket(ToStorageKey("http://foo.com"), kDefaultBucketName, kTemp);
+ ASSERT_TRUE(foo_bucket.ok());
GetHostUsageWithBreakdown("foo.com", kTemp);
const int64_t predelete_foo_tmp = usage();
- DeleteBucketData(foo_bucket.ToBucketLocator(),
+ DeleteBucketData(foo_bucket->ToBucketLocator(),
{QuotaClientType::kFileSystem});
- task_environment_.RunUntilIdle();
GetHostUsageWithBreakdown("foo.com", kTemp);
EXPECT_EQ(predelete_foo_tmp - 1, usage());
- DeleteBucketData(foo_bucket.ToBucketLocator(),
+ DeleteBucketData(foo_bucket->ToBucketLocator(),
{QuotaClientType::kServiceWorkerCache});
- task_environment_.RunUntilIdle();
GetHostUsageWithBreakdown("foo.com", kTemp);
EXPECT_EQ(predelete_foo_tmp - 2 - 1, usage());
- DeleteBucketData(foo_bucket.ToBucketLocator(), {QuotaClientType::kDatabase});
- task_environment_.RunUntilIdle();
+ DeleteBucketData(foo_bucket->ToBucketLocator(), {QuotaClientType::kDatabase});
GetHostUsageWithBreakdown("foo.com", kTemp);
EXPECT_EQ(predelete_foo_tmp - 4 - 2 - 1, usage());
- DeleteBucketData(foo_bucket.ToBucketLocator(),
+ DeleteBucketData(foo_bucket->ToBucketLocator(),
{QuotaClientType::kIndexedDatabase});
- task_environment_.RunUntilIdle();
- GetHostUsageWithBreakdown("foo.com", kTemp);
- EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage());
-}
-
-TEST_F(QuotaManagerImplTest, DeleteSpecificClientTypeSingleHost) {
- static const MockStorageKeyData kData1[] = {
- {"http://foo.com:1111/", kTemp, 1},
- };
- static const MockStorageKeyData kData2[] = {
- {"http://foo.com:2222/", kTemp, 2},
- };
- static const MockStorageKeyData kData3[] = {
- {"http://foo.com:3333/", kTemp, 4},
- };
- static const MockStorageKeyData kData4[] = {
- {"http://foo.com:4444/", kTemp, 8},
- };
- CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary});
- CreateAndRegisterClient(kData2, QuotaClientType::kServiceWorkerCache,
- {blink::mojom::StorageType::kTemporary});
- CreateAndRegisterClient(kData3, QuotaClientType::kDatabase,
- {blink::mojom::StorageType::kTemporary});
- CreateAndRegisterClient(kData4, QuotaClientType::kIndexedDatabase,
- {blink::mojom::StorageType::kTemporary});
-
- GetHostUsageWithBreakdown("foo.com", kTemp);
- const int64_t predelete_foo_tmp = usage();
-
- DeleteHostData("foo.com", kTemp, {QuotaClientType::kFileSystem});
- task_environment_.RunUntilIdle();
- GetHostUsageWithBreakdown("foo.com", kTemp);
- EXPECT_EQ(predelete_foo_tmp - 1, usage());
-
- DeleteHostData("foo.com", kTemp, {QuotaClientType::kServiceWorkerCache});
- task_environment_.RunUntilIdle();
- GetHostUsageWithBreakdown("foo.com", kTemp);
- EXPECT_EQ(predelete_foo_tmp - 2 - 1, usage());
-
- DeleteHostData("foo.com", kTemp, {QuotaClientType::kDatabase});
- task_environment_.RunUntilIdle();
- GetHostUsageWithBreakdown("foo.com", kTemp);
- EXPECT_EQ(predelete_foo_tmp - 4 - 2 - 1, usage());
-
- DeleteHostData("foo.com", kTemp, {QuotaClientType::kIndexedDatabase});
- task_environment_.RunUntilIdle();
GetHostUsageWithBreakdown("foo.com", kTemp);
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 ClientBucketData kData1[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 1},
};
- static const MockStorageKeyData kData2[] = {
- {"http://foo.com/", kTemp, 2},
+ static const ClientBucketData kData2[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 2},
};
- static const MockStorageKeyData kData3[] = {
- {"http://foo.com/", kTemp, 4},
+ static const ClientBucketData kData3[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 4},
};
- static const MockStorageKeyData kData4[] = {
- {"http://foo.com/", kTemp, 8},
+ static const ClientBucketData kData4[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 8},
};
- CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary});
- CreateAndRegisterClient(kData2, QuotaClientType::kServiceWorkerCache,
- {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();
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp});
+ MockQuotaClient* sw_client =
+ CreateAndRegisterClient(QuotaClientType::kServiceWorkerCache, {kTemp});
+ MockQuotaClient* db_client =
+ CreateAndRegisterClient(QuotaClientType::kDatabase, {kTemp});
+ MockQuotaClient* idb_client =
+ CreateAndRegisterClient(QuotaClientType::kIndexedDatabase, {kTemp});
+ RegisterClientBucketData(fs_client, kData1);
+ RegisterClientBucketData(sw_client, kData2);
+ RegisterClientBucketData(db_client, kData3);
+ RegisterClientBucketData(idb_client, kData4);
+
+ auto foo_bucket =
+ GetBucket(ToStorageKey("http://foo.com/"), kDefaultBucketName, kTemp);
+ ASSERT_TRUE(foo_bucket.ok());
GetHostUsageWithBreakdown("foo.com", kTemp);
const int64_t predelete_foo_tmp = usage();
- DeleteBucketData(foo_bucket.ToBucketLocator(),
+ DeleteBucketData(foo_bucket->ToBucketLocator(),
{QuotaClientType::kFileSystem, QuotaClientType::kDatabase});
- task_environment_.RunUntilIdle();
GetHostUsageWithBreakdown("foo.com", kTemp);
EXPECT_EQ(predelete_foo_tmp - 4 - 1, usage());
- DeleteBucketData(foo_bucket.ToBucketLocator(),
+ DeleteBucketData(foo_bucket->ToBucketLocator(),
{QuotaClientType::kServiceWorkerCache,
QuotaClientType::kIndexedDatabase});
- task_environment_.RunUntilIdle();
- GetHostUsageWithBreakdown("foo.com", kTemp);
- EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage());
-}
-
-TEST_F(QuotaManagerImplTest, DeleteMultipleClientTypesSingleHost) {
- static const MockStorageKeyData kData1[] = {
- {"http://foo.com:1111/", kTemp, 1},
- };
- static const MockStorageKeyData kData2[] = {
- {"http://foo.com:2222/", kTemp, 2},
- };
- static const MockStorageKeyData kData3[] = {
- {"http://foo.com:3333/", kTemp, 4},
- };
- static const MockStorageKeyData kData4[] = {
- {"http://foo.com:4444/", kTemp, 8},
- };
- CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary});
- CreateAndRegisterClient(kData2, QuotaClientType::kServiceWorkerCache,
- {blink::mojom::StorageType::kTemporary});
- CreateAndRegisterClient(kData3, QuotaClientType::kDatabase,
- {blink::mojom::StorageType::kTemporary});
- CreateAndRegisterClient(kData4, QuotaClientType::kIndexedDatabase,
- {blink::mojom::StorageType::kTemporary});
-
- GetHostUsageWithBreakdown("foo.com", kTemp);
- const int64_t predelete_foo_tmp = usage();
-
- DeleteHostData(
- "foo.com", kTemp,
- {QuotaClientType::kFileSystem, QuotaClientType::kServiceWorkerCache});
- task_environment_.RunUntilIdle();
- GetHostUsageWithBreakdown("foo.com", kTemp);
- EXPECT_EQ(predelete_foo_tmp - 2 - 1, usage());
-
- DeleteHostData(
- "foo.com", kTemp,
- {QuotaClientType::kDatabase, QuotaClientType::kIndexedDatabase});
- task_environment_.RunUntilIdle();
GetHostUsageWithBreakdown("foo.com", kTemp);
EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage());
}
@@ -2927,47 +2730,47 @@ TEST_F(QuotaManagerImplTest, DeleteMultipleClientTypesSingleHost) {
TEST_F(QuotaManagerImplTest, GetUsageAndQuota_Incognito) {
ResetQuotaManagerImpl(true);
- static const MockStorageKeyData kData[] = {
- {"http://foo.com/", kTemp, 10},
- {"http://foo.com/", kPerm, 80},
+ static const ClientBucketData kData[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 10},
+ {"http://foo.com/", kDefaultBucketName, kPerm, 80},
};
- CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ MockQuotaClient* fs_client =
+ CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+ RegisterClientBucketData(fs_client, kData);
// Query global usage to warmup the usage tracker caching.
GetGlobalUsage(kTemp);
GetGlobalUsage(kPerm);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(80, usage());
- EXPECT_EQ(0, quota());
+ auto result =
+ GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 80);
+ EXPECT_EQ(result.quota, 0);
const int kPoolSize = 1000;
const int kPerHostQuota = kPoolSize / 5;
SetQuotaSettings(kPoolSize, kPerHostQuota, INT64_C(0));
- GetStorageCapacity();
- task_environment_.RunUntilIdle();
- EXPECT_EQ(kPoolSize, total_space());
- EXPECT_EQ(kPoolSize - 80 - 10, available_space());
+ auto storage_capacity = GetStorageCapacity();
+ EXPECT_EQ(storage_capacity.total_space, kPoolSize);
+ EXPECT_EQ(storage_capacity.available_space, kPoolSize - 80 - 10);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(10, usage());
- EXPECT_LE(kPerHostQuota, quota());
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 10);
+ EXPECT_GE(result.quota, kPerHostQuota);
mock_special_storage_policy()->AddUnlimited(GURL("http://foo.com/"));
- GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(80, usage());
- EXPECT_EQ(available_space() + usage(), quota());
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 80);
+ EXPECT_EQ(result.quota, storage_capacity.available_space + result.usage);
- GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(10, usage());
- EXPECT_EQ(available_space() + usage(), quota());
+ result = GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 10);
+ EXPECT_EQ(result.quota, storage_capacity.available_space + result.usage);
}
TEST_F(QuotaManagerImplTest, GetUsageAndQuota_SessionOnly) {
@@ -2975,12 +2778,12 @@ TEST_F(QuotaManagerImplTest, GetUsageAndQuota_SessionOnly) {
mock_special_storage_policy()->AddSessionOnly(
kEpheremalStorageKey.origin().GetURL());
- GetUsageAndQuotaForWebApps(kEpheremalStorageKey, kTemp);
+ auto result = GetUsageAndQuotaForWebApps(kEpheremalStorageKey, kTemp);
EXPECT_EQ(quota_manager_impl()->settings().session_only_per_host_quota,
- quota());
+ result.quota);
- GetUsageAndQuotaForWebApps(kEpheremalStorageKey, kPerm);
- EXPECT_EQ(0, quota());
+ result = GetUsageAndQuotaForWebApps(kEpheremalStorageKey, kPerm);
+ EXPECT_EQ(0, result.quota);
}
TEST_F(QuotaManagerImplTest, MaybeRunStoragePressureCallback) {
@@ -3011,10 +2814,10 @@ TEST_F(QuotaManagerImplTest, OverrideQuotaForStorageKey) {
base::BindLambdaForTesting([&]() { run_loop.Quit(); }));
run_loop.Run();
- GetUsageAndQuotaForWebApps(storage_key, kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(0, usage());
- EXPECT_EQ(5000, quota());
+ auto result = GetUsageAndQuotaForWebApps(storage_key, kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.usage, 0);
+ EXPECT_EQ(result.quota, 5000);
}
TEST_F(QuotaManagerImplTest, OverrideQuotaForStorageKey_Disable) {
@@ -3028,9 +2831,9 @@ TEST_F(QuotaManagerImplTest, OverrideQuotaForStorageKey_Disable) {
base::BindLambdaForTesting([&]() { run_loop1.Quit(); }));
run_loop1.Run();
- GetUsageAndQuotaForWebApps(storage_key, kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(5000, quota());
+ auto result = GetUsageAndQuotaForWebApps(storage_key, kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.quota, 5000);
base::RunLoop run_loop2;
handle2->OverrideQuotaForStorageKey(
@@ -3038,9 +2841,9 @@ TEST_F(QuotaManagerImplTest, OverrideQuotaForStorageKey_Disable) {
base::BindLambdaForTesting([&]() { run_loop2.Quit(); }));
run_loop2.Run();
- GetUsageAndQuotaForWebApps(storage_key, kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(9000, quota());
+ result = GetUsageAndQuotaForWebApps(storage_key, kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.quota, 9000);
base::RunLoop run_loop3;
handle2->OverrideQuotaForStorageKey(
@@ -3048,9 +2851,9 @@ TEST_F(QuotaManagerImplTest, OverrideQuotaForStorageKey_Disable) {
base::BindLambdaForTesting([&]() { run_loop3.Quit(); }));
run_loop3.Run();
- GetUsageAndQuotaForWebApps(storage_key, kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(kDefaultPerHostQuota, quota());
+ result = GetUsageAndQuotaForWebApps(storage_key, kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.quota, kDefaultPerHostQuota);
}
TEST_F(QuotaManagerImplTest, WithdrawQuotaOverride) {
@@ -3064,9 +2867,9 @@ TEST_F(QuotaManagerImplTest, WithdrawQuotaOverride) {
base::BindLambdaForTesting([&]() { run_loop1.Quit(); }));
run_loop1.Run();
- GetUsageAndQuotaForWebApps(storage_key, kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(5000, quota());
+ auto result = GetUsageAndQuotaForWebApps(storage_key, kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.quota, 5000);
base::RunLoop run_loop2;
handle1->OverrideQuotaForStorageKey(
@@ -3074,22 +2877,22 @@ TEST_F(QuotaManagerImplTest, WithdrawQuotaOverride) {
base::BindLambdaForTesting([&]() { run_loop2.Quit(); }));
run_loop2.Run();
- GetUsageAndQuotaForWebApps(storage_key, kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(8000, quota());
+ result = GetUsageAndQuotaForWebApps(storage_key, kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.quota, 8000);
// Quota should remain overridden if only one of the two handles withdraws
// it's overrides
handle2.reset();
- GetUsageAndQuotaForWebApps(storage_key, kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(8000, quota());
+ result = GetUsageAndQuotaForWebApps(storage_key, kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.quota, 8000);
handle1.reset();
task_environment_.RunUntilIdle();
- GetUsageAndQuotaForWebApps(storage_key, kTemp);
- EXPECT_EQ(QuotaStatusCode::kOk, status());
- EXPECT_EQ(kDefaultPerHostQuota, quota());
+ result = GetUsageAndQuotaForWebApps(storage_key, kTemp);
+ EXPECT_EQ(result.status, QuotaStatusCode::kOk);
+ EXPECT_EQ(result.quota, kDefaultPerHostQuota);
}
TEST_F(QuotaManagerImplTest, QuotaChangeEvent_LargePartitionPressure) {
@@ -3104,7 +2907,6 @@ TEST_F(QuotaManagerImplTest, QuotaChangeEvent_LargePartitionPressure) {
return std::make_tuple(total, available);
});
GetStorageCapacity();
- task_environment_.RunUntilIdle();
EXPECT_FALSE(quota_change_dispatched);
SetGetVolumeInfoFn([](const base::FilePath&) -> std::tuple<int64_t, int64_t> {
@@ -3113,7 +2915,6 @@ TEST_F(QuotaManagerImplTest, QuotaChangeEvent_LargePartitionPressure) {
return std::make_tuple(total, available);
});
GetStorageCapacity();
- task_environment_.RunUntilIdle();
EXPECT_TRUE(quota_change_dispatched);
}
@@ -3129,7 +2930,6 @@ TEST_F(QuotaManagerImplTest, QuotaChangeEvent_SmallPartitionPressure) {
return std::make_tuple(total, available);
});
GetStorageCapacity();
- task_environment_.RunUntilIdle();
EXPECT_FALSE(quota_change_dispatched);
SetGetVolumeInfoFn([](const base::FilePath&) -> std::tuple<int64_t, int64_t> {
@@ -3141,8 +2941,83 @@ TEST_F(QuotaManagerImplTest, QuotaChangeEvent_SmallPartitionPressure) {
return std::make_tuple(total, available);
});
GetStorageCapacity();
- task_environment_.RunUntilIdle();
EXPECT_TRUE(quota_change_dispatched);
}
+TEST_F(QuotaManagerImplTest, DeleteBucketData_QuotaManagerDeletedImmediately) {
+ static const ClientBucketData kData[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 1},
+ };
+ MockQuotaClient* client =
+ CreateAndRegisterClient(QuotaClientType::kIndexedDatabase, {kTemp});
+ RegisterClientBucketData(client, kData);
+
+ QuotaErrorOr<BucketInfo> bucket =
+ GetBucket(ToStorageKey("http://foo.com/"), kDefaultBucketName, kTemp);
+ ASSERT_TRUE(bucket.ok());
+
+ base::test::TestFuture<QuotaStatusCode> delete_bucket_data_future;
+ quota_manager_impl_->DeleteBucketData(
+ bucket->ToBucketLocator(), {QuotaClientType::kIndexedDatabase},
+ delete_bucket_data_future.GetCallback());
+ quota_manager_impl_.reset();
+ EXPECT_EQ(QuotaStatusCode::kErrorAbort, delete_bucket_data_future.Get());
+}
+
+TEST_F(QuotaManagerImplTest, DeleteBucketData_CallbackDeletesQuotaManager) {
+ static const ClientBucketData kData[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 1},
+ };
+ MockQuotaClient* client =
+ CreateAndRegisterClient(QuotaClientType::kIndexedDatabase, {kTemp});
+ RegisterClientBucketData(client, kData);
+
+ QuotaErrorOr<BucketInfo> bucket =
+ GetBucket(ToStorageKey("http://foo.com/"), kDefaultBucketName, kTemp);
+ ASSERT_TRUE(bucket.ok());
+
+ base::RunLoop run_loop;
+ QuotaStatusCode delete_bucket_data_result = QuotaStatusCode::kUnknown;
+ quota_manager_impl_->DeleteBucketData(
+ bucket->ToBucketLocator(), {QuotaClientType::kIndexedDatabase},
+ base::BindLambdaForTesting([&](QuotaStatusCode status_code) {
+ quota_manager_impl_.reset();
+ delete_bucket_data_result = status_code;
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+
+ EXPECT_EQ(QuotaStatusCode::kOk, delete_bucket_data_result);
+}
+
+TEST_F(QuotaManagerImplTest, DeleteHostData_CallbackDeletesQuotaManager) {
+ static const ClientBucketData kData[] = {
+ {"http://foo.com/", kDefaultBucketName, kTemp, 1},
+ };
+ MockQuotaClient* client =
+ CreateAndRegisterClient(QuotaClientType::kIndexedDatabase, {kTemp});
+ RegisterClientBucketData(client, kData);
+
+ QuotaErrorOr<BucketInfo> bucket =
+ GetBucket(ToStorageKey("http://foo.com/"), kDefaultBucketName, kTemp);
+ ASSERT_TRUE(bucket.ok());
+
+ auto status = DeleteBucketData(bucket->ToBucketLocator(),
+ {QuotaClientType::kFileSystem});
+ EXPECT_EQ(status, QuotaStatusCode::kOk);
+
+ base::RunLoop run_loop;
+ QuotaStatusCode delete_host_data_result = QuotaStatusCode::kUnknown;
+ quota_manager_impl_->DeleteHostData(
+ "foo.com", kTemp,
+ base::BindLambdaForTesting([&](QuotaStatusCode status_code) {
+ quota_manager_impl_.reset();
+ delete_host_data_result = status_code;
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+
+ EXPECT_EQ(QuotaStatusCode::kOk, delete_host_data_result);
+}
+
} // namespace storage
diff --git a/chromium/storage/browser/quota/quota_temporary_storage_evictor.cc b/chromium/storage/browser/quota/quota_temporary_storage_evictor.cc
index 38faa8a0da4..8962a7d0c96 100644
--- a/chromium/storage/browser/quota/quota_temporary_storage_evictor.cc
+++ b/chromium/storage/browser/quota/quota_temporary_storage_evictor.cc
@@ -196,7 +196,7 @@ void QuotaTemporaryStorageEvictor::OnGotEvictionRoundInfo(
// TODO(michaeln): if the reason for eviction is low physical disk space,
// make 'unlimited' storage keys subject to eviction too.
quota_eviction_handler_->GetEvictionBucket(
- blink::mojom::StorageType::kTemporary, settings.pool_size,
+ blink::mojom::StorageType::kTemporary,
base::BindOnce(&QuotaTemporaryStorageEvictor::OnGotEvictionBucket,
weak_factory_.GetWeakPtr()));
return;
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 ab8e9fc940f..9abddf3253d 100644
--- a/chromium/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc
+++ b/chromium/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc
@@ -63,7 +63,6 @@ class MockQuotaEvictionHandler : public QuotaEvictionHandler {
}
void GetEvictionBucket(StorageType type,
- int64_t global_quota,
GetBucketCallback callback) override {
if (bucket_order_.empty()) {
std::move(callback).Run(absl::nullopt);
diff --git a/chromium/storage/browser/quota/storage_policy_observer.cc b/chromium/storage/browser/quota/storage_policy_observer.cc
index 5fe45ed8ffe..884ade794c5 100644
--- a/chromium/storage/browser/quota/storage_policy_observer.cc
+++ b/chromium/storage/browser/quota/storage_policy_observer.cc
@@ -6,7 +6,9 @@
#include <utility>
+#include "base/feature_list.h"
#include "base/task/post_task.h"
+#include "storage/browser/quota/quota_features.h"
#include "url/origin.h"
namespace storage {
@@ -69,25 +71,23 @@ StoragePolicyObserver::~StoragePolicyObserver() {
void StoragePolicyObserver::StartTrackingOrigin(const url::Origin& origin) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- // If the origin exists, emplace fails, and its state is unchanged.
- const GURL origin_url = GURL(origin.Serialize());
- origin_state_.emplace(origin_url, OriginState());
-
- OnPolicyChanged();
+ StartTrackingOrigins({origin});
}
void StoragePolicyObserver::StartTrackingOrigins(
const std::vector<url::Origin>& origins) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ std::vector<std::pair<const GURL, OriginState>*> updates;
for (const auto& origin : origins) {
// If the origin exists, emplace fails, and its state is unchanged.
GURL origin_url = GURL(origin.Serialize());
- origin_state_.emplace(std::move(origin_url), OriginState());
+ auto& entry =
+ *origin_state_.emplace(std::move(origin_url), OriginState()).first;
+ updates.push_back(&entry);
}
- OnPolicyChanged();
+ OnPolicyChangedForOrigins(updates);
}
void StoragePolicyObserver::StopTrackingOrigin(const url::Origin& origin) {
@@ -100,17 +100,8 @@ void StoragePolicyObserver::OnPolicyChanged() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::vector<storage::mojom::StoragePolicyUpdatePtr> policy_updates;
- for (auto& entry : origin_state_) {
- const GURL& origin = entry.first;
- OriginState& state = entry.second;
- state.should_purge_on_shutdown = ShouldPurgeOnShutdown(origin);
-
- if (state.should_purge_on_shutdown != state.will_purge_on_shutdown) {
- state.will_purge_on_shutdown = state.should_purge_on_shutdown;
- policy_updates.emplace_back(storage::mojom::StoragePolicyUpdate::New(
- url::Origin::Create(origin), state.should_purge_on_shutdown));
- }
- }
+ for (auto& entry : origin_state_)
+ AddPolicyUpdate(&entry, &policy_updates);
if (policy_updates.empty())
return;
callback_.Run(std::move(policy_updates));
@@ -133,4 +124,34 @@ bool StoragePolicyObserver::ShouldPurgeOnShutdown(const GURL& origin) {
return true;
}
+void StoragePolicyObserver::OnPolicyChangedForOrigins(
+ const std::vector<std::pair<const GURL, OriginState>*>& updated_origins) {
+ if (!base::FeatureList::IsEnabled(
+ features::kOnlySendStoragePolicyUpdatesForModifiedOrigins)) {
+ OnPolicyChanged();
+ return;
+ }
+
+ std::vector<storage::mojom::StoragePolicyUpdatePtr> policy_updates;
+ for (auto* entry : updated_origins)
+ AddPolicyUpdate(entry, &policy_updates);
+ if (policy_updates.empty())
+ return;
+ callback_.Run(std::move(policy_updates));
+}
+
+void StoragePolicyObserver::AddPolicyUpdate(
+ std::pair<const GURL, OriginState>* entry,
+ std::vector<storage::mojom::StoragePolicyUpdatePtr>* policy_updates) {
+ const GURL& origin = entry->first;
+ OriginState& state = entry->second;
+ state.should_purge_on_shutdown = ShouldPurgeOnShutdown(origin);
+
+ if (state.should_purge_on_shutdown != state.will_purge_on_shutdown) {
+ state.will_purge_on_shutdown = state.should_purge_on_shutdown;
+ policy_updates->emplace_back(storage::mojom::StoragePolicyUpdate::New(
+ url::Origin::Create(origin), state.should_purge_on_shutdown));
+ }
+}
+
} // namespace storage
diff --git a/chromium/storage/browser/quota/storage_policy_observer.h b/chromium/storage/browser/quota/storage_policy_observer.h
index 01990226bb6..a9a1f01eb97 100644
--- a/chromium/storage/browser/quota/storage_policy_observer.h
+++ b/chromium/storage/browser/quota/storage_policy_observer.h
@@ -67,6 +67,13 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) StoragePolicyObserver {
// Indicates the last value for `purge_on_shutdown` that was communicated.
bool will_purge_on_shutdown = false;
};
+
+ void OnPolicyChangedForOrigins(
+ const std::vector<std::pair<const GURL, OriginState>*>& updated_origins);
+ void AddPolicyUpdate(
+ std::pair<const GURL, OriginState>* entry,
+ std::vector<storage::mojom::StoragePolicyUpdatePtr>* policy_updates);
+
// NOTE: The GURL key is specifically an origin GURL.
// Special storage policy uses GURLs and not Origins, so it's simpler
// to store everything in GURL form.
diff --git a/chromium/storage/browser/quota/storage_policy_observer_unittest.cc b/chromium/storage/browser/quota/storage_policy_observer_unittest.cc
new file mode 100644
index 00000000000..8b879a5fb27
--- /dev/null
+++ b/chromium/storage/browser/quota/storage_policy_observer_unittest.cc
@@ -0,0 +1,92 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "storage/browser/quota/storage_policy_observer.h"
+
+#include "base/test/task_environment.h"
+#include "storage/browser/test/mock_special_storage_policy.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace storage {
+namespace {
+
+constexpr char kOrigin1[] = "http://origin1.com";
+constexpr char kOrigin2[] = "http://origin2.com";
+constexpr char kSessionOrigin1[] = "http://session-origin1.com";
+constexpr char kSessionOrigin2[] = "http://session-origin2.com";
+
+class StoragePolicyObserverTest : public testing::Test {
+ public:
+ StoragePolicyObserverTest()
+ : mock_policy_(base::MakeRefCounted<MockSpecialStoragePolicy>()),
+ observer_(std::make_unique<StoragePolicyObserver>(
+ base::BindRepeating(&StoragePolicyObserverTest::OnPolicyUpdates,
+ base::Unretained(this)),
+ task_environment_.GetMainThreadTaskRunner(),
+ mock_policy_)) {
+ mock_policy_->AddSessionOnly(GURL(kSessionOrigin1));
+ mock_policy_->AddSessionOnly(GURL(kSessionOrigin2));
+ // Make sure the IO thread observer is created.
+ task_environment_.RunUntilIdle();
+ }
+
+ ~StoragePolicyObserverTest() override {
+ observer_.reset();
+ // Make sure the IO thread observer is destroyed.
+ task_environment_.RunUntilIdle();
+ }
+
+ protected:
+ void OnPolicyUpdates(
+ std::vector<storage::mojom::StoragePolicyUpdatePtr> updates) {
+ ASSERT_TRUE(latest_updates_.empty());
+ latest_updates_ = std::move(updates);
+ }
+
+ std::vector<storage::mojom::StoragePolicyUpdatePtr> TakeLatestUpdates() {
+ return std::move(latest_updates_);
+ }
+
+ void ExpectUpdates(std::map<url::Origin, bool> expectations) {
+ auto updates = TakeLatestUpdates();
+ EXPECT_EQ(updates.size(), expectations.size());
+ for (const auto& update : updates) {
+ auto it = expectations.find(update->origin);
+ ASSERT_NE(it, expectations.end());
+ EXPECT_EQ(it->second, update->purge_on_shutdown);
+ }
+ }
+
+ base::test::TaskEnvironment task_environment_;
+ scoped_refptr<MockSpecialStoragePolicy> mock_policy_;
+ std::unique_ptr<StoragePolicyObserver> observer_;
+
+ private:
+ std::vector<storage::mojom::StoragePolicyUpdatePtr> latest_updates_;
+};
+
+TEST_F(StoragePolicyObserverTest, NonSessionOnlyOriginDoesNotCreateUpdate) {
+ observer_->StartTrackingOrigins({url::Origin::Create(GURL(kOrigin1)),
+ url::Origin::Create(GURL(kOrigin2))});
+ auto updates = TakeLatestUpdates();
+ EXPECT_TRUE(updates.empty());
+}
+
+TEST_F(StoragePolicyObserverTest, SessionOnlyOriginCreateUpdate) {
+ url::Origin origin1 = url::Origin::Create(GURL(kSessionOrigin1));
+ observer_->StartTrackingOrigin(origin1);
+ ExpectUpdates({{origin1, true}});
+
+ url::Origin origin2 = url::Origin::Create(GURL(kSessionOrigin2));
+ observer_->StartTrackingOrigin(origin2);
+ ExpectUpdates({{origin2, true}});
+
+ mock_policy_->RemoveSessionOnly(GURL(kSessionOrigin1));
+ mock_policy_->RemoveSessionOnly(GURL(kSessionOrigin2));
+ observer_->OnPolicyChanged();
+ ExpectUpdates({{origin1, false}, {origin2, false}});
+}
+
+} // namespace
+} // namespace storage
diff --git a/chromium/storage/browser/quota/usage_tracker.cc b/chromium/storage/browser/quota/usage_tracker.cc
index 87624191bd2..f6018b20d7d 100644
--- a/chromium/storage/browser/quota/usage_tracker.cc
+++ b/chromium/storage/browser/quota/usage_tracker.cc
@@ -11,6 +11,7 @@
#include "base/barrier_closure.h"
#include "base/bind.h"
+#include "components/services/storage/public/cpp/buckets/constants.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"
@@ -18,10 +19,6 @@
namespace storage {
struct UsageTracker::AccumulateInfo {
- AccumulateInfo() = default;
- ~AccumulateInfo() = default;
-
- size_t pending_clients = 0;
int64_t usage = 0;
int64_t unlimited_usage = 0;
blink::mojom::UsageBreakdownPtr usage_breakdown =
@@ -29,11 +26,12 @@ struct UsageTracker::AccumulateInfo {
};
UsageTracker::UsageTracker(
+ QuotaManagerImpl* quota_manager_impl,
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;
+ : quota_manager_impl_(quota_manager_impl), type_(type) {
+ DCHECK(quota_manager_impl_);
for (const auto& client_and_type : client_types) {
mojom::QuotaClient* client = client_and_type.first;
@@ -41,41 +39,22 @@ UsageTracker::UsageTracker(
client_tracker_map_[client_type].push_back(
std::make_unique<ClientUsageTracker>(this, client, type,
special_storage_policy));
- ++client_count;
}
- client_count_ = client_count;
}
UsageTracker::~UsageTracker() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
-void UsageTracker::GetGlobalUsage(GlobalUsageCallback callback) {
+void UsageTracker::GetGlobalUsage(UsageCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
global_usage_callbacks_.emplace_back(std::move(callback));
if (global_usage_callbacks_.size() > 1)
return;
- AccumulateInfo* info = new AccumulateInfo;
- // Calling GetGlobalUsage(accumulator) may synchronously
- // return if the usage is cached, which may in turn dispatch
- // the completion callback before we finish looping over
- // all clients (because info->pending_clients may reach 0
- // during the loop).
- // To avoid this, we add one more pending client as a sentinel
- // and fire the sentinel callback at the end.
- info->pending_clients = client_tracker_map_.size() + 1;
- auto accumulator =
- base::BindRepeating(&UsageTracker::AccumulateClientGlobalUsage,
- weak_factory_.GetWeakPtr(), base::Owned(info));
-
- for (const auto& client_type_and_trackers : client_tracker_map_) {
- for (const auto& client_tracker : client_type_and_trackers.second)
- client_tracker->GetGlobalUsage(accumulator);
- }
-
- // Fire the sentinel as we've now called GetGlobalUsage for all clients.
- accumulator.Run(0, 0);
+ quota_manager_impl_->GetBucketsForType(
+ type_, base::BindOnce(&UsageTracker::DidGetBucketsForType,
+ weak_factory_.GetWeakPtr()));
}
void UsageTracker::GetHostUsageWithBreakdown(
@@ -88,30 +67,30 @@ void UsageTracker::GetHostUsageWithBreakdown(
if (host_callbacks.size() > 1)
return;
- AccumulateInfo* info = new AccumulateInfo;
- // We use BarrierClosure here instead of manually counting pending_clients.
- base::RepeatingClosure barrier = base::BarrierClosure(
- client_tracker_map_.size(),
- base::BindOnce(&UsageTracker::FinallySendHostUsageWithBreakdown,
- weak_factory_.GetWeakPtr(), base::Owned(info), host));
+ quota_manager_impl_->GetBucketsForHost(
+ host, type_,
+ base::BindOnce(&UsageTracker::DidGetBucketsForHost,
+ weak_factory_.GetWeakPtr(), host));
+}
- for (const auto& client_type_and_trackers : client_tracker_map_) {
- for (const auto& client_tracker : client_type_and_trackers.second) {
- client_tracker->GetHostUsage(
- host, base::BindOnce(&UsageTracker::AccumulateClientHostUsage,
- weak_factory_.GetWeakPtr(), barrier, info, host,
- client_type_and_trackers.first));
- }
- }
+void UsageTracker::UpdateBucketUsageCache(QuotaClientType client_type,
+ const BucketLocator& bucket,
+ 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->UpdateBucketUsageCache(bucket, delta);
}
-void UsageTracker::UpdateUsageCache(QuotaClientType client_type,
- const blink::StorageKey& storage_key,
- int64_t delta) {
+void UsageTracker::DeleteBucketCache(QuotaClientType client_type,
+ const BucketLocator& bucket) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(client_tracker_map_.count(client_type));
+ DCHECK_EQ(bucket.type, type_);
+
for (const auto& client_tracker : client_tracker_map_[client_type])
- client_tracker->UpdateUsageCache(storage_key, delta);
+ client_tracker->DeleteBucketCache(bucket);
}
int64_t UsageTracker::GetCachedUsage() const {
@@ -154,20 +133,6 @@ std::map<blink::StorageKey, int64_t> UsageTracker::GetCachedStorageKeysUsage()
return storage_key_usage;
}
-std::set<blink::StorageKey> UsageTracker::GetCachedStorageKeys() const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- 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<blink::StorageKey> client_storage_keys =
- client_tracker->GetCachedStorageKeys();
- for (const auto& client_storage_key : client_storage_keys)
- storage_keys.insert(client_storage_key);
- }
- }
- return storage_keys;
-}
-
void UsageTracker::SetUsageCacheEnabled(QuotaClientType client_type,
const blink::StorageKey& storage_key,
bool enabled) {
@@ -177,75 +142,157 @@ void UsageTracker::SetUsageCacheEnabled(QuotaClientType client_type,
client_tracker->SetUsageCacheEnabled(storage_key, enabled);
}
-void UsageTracker::AccumulateClientGlobalUsage(AccumulateInfo* info,
- int64_t usage,
- int64_t unlimited_usage) {
- DCHECK_GT(info->pending_clients, 0U);
+void UsageTracker::DidGetBucketsForType(
+ QuotaErrorOr<std::set<BucketLocator>> result) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- info->usage += usage;
- info->unlimited_usage += unlimited_usage;
- if (--info->pending_clients)
+ auto info = std::make_unique<AccumulateInfo>();
+ if (!result.ok()) {
+ // Return with invalid values on error.
+ info->usage = -1;
+ info->unlimited_usage = -1;
+ FinallySendGlobalUsage(std::move(info));
return;
+ }
- // Defend against confusing inputs from clients.
- if (info->usage < 0)
- info->usage = 0;
+ const std::set<BucketLocator>& buckets = result.value();
+ if (buckets.empty()) {
+ FinallySendGlobalUsage(std::move(info));
+ return;
+ }
- // TODO(michaeln): The unlimited number is not trustworthy, it
- // can get out of whack when apps are installed or uninstalled.
- if (info->unlimited_usage > info->usage)
- info->unlimited_usage = info->usage;
- else if (info->unlimited_usage < 0)
- info->unlimited_usage = 0;
+ auto* info_ptr = info.get();
+ base::RepeatingClosure barrier = base::BarrierClosure(
+ client_tracker_map_.size(),
+ base::BindOnce(&UsageTracker::FinallySendGlobalUsage,
+ weak_factory_.GetWeakPtr(), std::move(info)));
- // Moving callbacks out of the original vector early handles the case where a
- // callback makes a new quota call.
- std::vector<GlobalUsageCallback> pending_callbacks;
- pending_callbacks.swap(global_usage_callbacks_);
- for (auto& callback : pending_callbacks)
- std::move(callback).Run(info->usage, info->unlimited_usage);
+ for (const auto& client_type_and_trackers : client_tracker_map_) {
+ for (const auto& client_tracker : client_type_and_trackers.second) {
+ client_tracker->GetBucketsUsage(
+ buckets,
+ // base::Unretained usage is safe here because BarrierClosure holds
+ // the std::unque_ptr that keeps AccumulateInfo alive, and the
+ // BarrierClosure will outlive all the AccumulateClientGlobalUsage
+ // closures.
+ base::BindOnce(&UsageTracker::AccumulateClientGlobalUsage,
+ weak_factory_.GetWeakPtr(), barrier,
+ base::Unretained(info_ptr)));
+ }
+ }
+}
+
+void UsageTracker::DidGetBucketsForHost(
+ const std::string& host,
+ QuotaErrorOr<std::set<BucketLocator>> result) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ auto info = std::make_unique<AccumulateInfo>();
+ if (!result.ok()) {
+ // Return with invalid values on error.
+ info->usage = -1;
+ info->unlimited_usage = -1;
+ FinallySendHostUsageWithBreakdown(std::move(info), host);
+ return;
+ }
+
+ const std::set<BucketLocator>& buckets = result.value();
+ if (buckets.empty()) {
+ FinallySendHostUsageWithBreakdown(std::move(info), host);
+ return;
+ }
+
+ auto* info_ptr = info.get();
+ base::RepeatingClosure barrier = base::BarrierClosure(
+ client_tracker_map_.size(),
+ base::BindOnce(&UsageTracker::FinallySendHostUsageWithBreakdown,
+ weak_factory_.GetWeakPtr(), std::move(info), host));
+
+ for (const auto& client_type_and_trackers : client_tracker_map_) {
+ for (const auto& client_tracker : client_type_and_trackers.second) {
+ client_tracker->GetBucketsUsage(
+ buckets,
+ // base::Unretained usage is safe here because BarrierClosure holds
+ // the std::unque_ptr that keeps AccumulateInfo alive, and the
+ // BarrierClosure will outlive all the AccumulateClientGlobalUsage
+ // closures.
+ base::BindOnce(&UsageTracker::AccumulateClientHostUsage,
+ weak_factory_.GetWeakPtr(), barrier,
+ base::Unretained(info_ptr), host,
+ client_type_and_trackers.first));
+ }
+ }
+}
+
+void UsageTracker::AccumulateClientGlobalUsage(
+ base::OnceClosure barrier_callback,
+ AccumulateInfo* info,
+ int64_t total_usage,
+ int64_t unlimited_usage) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_GE(unlimited_usage, 0);
+ DCHECK_GE(total_usage, unlimited_usage);
+
+ info->usage += total_usage;
+ info->unlimited_usage += unlimited_usage;
+
+ std::move(barrier_callback).Run();
}
-void UsageTracker::AccumulateClientHostUsage(base::OnceClosure callback,
+void UsageTracker::AccumulateClientHostUsage(base::OnceClosure barrier_callback,
AccumulateInfo* info,
const std::string& host,
QuotaClientType client,
- int64_t usage) {
+ int64_t total_usage,
+ int64_t unlimited_usage) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- info->usage += usage;
- // Defend against confusing inputs from clients.
- if (info->usage < 0)
- info->usage = 0;
+ DCHECK_GE(unlimited_usage, 0);
+ DCHECK_GE(total_usage, unlimited_usage);
+
+ info->usage += total_usage;
switch (client) {
case QuotaClientType::kFileSystem:
- info->usage_breakdown->fileSystem += usage;
+ info->usage_breakdown->fileSystem += total_usage;
break;
case QuotaClientType::kDatabase:
- info->usage_breakdown->webSql += usage;
+ info->usage_breakdown->webSql += total_usage;
break;
case QuotaClientType::kIndexedDatabase:
- info->usage_breakdown->indexedDatabase += usage;
+ info->usage_breakdown->indexedDatabase += total_usage;
break;
case QuotaClientType::kServiceWorkerCache:
- info->usage_breakdown->serviceWorkerCache += usage;
+ info->usage_breakdown->serviceWorkerCache += total_usage;
break;
case QuotaClientType::kServiceWorker:
- info->usage_breakdown->serviceWorker += usage;
+ info->usage_breakdown->serviceWorker += total_usage;
break;
case QuotaClientType::kBackgroundFetch:
- info->usage_breakdown->backgroundFetch += usage;
+ info->usage_breakdown->backgroundFetch += total_usage;
break;
case QuotaClientType::kNativeIO:
- info->usage_breakdown->fileSystem += usage;
+ info->usage_breakdown->fileSystem += total_usage;
break;
}
- std::move(callback).Run();
+ std::move(barrier_callback).Run();
}
-void UsageTracker::FinallySendHostUsageWithBreakdown(AccumulateInfo* info,
- const std::string& host) {
+void UsageTracker::FinallySendGlobalUsage(
+ std::unique_ptr<AccumulateInfo> info) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_GE(info->unlimited_usage, -1);
+ DCHECK_GE(info->usage, info->unlimited_usage);
+
+ // Moving callbacks out of the original vector early handles the case where a
+ // callback makes a new quota call.
+ std::vector<UsageCallback> pending_callbacks;
+ pending_callbacks.swap(global_usage_callbacks_);
+ for (auto& callback : pending_callbacks)
+ std::move(callback).Run(info->usage, info->unlimited_usage);
+}
+
+void UsageTracker::FinallySendHostUsageWithBreakdown(
+ std::unique_ptr<AccumulateInfo> info,
+ const std::string& host) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto it = host_usage_callbacks_.find(host);
if (it == host_usage_callbacks_.end())
@@ -257,9 +304,8 @@ void UsageTracker::FinallySendHostUsageWithBreakdown(AccumulateInfo* info,
<< "host_usage_callbacks_ should only have non-empty callback lists";
host_usage_callbacks_.erase(it);
- for (auto& callback : pending_callbacks) {
+ for (auto& callback : pending_callbacks)
std::move(callback).Run(info->usage, info->usage_breakdown->Clone());
- }
}
} // namespace storage
diff --git a/chromium/storage/browser/quota/usage_tracker.h b/chromium/storage/browser/quota/usage_tracker.h
index 7c300eae9cb..b95cdd47bcb 100644
--- a/chromium/storage/browser/quota/usage_tracker.h
+++ b/chromium/storage/browser/quota/usage_tracker.h
@@ -18,9 +18,12 @@
#include "base/containers/flat_map.h"
#include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h"
+#include "components/services/storage/public/cpp/buckets/bucket_info.h"
+#include "components/services/storage/public/cpp/buckets/bucket_locator.h"
#include "components/services/storage/public/mojom/quota_client.mojom.h"
#include "storage/browser/quota/quota_callbacks.h"
#include "storage/browser/quota/quota_client_type.h"
+#include "storage/browser/quota/quota_manager_impl.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"
@@ -45,6 +48,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) UsageTracker
// The caller must ensure that all mojo::QuotaClient instances outlive this
// instance.
UsageTracker(
+ QuotaManagerImpl* quota_manager_impl,
const base::flat_map<mojom::QuotaClient*, QuotaClientType>& client_types,
blink::mojom::StorageType type,
scoped_refptr<SpecialStoragePolicy> special_storage_policy);
@@ -54,26 +58,48 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) UsageTracker
~UsageTracker() override;
- blink::mojom::StorageType type() const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return type_;
- }
+ // Retrieves all buckets for type from QuotaDatabase and requests bucket usage
+ // from each registered client. Returns cached bucket usage if one exists for
+ // a bucket.
+ void GetGlobalUsage(UsageCallback callback);
- void GetGlobalUsage(GlobalUsageCallback callback);
+ // Retrieves all buckets for host from QuotaDatabase and requests bucket usage
+ // from each registered client. Returns cached bucket usage if one exists for
+ // a bucket.
void GetHostUsageWithBreakdown(const std::string& host,
UsageWithBreakdownCallback callback);
- void UpdateUsageCache(QuotaClientType client_type,
- const blink::StorageKey& storage_key,
- int64_t delta);
+
+ // Updates usage for `bucket` in the ClientUsageTracker for `client_type`.
+ void UpdateBucketUsageCache(QuotaClientType client_type,
+ const BucketLocator& bucket,
+ int64_t delta);
+
+ // Deletes `bucket` from the cache for `client_type` if it exists.
+ // Called by QuotaManagerImpl::BucketDataDeleter.
+ void DeleteBucketCache(QuotaClientType client_type,
+ const BucketLocator& bucket);
+
+ // Returns accumulated usage for all cached buckets from registered
+ // ClientUsageTrackers. Used to determine storage pressure.
int64_t GetCachedUsage() const;
+
+ // Retrieves all cached usage organized by host. Expected to be called after
+ // GetGlobalUsage which retrieves and caches host usage.
std::map<std::string, int64_t> GetCachedHostsUsage() const;
+
+ // Returns all cached usage organized by StorageKey. Used for histogram
+ // recording.
std::map<blink::StorageKey, int64_t> GetCachedStorageKeysUsage() const;
- std::set<blink::StorageKey> GetCachedStorageKeys() const;
+
+ // Checks if there are ongoing tasks to get global or host usage. Used to
+ // prevent a UsageTracker reset from happening before a task is complete.
bool IsWorking() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return !global_usage_callbacks_.empty() || !host_usage_callbacks_.empty();
}
+ // Sets if a `storage_key` for `client_type` should / should not be excluded
+ // from quota restrictions.
void SetUsageCacheEnabled(QuotaClientType client_type,
const blink::StorageKey& storage_key,
bool enabled);
@@ -82,29 +108,42 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) UsageTracker
struct AccumulateInfo;
friend class ClientUsageTracker;
- void AccumulateClientGlobalUsage(AccumulateInfo* info,
- int64_t usage,
+ void DidGetBucketsForType(QuotaErrorOr<std::set<BucketLocator>> result);
+ void DidGetBucketsForHost(const std::string& host,
+ QuotaErrorOr<std::set<BucketLocator>> result);
+ void DidGetBucketForUsage(QuotaClientType client_type,
+ int64_t delta,
+ QuotaErrorOr<BucketInfo> result);
+
+ void AccumulateClientGlobalUsage(base::OnceClosure barrier_callback,
+ AccumulateInfo* info,
+ int64_t total_usage,
int64_t unlimited_usage);
- void AccumulateClientHostUsage(base::OnceClosure callback,
+ void AccumulateClientHostUsage(base::OnceClosure barrier_callback,
AccumulateInfo* info,
const std::string& host,
QuotaClientType client,
- int64_t usage);
- void FinallySendHostUsageWithBreakdown(AccumulateInfo* info,
+ int64_t total_usage,
+ int64_t unlimited_usage);
+
+ void FinallySendGlobalUsage(std::unique_ptr<AccumulateInfo> info);
+ void FinallySendHostUsageWithBreakdown(std::unique_ptr<AccumulateInfo> info,
const std::string& host);
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ // Raw pointer usage is safe because `quota_manager_impl_` owns `this` and
+ // is therefore valid throughout its lifetime.
+ QuotaManagerImpl* const quota_manager_impl_;
const blink::mojom::StorageType type_;
base::flat_map<QuotaClientType,
std::vector<std::unique_ptr<ClientUsageTracker>>>
client_tracker_map_;
- size_t client_count_;
- std::vector<GlobalUsageCallback> global_usage_callbacks_;
+ std::vector<UsageCallback> global_usage_callbacks_;
std::map<std::string, std::vector<UsageWithBreakdownCallback>>
host_usage_callbacks_;
- SEQUENCE_CHECKER(sequence_checker_);
-
base::WeakPtrFactory<UsageTracker> weak_factory_{this};
};
diff --git a/chromium/storage/browser/quota/usage_tracker_unittest.cc b/chromium/storage/browser/quota/usage_tracker_unittest.cc
index 28e09638fe2..477d8fc4455 100644
--- a/chromium/storage/browser/quota/usage_tracker_unittest.cc
+++ b/chromium/storage/browser/quota/usage_tracker_unittest.cc
@@ -4,18 +4,25 @@
#include <stdint.h>
+#include <cstdint>
#include <utility>
#include <vector>
#include "base/bind.h"
+#include "base/files/scoped_temp_dir.h"
#include "base/location.h"
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/task_environment.h"
+#include "base/test/test_future.h"
#include "base/threading/thread_task_runner_handle.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 "components/services/storage/public/mojom/quota_client.mojom.h"
#include "storage/browser/quota/quota_client_type.h"
+#include "storage/browser/quota/quota_manager_impl.h"
#include "storage/browser/quota/usage_tracker.h"
#include "storage/browser/test/mock_special_storage_policy.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -29,17 +36,6 @@ namespace storage {
namespace {
-void DidGetGlobalUsage(bool* done,
- int64_t* usage_out,
- int64_t* unlimited_usage_out,
- int64_t usage,
- int64_t unlimited_usage) {
- EXPECT_FALSE(*done);
- *done = true;
- *usage_out = usage;
- *unlimited_usage_out = unlimited_usage;
-}
-
class UsageTrackerTestQuotaClient : public mojom::QuotaClient {
public:
UsageTrackerTestQuotaClient() = default;
@@ -48,11 +44,10 @@ class UsageTrackerTestQuotaClient : public mojom::QuotaClient {
UsageTrackerTestQuotaClient& operator=(const UsageTrackerTestQuotaClient&) =
delete;
- void GetStorageKeyUsage(const StorageKey& storage_key,
- StorageType type,
- GetStorageKeyUsageCallback callback) override {
- EXPECT_EQ(StorageType::kTemporary, type);
- int64_t usage = GetUsage(storage_key);
+ void GetBucketUsage(const BucketLocator& bucket,
+ GetBucketUsageCallback callback) override {
+ EXPECT_EQ(StorageType::kTemporary, bucket.type);
+ int64_t usage = GetUsage(bucket);
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), usage));
}
@@ -60,33 +55,19 @@ class UsageTrackerTestQuotaClient : public mojom::QuotaClient {
void GetStorageKeysForType(StorageType type,
GetStorageKeysForTypeCallback callback) override {
EXPECT_EQ(StorageType::kTemporary, type);
- 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(storage_keys)));
- }
-
- void GetStorageKeysForHost(StorageType type,
- const std::string& host,
- GetStorageKeysForHostCallback callback) override {
- EXPECT_EQ(StorageType::kTemporary, type);
- 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);
- }
+ std::set<StorageKey> storage_keys;
+ for (const auto& bucket_usage_pair : bucket_usage_map_)
+ storage_keys.emplace(bucket_usage_pair.first.storage_key);
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(std::move(callback), std::move(storage_keys)));
+ FROM_HERE, base::BindOnce(std::move(callback),
+ std::vector<StorageKey>(storage_keys.begin(),
+ storage_keys.end())));
}
- void DeleteStorageKeyData(const StorageKey& storage_key,
- StorageType type,
- DeleteStorageKeyDataCallback callback) override {
- EXPECT_EQ(StorageType::kTemporary, type);
- storage_key_usage_map_.erase(storage_key);
+ void DeleteBucketData(const BucketLocator& bucket,
+ DeleteBucketDataCallback callback) override {
+ EXPECT_EQ(StorageType::kTemporary, bucket.type);
+ bucket_usage_map_.erase(bucket);
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), QuotaStatusCode::kOk));
}
@@ -96,23 +77,19 @@ class UsageTrackerTestQuotaClient : public mojom::QuotaClient {
std::move(callback).Run();
}
- int64_t GetUsage(const StorageKey& storage_key) {
- auto it = storage_key_usage_map_.find(storage_key);
- if (it == storage_key_usage_map_.end())
+ int64_t GetUsage(const BucketLocator& bucket) {
+ auto it = bucket_usage_map_.find(bucket);
+ if (it == bucket_usage_map_.end())
return 0;
return it->second;
}
- void SetUsage(const StorageKey& storage_key, int64_t usage) {
- storage_key_usage_map_[storage_key] = usage;
- }
-
- int64_t UpdateUsage(const StorageKey& storage_key, int64_t delta) {
- return storage_key_usage_map_[storage_key] += delta;
+ int64_t UpdateUsage(const BucketLocator& bucket, int64_t delta) {
+ return bucket_usage_map_[bucket] += delta;
}
private:
- std::map<StorageKey, int64_t> storage_key_usage_map_;
+ std::map<BucketLocator, int64_t> bucket_usage_map_;
};
} // namespace
@@ -121,65 +98,47 @@ class UsageTrackerTest : public testing::Test {
public:
UsageTrackerTest()
: storage_policy_(base::MakeRefCounted<MockSpecialStoragePolicy>()),
- quota_client_(std::make_unique<UsageTrackerTestQuotaClient>()),
- usage_tracker_(GetQuotaClientMap(),
- StorageType::kTemporary,
- storage_policy_.get()) {}
+ quota_client_(std::make_unique<UsageTrackerTestQuotaClient>()) {
+ EXPECT_TRUE(base_.CreateUniqueTempDir());
+ quota_manager_ = base::MakeRefCounted<QuotaManagerImpl>(
+ /*is_incognito=*/false, base_.GetPath(),
+ base::ThreadTaskRunnerHandle::Get().get(),
+ /*quota_change_callback=*/base::DoNothing(), storage_policy_.get(),
+ GetQuotaSettingsFunc());
+ usage_tracker_ = std::make_unique<UsageTracker>(
+ quota_manager_.get(), GetQuotaClientMap(), StorageType::kTemporary,
+ storage_policy_.get());
+ }
UsageTrackerTest(const UsageTrackerTest&) = delete;
UsageTrackerTest& operator=(const UsageTrackerTest&) = delete;
~UsageTrackerTest() override = default;
- UsageTracker* usage_tracker() {
- return &usage_tracker_;
- }
-
- static void DidGetUsageBreakdown(
- bool* done,
- int64_t* usage_out,
- blink::mojom::UsageBreakdownPtr* usage_breakdown_out,
- int64_t usage,
- blink::mojom::UsageBreakdownPtr usage_breakdown) {
- EXPECT_FALSE(*done);
- *usage_out = usage;
- *usage_breakdown_out = std::move(usage_breakdown);
- *done = true;
- }
-
- void UpdateUsage(const StorageKey& storage_key, int64_t delta) {
- quota_client_->UpdateUsage(storage_key, delta);
- usage_tracker_.UpdateUsageCache(QuotaClientType::kFileSystem, storage_key,
- delta);
+ void UpdateUsage(const BucketInfo& bucket, int64_t delta) {
+ quota_client_->UpdateUsage(bucket.ToBucketLocator(), delta);
+ usage_tracker_->UpdateBucketUsageCache(QuotaClientType::kFileSystem,
+ bucket.ToBucketLocator(), delta);
base::RunLoop().RunUntilIdle();
}
- void UpdateUsageWithoutNotification(const StorageKey& storage_key,
- int64_t delta) {
- quota_client_->UpdateUsage(storage_key, delta);
+ void UpdateUsageWithoutNotification(const BucketInfo& bucket, int64_t delta) {
+ quota_client_->UpdateUsage(bucket.ToBucketLocator(), delta);
}
void GetGlobalUsage(int64_t* usage, int64_t* unlimited_usage) {
- bool done = false;
- usage_tracker_.GetGlobalUsage(
- base::BindOnce(&DidGetGlobalUsage, &done, usage, unlimited_usage));
- base::RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(done);
+ base::test::TestFuture<int64_t, int64_t> future;
+ usage_tracker_->GetGlobalUsage(future.GetCallback());
+ *usage = future.Get<0>();
+ *unlimited_usage = future.Get<1>();
}
std::pair<int64_t, blink::mojom::UsageBreakdownPtr> GetHostUsageWithBreakdown(
const std::string& host) {
- int64_t usage;
- blink::mojom::UsageBreakdownPtr usage_breakdown;
- bool done = false;
-
- usage_tracker_.GetHostUsageWithBreakdown(
- host, base::BindOnce(&UsageTrackerTest::DidGetUsageBreakdown, &done,
- &usage, &usage_breakdown));
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(done);
- return std::make_pair(usage, std::move(usage_breakdown));
+ base::test::TestFuture<int64_t, blink::mojom::UsageBreakdownPtr> future;
+ usage_tracker_->GetHostUsageWithBreakdown(host, future.GetCallback());
+ return std::make_pair(future.Get<0>(),
+ std::move(std::get<1>(future.Take())));
}
void GrantUnlimitedStoragePolicy(const StorageKey& storage_key) {
@@ -199,8 +158,29 @@ class UsageTrackerTest : public testing::Test {
}
void SetUsageCacheEnabled(const StorageKey& storage_key, bool enabled) {
- usage_tracker_.SetUsageCacheEnabled(QuotaClientType::kFileSystem,
- storage_key, enabled);
+ usage_tracker_->SetUsageCacheEnabled(QuotaClientType::kFileSystem,
+ storage_key, enabled);
+ }
+
+ BucketInfo CreateBucket(const StorageKey& storage_key,
+ const std::string& bucket_name) {
+ base::test::TestFuture<QuotaErrorOr<BucketInfo>> future;
+ quota_manager_->CreateBucketForTesting(storage_key, bucket_name,
+ StorageType::kTemporary,
+ future.GetCallback());
+ QuotaErrorOr<BucketInfo> bucket_result = future.Take();
+ DCHECK(bucket_result.ok());
+ return bucket_result.value();
+ }
+
+ void OpenDatabase() { quota_manager_->EnsureDatabaseOpened(); }
+
+ void disable_quota_database(bool disable) {
+ quota_manager_->database_->SetDisabledForTesting(disable);
+ }
+
+ void disable_database_bootstrap(bool disable) {
+ quota_manager_->SetBootstrapDisabledForTesting(disable);
}
private:
@@ -215,7 +195,10 @@ class UsageTrackerTest : public testing::Test {
scoped_refptr<MockSpecialStoragePolicy> storage_policy_;
std::unique_ptr<UsageTrackerTestQuotaClient> quota_client_;
- UsageTracker usage_tracker_;
+
+ scoped_refptr<QuotaManagerImpl> quota_manager_;
+ std::unique_ptr<UsageTracker> usage_tracker_;
+ base::ScopedTempDir base_;
};
TEST_F(UsageTrackerTest, GrantAndRevokeUnlimitedStorage) {
@@ -231,7 +214,9 @@ TEST_F(UsageTrackerTest, GrantAndRevokeUnlimitedStorage) {
StorageKey::CreateFromStringForTesting("http://example.com");
const std::string& host = storage_key.origin().host();
- UpdateUsage(storage_key, 100);
+ BucketInfo bucket = CreateBucket(storage_key, kDefaultBucketName);
+
+ UpdateUsage(bucket, 100);
GetGlobalUsage(&usage, &unlimited_usage);
EXPECT_EQ(100, usage);
EXPECT_EQ(0, unlimited_usage);
@@ -268,7 +253,9 @@ TEST_F(UsageTrackerTest, CacheDisabledClientTest) {
StorageKey::CreateFromStringForTesting("http://example.com");
const std::string& host = storage_key.origin().host();
- UpdateUsage(storage_key, 100);
+ BucketInfo bucket = CreateBucket(storage_key, kDefaultBucketName);
+
+ UpdateUsage(bucket, 100);
GetGlobalUsage(&usage, &unlimited_usage);
EXPECT_EQ(100, usage);
EXPECT_EQ(0, unlimited_usage);
@@ -278,7 +265,7 @@ TEST_F(UsageTrackerTest, CacheDisabledClientTest) {
EXPECT_EQ(100, host_usage_breakdown.first);
EXPECT_EQ(host_usage_breakdown_expected, host_usage_breakdown.second);
- UpdateUsageWithoutNotification(storage_key, 100);
+ UpdateUsageWithoutNotification(bucket, 100);
GetGlobalUsage(&usage, &unlimited_usage);
EXPECT_EQ(100, usage);
EXPECT_EQ(0, unlimited_usage);
@@ -287,9 +274,9 @@ TEST_F(UsageTrackerTest, CacheDisabledClientTest) {
EXPECT_EQ(host_usage_breakdown_expected, host_usage_breakdown.second);
GrantUnlimitedStoragePolicy(storage_key);
- UpdateUsageWithoutNotification(storage_key, 100);
+ UpdateUsageWithoutNotification(bucket, 100);
SetUsageCacheEnabled(storage_key, false);
- UpdateUsageWithoutNotification(storage_key, 100);
+ UpdateUsageWithoutNotification(bucket, 100);
GetGlobalUsage(&usage, &unlimited_usage);
EXPECT_EQ(400, usage);
@@ -308,7 +295,7 @@ TEST_F(UsageTrackerTest, CacheDisabledClientTest) {
EXPECT_EQ(host_usage_breakdown_expected, host_usage_breakdown.second);
SetUsageCacheEnabled(storage_key, true);
- UpdateUsage(storage_key, 100);
+ UpdateUsage(bucket, 100);
GetGlobalUsage(&usage, &unlimited_usage);
EXPECT_EQ(500, usage);
@@ -329,16 +316,22 @@ TEST_F(UsageTrackerTest, GlobalUsageUnlimitedUncached) {
const StorageKey kNonCachedUnlimited =
StorageKey::CreateFromStringForTesting("http://non_cached-unlimited");
+ BucketInfo bucket_normal = CreateBucket(kNormal, kDefaultBucketName);
+ BucketInfo bucket_unlimited = CreateBucket(kUnlimited, kDefaultBucketName);
+ BucketInfo bucket_noncached = CreateBucket(kNonCached, kDefaultBucketName);
+ BucketInfo bucket_noncached_unlimited =
+ CreateBucket(kNonCachedUnlimited, kDefaultBucketName);
+
GrantUnlimitedStoragePolicy(kUnlimited);
GrantUnlimitedStoragePolicy(kNonCachedUnlimited);
SetUsageCacheEnabled(kNonCached, false);
SetUsageCacheEnabled(kNonCachedUnlimited, false);
- UpdateUsageWithoutNotification(kNormal, 1);
- UpdateUsageWithoutNotification(kUnlimited, 2);
- UpdateUsageWithoutNotification(kNonCached, 4);
- UpdateUsageWithoutNotification(kNonCachedUnlimited, 8);
+ UpdateUsageWithoutNotification(bucket_normal, 1);
+ UpdateUsageWithoutNotification(bucket_unlimited, 2);
+ UpdateUsageWithoutNotification(bucket_noncached, 4);
+ UpdateUsageWithoutNotification(bucket_noncached_unlimited, 8);
int64_t total_usage = 0;
int64_t unlimited_usage = 0;
@@ -347,8 +340,8 @@ TEST_F(UsageTrackerTest, GlobalUsageUnlimitedUncached) {
EXPECT_EQ(1 + 2 + 4 + 8, total_usage);
EXPECT_EQ(2 + 8, unlimited_usage);
- UpdateUsageWithoutNotification(kNonCached, 16 - 4);
- UpdateUsageWithoutNotification(kNonCachedUnlimited, 32 - 8);
+ UpdateUsageWithoutNotification(bucket_noncached, 16 - 4);
+ UpdateUsageWithoutNotification(bucket_noncached_unlimited, 32 - 8);
GetGlobalUsage(&total_usage, &unlimited_usage);
EXPECT_EQ(1 + 2 + 16 + 32, total_usage);
@@ -363,8 +356,11 @@ TEST_F(UsageTrackerTest, GlobalUsageMultipleStorageKeysPerHostCachedInit) {
ASSERT_EQ(kStorageKey1.origin().host(), kStorageKey2.origin().host())
<< "The test assumes that the two storage keys have the same host";
- UpdateUsageWithoutNotification(kStorageKey1, 100);
- UpdateUsageWithoutNotification(kStorageKey2, 200);
+ BucketInfo bucket1 = CreateBucket(kStorageKey1, kDefaultBucketName);
+ BucketInfo bucket2 = CreateBucket(kStorageKey2, kDefaultBucketName);
+
+ UpdateUsageWithoutNotification(bucket1, 100);
+ UpdateUsageWithoutNotification(bucket2, 200);
int64_t total_usage = 0;
int64_t unlimited_usage = 0;
@@ -384,6 +380,9 @@ TEST_F(UsageTrackerTest, GlobalUsageMultipleStorageKeysPerHostCachedUpdate) {
ASSERT_EQ(kStorageKey1.origin().host(), kStorageKey2.origin().host())
<< "The test assumes that the two storage keys have the same host";
+ BucketInfo bucket1 = CreateBucket(kStorageKey1, kDefaultBucketName);
+ BucketInfo bucket2 = CreateBucket(kStorageKey2, kDefaultBucketName);
+
int64_t total_usage = 0;
int64_t unlimited_usage = 0;
// GetGlobalUsage() takes different code paths on the first call and on
@@ -393,8 +392,8 @@ TEST_F(UsageTrackerTest, GlobalUsageMultipleStorageKeysPerHostCachedUpdate) {
EXPECT_EQ(0, total_usage);
EXPECT_EQ(0, unlimited_usage);
- UpdateUsage(kStorageKey1, 100);
- UpdateUsage(kStorageKey2, 200);
+ UpdateUsage(bucket1, 100);
+ UpdateUsage(bucket2, 200);
GetGlobalUsage(&total_usage, &unlimited_usage);
EXPECT_EQ(100 + 200, total_usage);
@@ -409,11 +408,14 @@ TEST_F(UsageTrackerTest, GlobalUsageMultipleStorageKeysPerHostUncachedInit) {
ASSERT_EQ(kStorageKey1.origin().host(), kStorageKey2.origin().host())
<< "The test assumes that the two storage keys have the same host";
+ BucketInfo bucket1 = CreateBucket(kStorageKey1, kDefaultBucketName);
+ BucketInfo bucket2 = CreateBucket(kStorageKey2, kDefaultBucketName);
+
SetUsageCacheEnabled(kStorageKey1, false);
SetUsageCacheEnabled(kStorageKey2, false);
- UpdateUsageWithoutNotification(kStorageKey1, 100);
- UpdateUsageWithoutNotification(kStorageKey2, 200);
+ UpdateUsageWithoutNotification(bucket1, 100);
+ UpdateUsageWithoutNotification(bucket2, 200);
int64_t total_usage = 0;
int64_t unlimited_usage = 0;
@@ -433,6 +435,9 @@ TEST_F(UsageTrackerTest, GlobalUsageMultipleStorageKeysPerHostUncachedUpdate) {
ASSERT_EQ(kStorageKey1.origin().host(), kStorageKey2.origin().host())
<< "The test assumes that the two storage keys have the same host";
+ BucketInfo bucket1 = CreateBucket(kStorageKey1, kDefaultBucketName);
+ BucketInfo bucket2 = CreateBucket(kStorageKey2, kDefaultBucketName);
+
int64_t total_usage = 0;
int64_t unlimited_usage = 0;
// GetGlobalUsage() takes different code paths on the first call and on
@@ -445,12 +450,32 @@ TEST_F(UsageTrackerTest, GlobalUsageMultipleStorageKeysPerHostUncachedUpdate) {
SetUsageCacheEnabled(kStorageKey1, false);
SetUsageCacheEnabled(kStorageKey2, false);
- UpdateUsageWithoutNotification(kStorageKey1, 100);
- UpdateUsageWithoutNotification(kStorageKey2, 200);
+ UpdateUsageWithoutNotification(bucket1, 100);
+ UpdateUsageWithoutNotification(bucket2, 200);
GetGlobalUsage(&total_usage, &unlimited_usage);
EXPECT_EQ(100 + 200, total_usage);
EXPECT_EQ(0, unlimited_usage);
}
+TEST_F(UsageTrackerTest, QuotaDatabaseDisabled) {
+ disable_database_bootstrap(true);
+ OpenDatabase();
+
+ disable_quota_database(true);
+
+ int64_t total_usage = 0;
+ int64_t unlimited_usage = 0;
+ GetGlobalUsage(&total_usage, &unlimited_usage);
+ EXPECT_EQ(total_usage, -1);
+ EXPECT_EQ(unlimited_usage, -1);
+
+ const StorageKey kStorageKey =
+ StorageKey::CreateFromStringForTesting("http://example.com");
+ std::pair<int64_t, blink::mojom::UsageBreakdownPtr> host_usage_breakdown =
+ GetHostUsageWithBreakdown(kStorageKey.origin().host());
+ EXPECT_EQ(host_usage_breakdown.first, -1);
+ EXPECT_EQ(host_usage_breakdown.second, blink::mojom::UsageBreakdown::New());
+}
+
} // namespace storage
diff --git a/chromium/storage/common/file_system/file_system_types.h b/chromium/storage/common/file_system/file_system_types.h
index 0677b34cdb9..e5630d1279f 100644
--- a/chromium/storage/common/file_system/file_system_types.h
+++ b/chromium/storage/common/file_system/file_system_types.h
@@ -122,7 +122,10 @@ enum FileSystemType {
// Indicates an SmbFs filesystem which provides access to SMB file shares.
kFileSystemTypeSmbFs,
- kFileSystemTypeLast = kFileSystemTypeSmbFs,
+ // Indicates a FUSE filesystem which provides access to virtual files.
+ kFileSystemTypeFuseBox,
+
+ kFileSystemTypeLast = kFileSystemTypeFuseBox,
// --------------------------------------------------------------------
// Marks the end of internal type enum. (This is not the actual fs type)
diff --git a/chromium/storage/common/file_system/file_system_util.cc b/chromium/storage/common/file_system/file_system_util.cc
index 34aa58cfd30..1d91dc7aff0 100644
--- a/chromium/storage/common/file_system/file_system_util.cc
+++ b/chromium/storage/common/file_system/file_system_util.cc
@@ -277,10 +277,12 @@ std::string GetFileSystemTypeString(FileSystemType type) {
return "DriveFs";
case kFileSystemTypeSmbFs:
return "SmbFs";
+ case kFileSystemTypeFuseBox:
+ return "FuseBox";
case kFileSystemInternalTypeEnumStart:
case kFileSystemInternalTypeEnumEnd:
NOTREACHED();
- FALLTHROUGH;
+ [[fallthrough]];
case kFileSystemTypeUnknown:
return "Unknown";
}
@@ -290,18 +292,18 @@ std::string GetFileSystemTypeString(FileSystemType type) {
std::string FilePathToString(const base::FilePath& file_path) {
// TODO(pkasting): Probably this should use AsUTF8Unsafe() across platforms.
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
return file_path.AsUTF8Unsafe();
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
+#elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
return file_path.value();
#endif
}
base::FilePath StringToFilePath(const std::string& file_path_string) {
// TODO(pkasting): Probably this should use FromUTF8Unsafe() across platforms.
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
return base::FilePath::FromUTF8Unsafe(file_path_string);
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
+#elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
return base::FilePath(file_path_string);
#endif
}