Skip to content

Commit

Permalink
StorageBuckets: Constructing path for QuotaClientType & BucketLocator
Browse files Browse the repository at this point in the history
This change adds a function in QuotaManagerProxy
that constructs file path for a bucket and QuotaClientType.
This will be the new path for StorageBucket/Storage Partitioned
data persisted to disk. The follow the following path structure.

{{storage_partition_path}}/WebStorage/{{bucket_id}}/
- CacheStorage/
- IndexedDB/
- FileSystem/
- ScriptCache/

Design discussion docs:
FilePath Discussion: https://docs.google.com/document/d/1G4m8ImZlIGNrpn_IyaWoLR_RLDMe3py8ifWaEyH3Pec/edit?usp=sharing
FilePath Design: https://docs.google.com/document/d/1D9Euw9ZgMw2YADFcuOmGj1QAT3e-4V_K6y8MMHxofEQ/edit?usp=sharing&resourcekey=0-MQc2XFLLf7Nl3cWdTY3qtg

Bug: 1305365
Change-Id: Iddfcc1d803c1c72117992bf5d0583e77fdf91037
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3537328
Reviewed-by: Marijn Kruisselbrink <mek@chromium.org>
Commit-Queue: Ayu Ishii <ayui@chromium.org>
Cr-Commit-Position: refs/heads/main@{#983981}
  • Loading branch information
ayuishii authored and Chromium LUCI CQ committed Mar 22, 2022
1 parent 1a480de commit b9f36ed
Show file tree
Hide file tree
Showing 12 changed files with 205 additions and 8 deletions.
18 changes: 18 additions & 0 deletions components/services/storage/public/cpp/constants.cc
Expand Up @@ -28,4 +28,22 @@ const base::FilePath::CharType kServiceWorkerDirectory[] =
const base::FilePath::CharType kMediaLicenseDatabaseFileName[] =
FILE_PATH_LITERAL("Media Licenses.db");

// The path where File System data is persisted on disk for partitioned storage.
const base::FilePath::CharType kFileSystemDirectory[] =
FILE_PATH_LITERAL("FileSystem");

// The path where IndexedDB data is persisted on disk for partitioned storage.
const base::FilePath::CharType kIndexedDbDirectory[] =
FILE_PATH_LITERAL("IndexedDB");

// The path where CacheStorage data is persisted on disk for partitioned
// storage.
const base::FilePath::CharType kCacheStorageDirectory[] =
FILE_PATH_LITERAL("CacheStorage");

// The path where ServiceWorker script data is persisted on disk for partitioned
// storage.
const base::FilePath::CharType kScriptCacheDirectory[] =
FILE_PATH_LITERAL("ScriptCache");

} // namespace storage
12 changes: 12 additions & 0 deletions components/services/storage/public/cpp/constants.h
Expand Up @@ -25,6 +25,18 @@ extern const base::FilePath::CharType kServiceWorkerDirectory[];
COMPONENT_EXPORT(STORAGE_SERVICE_PUBLIC)
extern const base::FilePath::CharType kMediaLicenseDatabaseFileName[];

COMPONENT_EXPORT(STORAGE_SERVICE_PUBLIC)
extern const base::FilePath::CharType kFileSystemDirectory[];

COMPONENT_EXPORT(STORAGE_SERVICE_PUBLIC)
extern const base::FilePath::CharType kIndexedDbDirectory[];

COMPONENT_EXPORT(STORAGE_SERVICE_PUBLIC)
extern const base::FilePath::CharType kCacheStorageDirectory[];

COMPONENT_EXPORT(STORAGE_SERVICE_PUBLIC)
extern const base::FilePath::CharType kScriptCacheDirectory[];

} // namespace storage

