0

Make the PERSISTENT filesystem use temporary quota.

This CL also adds support in BarrierCallback for running done_callbacks
that take a `const std::vector<T>&` of results, rather than a
std::vector<T>; and also adds support for use with RepeatingCallbacks
whose parameter T is a const and/or reference.

Persistent Quota I2D:
https://groups.google.com/u/1/a/chromium.org/g/blink-dev/c/ziTjKMdOqz8

Bug: 1233525
Change-Id: I005b5b9329692f13a7b16f9bdb8e4be462c6fcc4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3052556
Commit-Queue: Chris Fredrickson <cfredric@chromium.org>
Reviewed-by: Marijn Kruisselbrink <mek@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#913064}
This commit is contained in:
cfredric
2021-08-18 17:56:52 +00:00
committed by Chromium LUCI CQ
parent 514cf8b843
commit dfcd193db4
12 changed files with 294 additions and 124 deletions

@ -7480,6 +7480,11 @@ const FeatureEntry kFeatureEntries[] = {
flag_descriptions::kExtensionsMenuAccessControlDescription, kOsDesktop,
FEATURE_VALUE_TYPE(features::kExtensionsMenuAccessControl)},
{"persistent-quota-is-temporary-quota",
flag_descriptions::kPersistentQuotaIsTemporaryQuotaName,
flag_descriptions::kPersistentQuotaIsTemporaryQuotaDescription, kOsAll,
FEATURE_VALUE_TYPE(blink::features::kPersistentQuotaIsTemporaryQuota)},
// NOTE: Adding a new flag requires adding a corresponding entry to enum
// "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag
// Histograms" in tools/metrics/histograms/README.md (run the

@ -4421,6 +4421,11 @@
"owners": [ "elklm", "engedy"],
"expiry_milestone": 100
},
{
"name": "persistent-quota-is-temporary-quota",
"owners": [ "mek", "cfredric" ],
"expiry_milestone": 100
},
{
"name": "photo-picker-video-support",
"owners": [ "finnur" ],

@ -2038,6 +2038,12 @@ const char kPermissionQuietChipDescription[] =
"prompts. Requires chrome://flags/#quiet-notification-prompts to be "
"enabled.";
const char kPersistentQuotaIsTemporaryQuotaName[] =
"window.PERSISTENT is temporary quota.";
const char kPersistentQuotaIsTemporaryQuotaDescription[] =
"Causes the window.PERSISTENT quota type to have the same semantics as "
"window.TEMPORARY.";
const char kPlaybackSpeedButtonName[] = "Playback Speed Button";
const char kPlaybackSpeedButtonDescription[] =
"Enable the playback speed button on the media controls.";

@ -1160,6 +1160,9 @@ extern const char kPermissionPredictionsDescription[];
extern const char kPermissionQuietChipName[];
extern const char kPermissionQuietChipDescription[];
extern const char kPersistentQuotaIsTemporaryQuotaName[];
extern const char kPersistentQuotaIsTemporaryQuotaDescription[];
extern const char kPlaybackSpeedButtonName[];
extern const char kPlaybackSpeedButtonDescription[];

@ -4,12 +4,17 @@
#include "storage/browser/file_system/file_system_quota_client.h"
#include <numeric>
#include <string>
#include <utility>
#include <vector>
#include "base/barrier_callback.h"
#include "base/barrier_closure.h"
#include "base/bind.h"
#include "base/check.h"
#include "base/containers/span.h"
#include "base/feature_list.h"
#include "base/files/file.h"
#include "base/location.h"
#include "base/sequence_checker.h"
@ -18,6 +23,7 @@
#include "storage/browser/file_system/file_system_context.h"
#include "storage/common/file_system/file_system_types.h"
#include "storage/common/file_system/file_system_util.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
#include "url/origin.h"
@ -26,6 +32,14 @@ namespace storage {
namespace {
static const FileSystemType kTemporaryAndPersistent[] = {
kFileSystemTypeTemporary,
kFileSystemTypePersistent,
};
static const FileSystemType kTemporary[] = {kFileSystemTypeTemporary};
static const FileSystemType kPersistent[] = {kFileSystemTypePersistent};
static const FileSystemType kSyncable[] = {kFileSystemTypeSyncable};
std::vector<blink::StorageKey> ToStorageKeys(
const std::vector<url::Origin>& origins) {
std::vector<blink::StorageKey> storage_keys;
@ -35,13 +49,53 @@ std::vector<blink::StorageKey> ToStorageKeys(
return storage_keys;
}
template <typename T>
std::vector<T> MergeWithoutDuplicates(const std::vector<std::vector<T>>& tss) {
if (tss.size() == 1) {
// We assume that each vector contains no duplicates, already.
return tss[0];
}
std::vector<T> merged;
merged.reserve(std::accumulate(
tss.begin(), tss.end(), 0U,
[](size_t acc, const std::vector<T>& ts) { return acc + ts.size(); }));
for (const auto& ts : tss) {
merged.insert(merged.end(), ts.begin(), ts.end());
}
base::ranges::sort(merged);
merged.erase(base::ranges::unique(merged), merged.end());
return merged;
}
// Converts StorageType to the FileSystemTypes that are used for that quota
// type.
base::span<const FileSystemType> QuotaStorageTypeToFileSystemTypes(
blink::mojom::StorageType storage_type) {
using StorageType = blink::mojom::StorageType;
if (base::FeatureList::IsEnabled(
blink::features::kPersistentQuotaIsTemporaryQuota)) {
DCHECK_NE(storage_type, StorageType::kPersistent);
if (storage_type == StorageType::kTemporary)
return kTemporaryAndPersistent;
}
switch (storage_type) {
case StorageType::kTemporary:
return kTemporary;
case StorageType::kPersistent:
return kPersistent;
case StorageType::kSyncable:
return kSyncable;
case StorageType::kQuotaNotManaged:
case StorageType::kUnknown:
NOTREACHED();
return {};
}
}
std::vector<blink::StorageKey> GetStorageKeysForTypeOnFileTaskRunner(
FileSystemContext* context,
blink::mojom::StorageType storage_type) {
FileSystemType type =
FileSystemQuotaClient::QuotaStorageTypeToFileSystemType(storage_type);
DCHECK(type != kFileSystemTypeUnknown);
FileSystemType type) {
FileSystemQuotaUtil* quota_util = context->GetQuotaUtil(type);
if (!quota_util)
return {};
@ -50,12 +104,8 @@ std::vector<blink::StorageKey> GetStorageKeysForTypeOnFileTaskRunner(
std::vector<blink::StorageKey> GetStorageKeysForHostOnFileTaskRunner(
FileSystemContext* context,
blink::mojom::StorageType storage_type,
FileSystemType type,
const std::string& host) {
FileSystemType type =
FileSystemQuotaClient::QuotaStorageTypeToFileSystemType(storage_type);
DCHECK(type != kFileSystemTypeUnknown);
FileSystemQuotaUtil* quota_util = context->GetQuotaUtil(type);
if (!quota_util)
return {};
@ -107,24 +157,31 @@ void FileSystemQuotaClient::GetStorageKeyUsage(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!callback.is_null());
FileSystemType type =
FileSystemQuotaClient::QuotaStorageTypeToFileSystemType(storage_type);
DCHECK(type != kFileSystemTypeUnknown);
base::span<const FileSystemType> types =
QuotaStorageTypeToFileSystemTypes(storage_type);
FileSystemQuotaUtil* quota_util = file_system_context_->GetQuotaUtil(type);
if (!quota_util) {
std::move(callback).Run(0);
return;
base::RepeatingCallback<void(int64_t)> barrier =
base::BarrierCallback<int64_t>(
types.size(), base::BindOnce([](std::vector<int64_t> usages) {
return std::accumulate(usages.begin(), usages.end(),
0U);
}).Then(std::move(callback)));
for (auto type : types) {
FileSystemQuotaUtil* quota_util = file_system_context_->GetQuotaUtil(type);
if (quota_util) {
file_task_runner()->PostTaskAndReplyWithResult(
FROM_HERE,
// It is safe to pass Unretained(quota_util) since context owns it.
base::BindOnce(&FileSystemQuotaUtil::GetOriginUsageOnFileTaskRunner,
base::Unretained(quota_util),
base::RetainedRef(file_system_context_),
storage_key.origin(), type),
barrier);
} else {
barrier.Run(0);
}
}
file_task_runner()->PostTaskAndReplyWithResult(
FROM_HERE,
// It is safe to pass Unretained(quota_util) since context owns it.
base::BindOnce(&FileSystemQuotaUtil::GetOriginUsageOnFileTaskRunner,
base::Unretained(quota_util),
base::RetainedRef(file_system_context_),
storage_key.origin(), type),
std::move(callback));
}
void FileSystemQuotaClient::GetStorageKeysForType(
@ -133,11 +190,22 @@ void FileSystemQuotaClient::GetStorageKeysForType(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!callback.is_null());
file_task_runner()->PostTaskAndReplyWithResult(
FROM_HERE,
base::BindOnce(&GetStorageKeysForTypeOnFileTaskRunner,
base::RetainedRef(file_system_context_), storage_type),
std::move(callback));
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(&GetStorageKeysForTypeOnFileTaskRunner,
base::RetainedRef(file_system_context_), type),
barrier);
}
}
void FileSystemQuotaClient::GetStorageKeysForHost(
@ -147,12 +215,22 @@ void FileSystemQuotaClient::GetStorageKeysForHost(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!callback.is_null());
file_task_runner()->PostTaskAndReplyWithResult(
FROM_HERE,
base::BindOnce(&GetStorageKeysForHostOnFileTaskRunner,
base::RetainedRef(file_system_context_), storage_type,
host),
std::move(callback));
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_), type, host),
barrier);
}
}
void FileSystemQuotaClient::DeleteStorageKeyData(
@ -162,15 +240,29 @@ void FileSystemQuotaClient::DeleteStorageKeyData(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!callback.is_null());
FileSystemType fs_type = QuotaStorageTypeToFileSystemType(type);
DCHECK(fs_type != kFileSystemTypeUnknown);
base::span<const FileSystemType> fs_types =
QuotaStorageTypeToFileSystemTypes(type);
file_task_runner()->PostTaskAndReplyWithResult(
FROM_HERE,
base::BindOnce(&DeleteStorageKeyOnFileTaskRunner,
base::RetainedRef(file_system_context_), storage_key,
fs_type),
std::move(callback));
base::RepeatingCallback<void(blink::mojom::QuotaStatusCode)> barrier =
base::BarrierCallback<blink::mojom::QuotaStatusCode>(
fs_types.size(),
base::BindOnce([](const std::vector<blink::mojom::QuotaStatusCode>&
statuses) {
for (auto status : statuses) {
if (status != blink::mojom::QuotaStatusCode::kOk)
return status;
}
return blink::mojom::QuotaStatusCode::kOk;
}).Then(std::move(callback)));
for (const auto fs_type : fs_types) {
file_task_runner()->PostTaskAndReplyWithResult(
FROM_HERE,
base::BindOnce(&DeleteStorageKeyOnFileTaskRunner,
base::RetainedRef(file_system_context_), storage_key,
fs_type),
barrier);
}
}
void FileSystemQuotaClient::PerformStorageCleanup(
@ -179,30 +271,19 @@ void FileSystemQuotaClient::PerformStorageCleanup(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!callback.is_null());
FileSystemType fs_type = QuotaStorageTypeToFileSystemType(type);
DCHECK(fs_type != kFileSystemTypeUnknown);
file_task_runner()->PostTaskAndReply(
FROM_HERE,
base::BindOnce(&PerformStorageCleanupOnFileTaskRunner,
base::RetainedRef(file_system_context_), fs_type),
std::move(callback));
}
base::span<const FileSystemType> fs_types =
QuotaStorageTypeToFileSystemTypes(type);
// static
FileSystemType FileSystemQuotaClient::QuotaStorageTypeToFileSystemType(
blink::mojom::StorageType storage_type) {
switch (storage_type) {
case blink::mojom::StorageType::kTemporary:
return kFileSystemTypeTemporary;
case blink::mojom::StorageType::kPersistent:
return kFileSystemTypePersistent;
case blink::mojom::StorageType::kSyncable:
return kFileSystemTypeSyncable;
case blink::mojom::StorageType::kQuotaNotManaged:
case blink::mojom::StorageType::kUnknown:
return kFileSystemTypeUnknown;
base::RepeatingClosure barrier =
base::BarrierClosure(fs_types.size(), std::move(callback));
for (auto fs_type : fs_types) {
file_task_runner()->PostTaskAndReply(
FROM_HERE,
base::BindOnce(&PerformStorageCleanupOnFileTaskRunner,
base::RetainedRef(file_system_context_), fs_type),
barrier);
}
return kFileSystemTypeUnknown;
}
base::SequencedTaskRunner* FileSystemQuotaClient::file_task_runner() const {

@ -55,14 +55,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemQuotaClient
void PerformStorageCleanup(blink::mojom::StorageType type,
PerformStorageCleanupCallback callback) override;
// Converts FileSystemType `type` to/from the StorageType `storage_type` that
// is used for the unified quota system.
// (Basically this naively maps TEMPORARY storage type to TEMPORARY filesystem
// type, PERSISTENT storage type to PERSISTENT filesystem type and vice
// versa.)
static FileSystemType QuotaStorageTypeToFileSystemType(
blink::mojom::StorageType storage_type);
private:
base::SequencedTaskRunner* file_task_runner() const;

@ -13,6 +13,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "components/services/storage/public/mojom/quota_client.mojom.h"
#include "storage/browser/file_system/file_system_context.h"
@ -27,6 +28,7 @@
#include "storage/common/file_system/file_system_util.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
#include "url/gurl.h"
@ -48,17 +50,26 @@ const StorageType kPersistent = StorageType::kPersistent;
} // namespace
class FileSystemQuotaClientTest : public testing::Test {
class FileSystemQuotaClientTest : public testing::TestWithParam<bool> {
public:
FileSystemQuotaClientTest() = default;
~FileSystemQuotaClientTest() override = default;
void SetUp() override {
if (persistent_quota_is_temporary_quota()) {
feature_list_.InitAndEnableFeature(
blink::features::kPersistentQuotaIsTemporaryQuota);
} else {
feature_list_.InitAndDisableFeature(
blink::features::kPersistentQuotaIsTemporaryQuota);
}
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
file_system_context_ = CreateFileSystemContextForTesting(
/*quota_manager_proxy=*/nullptr, data_dir_.GetPath());
}
bool persistent_quota_is_temporary_quota() const { return GetParam(); }
struct TestFile {
bool isDirectory;
const char* name;
@ -169,9 +180,8 @@ class FileSystemQuotaClientTest : public testing::Test {
// create it later, this will fail due to a quota mismatch. If we
// call this before we create the root, it succeeds, but hasn't
// actually created the cache.
ASSERT_EQ(0, GetStorageKeyUsage(
quota_client, file.origin_url,
FileSystemTypeToQuotaStorageType(file.type)));
GetStorageKeyUsage(quota_client, file.origin_url,
FileSystemTypeToQuotaStorageType(file.type));
}
} else {
ASSERT_TRUE(
@ -232,6 +242,7 @@ class FileSystemQuotaClientTest : public testing::Test {
deletion_status_ = status;
}
base::test::ScopedFeatureList feature_list_;
base::ScopedTempDir data_dir_;
base::test::TaskEnvironment task_environment_;
scoped_refptr<FileSystemContext> file_system_context_;
@ -243,13 +254,13 @@ class FileSystemQuotaClientTest : public testing::Test {
base::WeakPtrFactory<FileSystemQuotaClientTest> weak_factory_{this};
};
TEST_F(FileSystemQuotaClientTest, NoFileSystemTest) {
TEST_P(FileSystemQuotaClientTest, NoFileSystemTest) {
FileSystemQuotaClient quota_client(GetFileSystemContext());
EXPECT_EQ(0, GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary));
}
TEST_F(FileSystemQuotaClientTest, NoFileTest) {
TEST_P(FileSystemQuotaClientTest, NoFileTest) {
FileSystemQuotaClient quota_client(GetFileSystemContext());
InitializeOriginFiles(quota_client,
@ -260,7 +271,7 @@ TEST_F(FileSystemQuotaClientTest, NoFileTest) {
}
}
TEST_F(FileSystemQuotaClientTest, OneFileTest) {
TEST_P(FileSystemQuotaClientTest, OneFileTest) {
FileSystemQuotaClient quota_client(GetFileSystemContext());
const std::vector<TestFile> kFiles = {
{true, "", 0, kDummyURL1, kFileSystemTypeTemporary},
@ -276,7 +287,7 @@ TEST_F(FileSystemQuotaClientTest, OneFileTest) {
}
}
TEST_F(FileSystemQuotaClientTest, TwoFilesTest) {
TEST_P(FileSystemQuotaClientTest, TwoFilesTest) {
FileSystemQuotaClient quota_client(GetFileSystemContext());
const std::vector<TestFile> kFiles = {
{true, "", 0, kDummyURL1, kFileSystemTypeTemporary},
@ -293,7 +304,7 @@ TEST_F(FileSystemQuotaClientTest, TwoFilesTest) {
}
}
TEST_F(FileSystemQuotaClientTest, EmptyFilesTest) {
TEST_P(FileSystemQuotaClientTest, EmptyFilesTest) {
FileSystemQuotaClient quota_client(GetFileSystemContext());
const std::vector<TestFile> kFiles = {
{true, "", 0, kDummyURL1, kFileSystemTypeTemporary},
@ -311,7 +322,7 @@ TEST_F(FileSystemQuotaClientTest, EmptyFilesTest) {
}
}
TEST_F(FileSystemQuotaClientTest, SubDirectoryTest) {
TEST_P(FileSystemQuotaClientTest, SubDirectoryTest) {
FileSystemQuotaClient quota_client(GetFileSystemContext());
const std::vector<TestFile> kFiles = {
{true, "", 0, kDummyURL1, kFileSystemTypeTemporary},
@ -329,7 +340,7 @@ TEST_F(FileSystemQuotaClientTest, SubDirectoryTest) {
}
}
TEST_F(FileSystemQuotaClientTest, MultiTypeTest) {
TEST_P(FileSystemQuotaClientTest, MultiTypeTest) {
FileSystemQuotaClient quota_client(GetFileSystemContext());
const std::vector<TestFile> kFiles = {
{true, "", 0, kDummyURL1, kFileSystemTypeTemporary},
@ -350,14 +361,20 @@ TEST_F(FileSystemQuotaClientTest, MultiTypeTest) {
kFileSystemTypePersistent);
for (int i = 0; i < 2; i++) {
EXPECT_EQ(133 + 14 + file_paths_cost_temporary,
GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary));
EXPECT_EQ(193 + 9 + file_paths_cost_persistent,
GetStorageKeyUsage(quota_client, kDummyURL1, kPersistent));
if (persistent_quota_is_temporary_quota()) {
EXPECT_EQ(133 + 14 + file_paths_cost_temporary + 193 + 9 +
file_paths_cost_persistent,
GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary));
} else {
EXPECT_EQ(133 + 14 + file_paths_cost_temporary,
GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary));
EXPECT_EQ(193 + 9 + file_paths_cost_persistent,
GetStorageKeyUsage(quota_client, kDummyURL1, kPersistent));
}
}
}
TEST_F(FileSystemQuotaClientTest, MultiDomainTest) {
TEST_P(FileSystemQuotaClientTest, MultiDomainTest) {
FileSystemQuotaClient quota_client(GetFileSystemContext());
const std::vector<TestFile> kFiles = {
{true, "", 0, kDummyURL1, kFileSystemTypeTemporary},
@ -392,18 +409,27 @@ TEST_F(FileSystemQuotaClientTest, MultiDomainTest) {
kFileSystemTypePersistent);
for (int i = 0; i < 2; i++) {
EXPECT_EQ(1331 + 134 + file_paths_cost_temporary1,
GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary));
EXPECT_EQ(1903 + 19 + file_paths_cost_persistent1,
GetStorageKeyUsage(quota_client, kDummyURL1, kPersistent));
EXPECT_EQ(1319 + 113 + file_paths_cost_temporary2,
GetStorageKeyUsage(quota_client, kDummyURL2, kTemporary));
EXPECT_EQ(2013 + 18 + file_paths_cost_persistent2,
GetStorageKeyUsage(quota_client, kDummyURL2, kPersistent));
if (persistent_quota_is_temporary_quota()) {
EXPECT_EQ(1331 + 134 + file_paths_cost_temporary1 + 1903 + 19 +
file_paths_cost_persistent1,
GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary));
EXPECT_EQ(1319 + 113 + file_paths_cost_temporary2 + 2013 + 18 +
file_paths_cost_persistent2,
GetStorageKeyUsage(quota_client, kDummyURL2, kTemporary));
} else {
EXPECT_EQ(1331 + 134 + file_paths_cost_temporary1,
GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary));
EXPECT_EQ(1903 + 19 + file_paths_cost_persistent1,
GetStorageKeyUsage(quota_client, kDummyURL1, kPersistent));
EXPECT_EQ(1319 + 113 + file_paths_cost_temporary2,
GetStorageKeyUsage(quota_client, kDummyURL2, kTemporary));
EXPECT_EQ(2013 + 18 + file_paths_cost_persistent2,
GetStorageKeyUsage(quota_client, kDummyURL2, kPersistent));
}
}
}
TEST_F(FileSystemQuotaClientTest, GetUsage_MultipleTasks) {
TEST_P(FileSystemQuotaClientTest, GetUsage_MultipleTasks) {
FileSystemQuotaClient quota_client(GetFileSystemContext());
const std::vector<TestFile> kFiles = {
{true, "", 0, kDummyURL1, kFileSystemTypeTemporary},
@ -433,7 +459,7 @@ TEST_F(FileSystemQuotaClientTest, GetUsage_MultipleTasks) {
EXPECT_EQ(2, additional_callback_count());
}
TEST_F(FileSystemQuotaClientTest, GetStorageKeysForType) {
TEST_P(FileSystemQuotaClientTest, GetStorageKeysForType) {
FileSystemQuotaClient quota_client(GetFileSystemContext());
InitializeOriginFiles(
quota_client, {
@ -442,13 +468,21 @@ TEST_F(FileSystemQuotaClientTest, GetStorageKeysForType) {
{true, "", 0, kDummyURL3, kFileSystemTypePersistent},
});
EXPECT_THAT(GetStorageKeysForType(quota_client, kTemporary),
testing::UnorderedElementsAre(
StorageKey::CreateFromStringForTesting(kDummyURL1),
StorageKey::CreateFromStringForTesting(kDummyURL2)));
if (persistent_quota_is_temporary_quota()) {
EXPECT_THAT(GetStorageKeysForType(quota_client, kTemporary),
testing::UnorderedElementsAre(
StorageKey::CreateFromStringForTesting(kDummyURL1),
StorageKey::CreateFromStringForTesting(kDummyURL2),
StorageKey::CreateFromStringForTesting(kDummyURL3)));
} else {
EXPECT_THAT(GetStorageKeysForType(quota_client, kTemporary),
testing::UnorderedElementsAre(
StorageKey::CreateFromStringForTesting(kDummyURL1),
StorageKey::CreateFromStringForTesting(kDummyURL2)));
}
}
TEST_F(FileSystemQuotaClientTest, GetStorageKeysForHost) {
TEST_P(FileSystemQuotaClientTest, GetStorageKeysForHost) {
FileSystemQuotaClient quota_client(GetFileSystemContext());
const char* kURL1 = "http://foo.com/";
const char* kURL2 = "https://foo.com/";
@ -464,14 +498,23 @@ TEST_F(FileSystemQuotaClientTest, GetStorageKeysForHost) {
{true, "", 0, kURL5, kFileSystemTypePersistent},
});
EXPECT_THAT(GetStorageKeysForHost(quota_client, kTemporary, "foo.com"),
testing::UnorderedElementsAre(
StorageKey::CreateFromStringForTesting(kURL1),
StorageKey::CreateFromStringForTesting(kURL2),
StorageKey::CreateFromStringForTesting(kURL3)));
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_F(FileSystemQuotaClientTest, DeleteOriginTest) {
TEST_P(FileSystemQuotaClientTest, DeleteOriginTest) {
FileSystemQuotaClient quota_client(GetFileSystemContext());
const std::vector<TestFile> kFiles = {
{true, "", 0, "http://foo.com/", kFileSystemTypeTemporary},
@ -499,6 +542,9 @@ TEST_F(FileSystemQuotaClientTest, DeleteOriginTest) {
const int64_t file_paths_cost_temporary_bar =
ComputeFilePathsCostForOriginAndType(kFiles, "http://bar.com/",
kFileSystemTypeTemporary);
const int64_t file_paths_cost_persistent_bar =
ComputeFilePathsCostForOriginAndType(kFiles, "http://bar.com/",
kFileSystemTypePersistent);
const int64_t file_paths_cost_temporary_bar_https =
ComputeFilePathsCostForOriginAndType(kFiles, "https://bar.com/",
kFileSystemTypeTemporary);
@ -510,29 +556,44 @@ TEST_F(FileSystemQuotaClientTest, DeleteOriginTest) {
base::RunLoop().RunUntilIdle();
EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, status());
DeleteStorageKeyData(&quota_client, "http://bar.com/", kPersistent);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, status());
if (!persistent_quota_is_temporary_quota()) {
DeleteStorageKeyData(&quota_client, "http://bar.com/", kPersistent);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, status());
}
DeleteStorageKeyData(&quota_client, "http://buz.com/", kTemporary);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, status());
EXPECT_EQ(0, GetStorageKeyUsage(quota_client, "http://foo.com/", kTemporary));
EXPECT_EQ(0,
GetStorageKeyUsage(quota_client, "http://bar.com/", kPersistent));
EXPECT_EQ(0, GetStorageKeyUsage(quota_client, "http://buz.com/", kTemporary));
EXPECT_EQ(2 + file_paths_cost_temporary_foo_https,
GetStorageKeyUsage(quota_client, "https://foo.com/", kTemporary));
EXPECT_EQ(4 + file_paths_cost_persistent_foo,
GetStorageKeyUsage(quota_client, "http://foo.com/", kPersistent));
EXPECT_EQ(8 + file_paths_cost_temporary_bar,
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));
EXPECT_EQ(32 + file_paths_cost_persistent_bar_https,
GetStorageKeyUsage(quota_client, "https://bar.com/", kPersistent));
EXPECT_EQ(64 + file_paths_cost_temporary_bar_https,
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));
if (!persistent_quota_is_temporary_quota()) {
EXPECT_EQ(0,
GetStorageKeyUsage(quota_client, "http://bar.com/", 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));
}
}
INSTANTIATE_TEST_SUITE_P(FileSystemQuotaClientTests,
FileSystemQuotaClientTest,
testing::Bool());
} // namespace storage

@ -4,13 +4,20 @@
#include "storage/browser/file_system/file_system_util.h"
#include "base/feature_list.h"
#include "storage/common/file_system/file_system_types.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
namespace storage {
blink::mojom::StorageType FileSystemTypeToQuotaStorageType(
FileSystemType type) {
if (base::FeatureList::IsEnabled(
blink::features::kPersistentQuotaIsTemporaryQuota) &&
(type == kFileSystemTypeTemporary || type == kFileSystemTypePersistent)) {
return blink::mojom::StorageType::kTemporary;
}
switch (type) {
case kFileSystemTypeTemporary:
return blink::mojom::StorageType::kTemporary;

@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "storage/browser/quota/quota_features.h"
#include "base/feature_list.h"
namespace storage {

@ -1028,5 +1028,8 @@ const base::Feature kDeprecateThirdPartyContextWebSQL{
const base::Feature kSyncLoadDataUrlFonts{"SyncLoadDataUrlFonts",
base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kPersistentQuotaIsTemporaryQuota{
"PersistentQuotaIsTemporaryQuota", base::FEATURE_DISABLED_BY_DEFAULT};
} // namespace features
} // namespace blink

@ -446,6 +446,10 @@ BLINK_COMMON_EXPORT extern const base::Feature
// Synchronously load web fonts inlined as data urls. See crbug.com/1236283
BLINK_COMMON_EXPORT extern const base::Feature kSyncLoadDataUrlFonts;
// Makes Persistent quota the same as Temporary quota.
BLINK_COMMON_EXPORT
extern const base::Feature kPersistentQuotaIsTemporaryQuota;
} // namespace features
} // namespace blink

@ -49116,6 +49116,7 @@ from previous Chrome versions.
<int value="-270261701" label="WebRtcEnableCaptureMultiChannelApm:disabled"/>
<int value="-269440655"
label="AutofillDownstreamCvcPromptUseGooglePayLogo:disabled"/>
<int value="-269227049" label="PersistentQuotaIsTemporaryQuota:enabled"/>
<int value="-268897347" label="DisableCameraFrameRotationAtSource:disabled"/>
<int value="-268549184"
label="AutofillSaveCreditCardUsesStrikeSystemV2:enabled"/>
@ -49726,6 +49727,7 @@ from previous Chrome versions.
<int value="246106068" label="HandwritingLegacyRecognition:disabled"/>
<int value="247200195" label="EnhancedProtectionPromoCard:enabled"/>
<int value="250855010" label="WebAssemblyBaseline:disabled"/>
<int value="251367892" label="PersistentQuotaIsTemporaryQuota:disabled"/>
<int value="254497185" label="VideoPlayerJsModules:enabled"/>
<int value="255375615" label="stop-non-timers-in-background:enabled"/>
<int value="258621334"