#endif // COMPONENTS_SERVICES_STORAGE_PUBLIC_CPP_CONSTANTS_H_
1 change: 1 addition & 0 deletions storage/browser/BUILD.gn
Expand Up @@ -327,6 +327,7 @@ source_set("unittests") {
"file_system/transient_file_util_unittest.cc",
"quota/quota_database_migrations_unittest.cc",
"quota/quota_database_unittest.cc",
"quota/quota_manager_proxy_unittest.cc",
"quota/quota_manager_unittest.cc",
"quota/quota_settings_unittest.cc",
"quota/quota_temporary_storage_evictor_unittest.cc",
Expand Down
3 changes: 2 additions & 1 deletion storage/browser/database/database_tracker_unittest.cc
Expand Up @@ -103,7 +103,8 @@ class TestQuotaManagerProxy : public QuotaManagerProxy {
TestQuotaManagerProxy()
: QuotaManagerProxy(
/*quota_manager_impl=*/nullptr,
base::SequencedTaskRunnerHandle::Get()) {}
base::SequencedTaskRunnerHandle::Get(),
/*profile_path=*/base::FilePath()) {}

void RegisterClient(
mojo::PendingRemote<mojom::QuotaClient> client,
Expand Down
Expand Up @@ -44,7 +44,9 @@ bool DidReserveQuota(bool accepted,
class MockQuotaManagerProxy : public QuotaManagerProxy {
public:
MockQuotaManagerProxy()
: QuotaManagerProxy(nullptr, base::ThreadTaskRunnerHandle::Get()),
: QuotaManagerProxy(/*quota_manager_impl=*/nullptr,
base::ThreadTaskRunnerHandle::Get(),
/*profile_path=*/base::FilePath()),
storage_modified_count_(0),
usage_(0),
quota_(0) {}
Expand Down
4 changes: 3 additions & 1 deletion storage/browser/quota/quota_manager_impl.cc
Expand Up @@ -1190,7 +1190,9 @@ QuotaManagerImpl::QuotaManagerImpl(
: RefCountedDeleteOnSequence<QuotaManagerImpl>(io_thread),
is_incognito_(is_incognito),
profile_path_(profile_path),
proxy_(base::MakeRefCounted<QuotaManagerProxy>(this, io_thread)),
proxy_(base::MakeRefCounted<QuotaManagerProxy>(this,
io_thread,
profile_path)),
io_thread_(std::move(io_thread)),
db_runner_(base::ThreadPool::CreateSequencedTaskRunner(
{base::MayBlock(), base::TaskPriority::USER_VISIBLE,
Expand Down
35 changes: 33 additions & 2 deletions storage/browser/quota/quota_manager_proxy.cc
Expand Up @@ -15,9 +15,12 @@
#include "base/location.h"
#include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h"
#include "base/strings/string_number_conversions.h"
#include "base/task/sequenced_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/services/storage/public/cpp/buckets/bucket_locator.h"
#include "components/services/storage/public/cpp/constants.h"
#include "components/services/storage/public/mojom/quota_client.mojom.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "storage/browser/quota/quota_client_type.h"
Expand Down Expand Up @@ -65,15 +68,43 @@ void DidGetStatus(

QuotaManagerProxy::QuotaManagerProxy(
QuotaManagerImpl* quota_manager_impl,
scoped_refptr<base::SequencedTaskRunner> quota_manager_impl_task_runner)
scoped_refptr<base::SequencedTaskRunner> quota_manager_impl_task_runner,
const base::FilePath& profile_path)
: quota_manager_impl_(quota_manager_impl),
quota_manager_impl_task_runner_(
std::move(quota_manager_impl_task_runner)) {
std::move(quota_manager_impl_task_runner)),
profile_path_(profile_path) {
DCHECK(quota_manager_impl_task_runner_.get());

DETACH_FROM_SEQUENCE(quota_manager_impl_sequence_checker_);
}

base::FilePath QuotaManagerProxy::GetBucketPath(const BucketLocator& bucket) {
return profile_path_.Append(kWebStorageDirectory)
.AppendASCII(base::NumberToString(bucket.id.value()));
}

base::FilePath QuotaManagerProxy::GetClientBucketPath(
const BucketLocator& bucket,
QuotaClientType client_type) {
base::FilePath bucket_directory = GetBucketPath(bucket);

switch (client_type) {
case QuotaClientType::kFileSystem:
return bucket_directory.Append(kFileSystemDirectory);
case QuotaClientType::kIndexedDatabase:
return bucket_directory.Append(kIndexedDbDirectory);
case QuotaClientType::kBackgroundFetch:
case QuotaClientType::kServiceWorkerCache:
return bucket_directory.Append(kCacheStorageDirectory);
case QuotaClientType::kServiceWorker:
return bucket_directory.Append(kScriptCacheDirectory);
default:
NOTREACHED() << "Unsupported QuotaClientType";
return base::FilePath();
}
}

void QuotaManagerProxy::RegisterClient(
mojo::PendingRemote<mojom::QuotaClient> client,
QuotaClientType client_type,
Expand Down
15 changes: 14 additions & 1 deletion storage/browser/quota/quota_manager_proxy.h
Expand Up @@ -38,6 +38,7 @@ class SequencedTaskRunner;

namespace storage {

struct BucketLocator;
class QuotaOverrideHandle;

// Thread-safe proxy for QuotaManagerImpl.
Expand All @@ -57,7 +58,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerProxy
// `quota_manager_impl` isn't a base::WeakPtr<QuotaManagerImpl>.
QuotaManagerProxy(
QuotaManagerImpl* quota_manager_impl,
scoped_refptr<base::SequencedTaskRunner> quota_manager_impl_task_runner);
scoped_refptr<base::SequencedTaskRunner> quota_manager_impl_task_runner,
const base::FilePath& profile_path);

QuotaManagerProxy(const QuotaManagerProxy&) = delete;
QuotaManagerProxy& operator=(const QuotaManagerProxy&) = delete;
Expand All @@ -70,6 +72,15 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerProxy
virtual void BindInternalsHandler(
mojo::PendingReceiver<mojom::QuotaInternalsHandler> receiver);

// Constructs path where `bucket` data is persisted to disk for partitioned
// storage.
base::FilePath GetBucketPath(const BucketLocator& bucket);

// Constructs path where `bucket` and `client_type` data is persisted to disk
// for partitioned storage.
base::FilePath GetClientBucketPath(const BucketLocator& bucket,
QuotaClientType client_type);

// 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
Expand Down Expand Up @@ -240,6 +251,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerProxy
// to the same object), and the object it points to is thread-safe.
const scoped_refptr<base::SequencedTaskRunner>
quota_manager_impl_task_runner_;

const base::FilePath profile_path_;
};

} // namespace storage
Expand Down
109 changes: 109 additions & 0 deletions storage/browser/quota/quota_manager_proxy_unittest.cc
@@ -0,0 +1,109 @@
// 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/quota_manager_proxy.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/scoped_refptr.h"
#include "base/strings/string_number_conversions.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/constants.h"
#include "components/services/storage/public/cpp/quota_error_or.h"
#include "storage/browser/quota/quota_client_type.h"
#include "storage/browser/quota/quota_manager_impl.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"

namespace storage {

class QuotaManagerProxyTest : public testing::Test {
public:
void SetUp() override {
EXPECT_TRUE(profile_path_.CreateUniqueTempDir());
quota_manager_ = base::MakeRefCounted<QuotaManagerImpl>(
/*is_incognito*/ false, profile_path_.GetPath(),
base::ThreadTaskRunnerHandle::Get().get(),
/*quota_change_callback=*/base::DoNothing(),
/*storage_policy=*/nullptr, GetQuotaSettingsFunc());
quota_manager_proxy_ = base::MakeRefCounted<QuotaManagerProxy>(
quota_manager_.get(), base::ThreadTaskRunnerHandle::Get(),
profile_path_.GetPath());
}

void TearDown() override {
quota_manager_proxy_ = nullptr;
quota_manager_ = nullptr;
}

protected:
base::ScopedTempDir profile_path_;
scoped_refptr<QuotaManagerImpl> quota_manager_;
scoped_refptr<QuotaManagerProxy> quota_manager_proxy_;

base::test::TaskEnvironment task_environment_;
};

TEST_F(QuotaManagerProxyTest, GetBucketPath) {
base::test::TestFuture<storage::QuotaErrorOr<storage::BucketInfo>> future;
quota_manager_proxy_->GetOrCreateBucket(
blink::StorageKey::CreateFromStringForTesting("http://example.com"),
"draft_bucket", base::ThreadTaskRunnerHandle::Get(),
future.GetCallback());
auto bucket = future.Take();
EXPECT_TRUE(bucket.ok());

base::FilePath expected_path =
profile_path_.GetPath()
.AppendASCII("WebStorage")
.AppendASCII(base::NumberToString(bucket->id.value()));
EXPECT_EQ(quota_manager_proxy_->GetBucketPath(bucket->ToBucketLocator()),
expected_path);
}

TEST_F(QuotaManagerProxyTest, GetClientBucketPath) {
base::test::TestFuture<storage::QuotaErrorOr<storage::BucketInfo>> future;
quota_manager_proxy_->GetOrCreateBucket(
blink::StorageKey::CreateFromStringForTesting("http://example.com"),
"draft_bucket", base::ThreadTaskRunnerHandle::Get(),
future.GetCallback());
auto bucket = future.Take();
EXPECT_TRUE(bucket.ok());

base::FilePath bucket_path =
profile_path_.GetPath()
.AppendASCII("WebStorage")
.AppendASCII(base::NumberToString(bucket->id.value()));

// FileSystem
base::FilePath expected_path = bucket_path.AppendASCII("FileSystem");
EXPECT_EQ(quota_manager_proxy_->GetClientBucketPath(
bucket->ToBucketLocator(), QuotaClientType::kFileSystem),
expected_path);

// IndexedDb
expected_path = bucket_path.AppendASCII("IndexedDB");
EXPECT_EQ(quota_manager_proxy_->GetClientBucketPath(
bucket->ToBucketLocator(), QuotaClientType::kIndexedDatabase),
expected_path);

// BackgroundFetch/CacheStorage
expected_path = bucket_path.AppendASCII("CacheStorage");
EXPECT_EQ(quota_manager_proxy_->GetClientBucketPath(
bucket->ToBucketLocator(), QuotaClientType::kBackgroundFetch),
expected_path);
EXPECT_EQ(
quota_manager_proxy_->GetClientBucketPath(
bucket->ToBucketLocator(), QuotaClientType::kServiceWorkerCache),
expected_path);

// ServiceWorker
expected_path = bucket_path.AppendASCII("ScriptCache");
EXPECT_EQ(quota_manager_proxy_->GetClientBucketPath(
bucket->ToBucketLocator(), QuotaClientType::kServiceWorker),
expected_path);
}

} // namespace storage
3 changes: 2 additions & 1 deletion storage/browser/test/mock_quota_manager.cc
Expand Up @@ -50,7 +50,8 @@ MockQuotaManager::MockQuotaManager(
std::move(io_thread),
/*quota_change_callback=*/base::DoNothing(),
std::move(special_storage_policy),
GetQuotaSettingsFunc()) {
GetQuotaSettingsFunc()),
profile_path_(profile_path) {
QuotaManagerImpl::SetEvictionDisabledForTesting(false);
}

Expand Down
4 changes: 4 additions & 0 deletions storage/browser/test/mock_quota_manager.h
Expand Up @@ -197,6 +197,10 @@ class MockQuotaManager : public QuotaManager {
void DidDeleteBucketData(StatusCallback callback,
blink::mojom::QuotaStatusCode status);

base::FilePath profile_path() { return profile_path_; }

const base::FilePath profile_path_;

BucketId::Generator bucket_id_generator_;

// The list of stored buckets that have been added via AddBucket.
Expand Down
5 changes: 4 additions & 1 deletion storage/browser/test/mock_quota_manager_proxy.cc
Expand Up @@ -16,7 +16,10 @@ namespace storage {
MockQuotaManagerProxy::MockQuotaManagerProxy(
MockQuotaManager* quota_manager,
scoped_refptr<base::SequencedTaskRunner> quota_manager_task_runner)
: QuotaManagerProxy(quota_manager, std::move(quota_manager_task_runner)),
: QuotaManagerProxy(
quota_manager,
std::move(quota_manager_task_runner),
quota_manager ? quota_manager->profile_path() : base::FilePath()),
mock_quota_manager_(quota_manager),
storage_accessed_count_(0),
storage_modified_count_(0),
Expand Down

0 comments on commit b9f36ed

Please sign in to comment.