0

Quota: Mojofy WebSQL's QuotaClient.

Bug: 1163048
Change-Id: Ifda6373f4550c7d7083b111c10e19376f841f936
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2628489
Reviewed-by: enne <enne@chromium.org>
Commit-Queue: Victor Costan <pwnall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#889504}
This commit is contained in:
Victor Costan
2021-06-04 23:05:34 +00:00
committed by Chromium LUCI CQ
parent 6b2740923f
commit 93ce33c491
7 changed files with 127 additions and 142 deletions

@ -234,6 +234,7 @@ component("browser") {
"//base/third_party/dynamic_annotations", "//base/third_party/dynamic_annotations",
"//build:chromeos_buildflags", "//build:chromeos_buildflags",
"//components/services/storage/public/cpp", "//components/services/storage/public/cpp",
"//components/services/storage/public/cpp/filesystem",
"//mojo/public/cpp/bindings", "//mojo/public/cpp/bindings",
"//net", "//net",
"//services/network:network_service", "//services/network:network_service",

@ -31,80 +31,13 @@ using blink::mojom::StorageType;
namespace storage { namespace storage {
namespace { DatabaseQuotaClient::DatabaseQuotaClient(DatabaseTracker& db_tracker)
: db_tracker_(db_tracker) {
int64_t GetOriginUsageOnDBThread(DatabaseTracker* db_tracker,
const url::Origin& origin) {
OriginInfo info;
if (db_tracker->GetOriginInfo(GetIdentifierFromOrigin(origin), &info))
return info.TotalSize();
return 0;
}
std::vector<url::Origin> GetOriginsOnDBThread(DatabaseTracker* db_tracker) {
std::vector<url::Origin> all_origins;
std::vector<std::string> origin_identifiers;
if (db_tracker->GetAllOriginIdentifiers(&origin_identifiers)) {
all_origins.reserve(origin_identifiers.size());
for (const auto& identifier : origin_identifiers) {
all_origins.push_back(GetOriginFromIdentifier(identifier));
}
}
return all_origins;
}
std::vector<url::Origin> GetOriginsForHostOnDBThread(
DatabaseTracker* db_tracker,
const std::string& host) {
std::vector<url::Origin> host_origins;
// In the vast majority of cases, this vector will end up with exactly one
// origin. The origin will be https://host or http://host.
host_origins.reserve(1);
std::vector<std::string> origin_identifiers;
if (db_tracker->GetAllOriginIdentifiers(&origin_identifiers)) {
for (const auto& identifier : origin_identifiers) {
url::Origin origin = GetOriginFromIdentifier(identifier);
if (host == origin.host())
host_origins.push_back(std::move(origin));
}
}
return host_origins;
}
void DidDeleteOriginData(
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
QuotaClient::DeleteOriginDataCallback callback,
int result) {
blink::mojom::QuotaStatusCode status;
if (result == net::OK)
status = blink::mojom::QuotaStatusCode::kOk;
else
status = blink::mojom::QuotaStatusCode::kUnknown;
original_task_runner->PostTask(FROM_HERE,
base::BindOnce(std::move(callback), status));
}
} // namespace
DatabaseQuotaClient::DatabaseQuotaClient(
scoped_refptr<DatabaseTracker> db_tracker)
: db_tracker_(std::move(db_tracker)) {
DCHECK(db_tracker_.get());
DETACH_FROM_SEQUENCE(sequence_checker_); DETACH_FROM_SEQUENCE(sequence_checker_);
} }
DatabaseQuotaClient::~DatabaseQuotaClient() { DatabaseQuotaClient::~DatabaseQuotaClient() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!db_tracker_->task_runner()->RunsTasksInCurrentSequence()) {
db_tracker_->task_runner()->ReleaseSoon(FROM_HERE, std::move(db_tracker_));
}
}
void DatabaseQuotaClient::OnQuotaManagerDestroyed() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
} }
void DatabaseQuotaClient::GetOriginUsage(const url::Origin& origin, void DatabaseQuotaClient::GetOriginUsage(const url::Origin& origin,
@ -114,11 +47,12 @@ void DatabaseQuotaClient::GetOriginUsage(const url::Origin& origin,
DCHECK(!callback.is_null()); DCHECK(!callback.is_null());
DCHECK_EQ(type, StorageType::kTemporary); DCHECK_EQ(type, StorageType::kTemporary);
db_tracker_->task_runner()->PostTaskAndReplyWithResult( OriginInfo info;
FROM_HERE, if (db_tracker_.GetOriginInfo(GetIdentifierFromOrigin(origin), &info)) {
base::BindOnce(&GetOriginUsageOnDBThread, base::RetainedRef(db_tracker_), std::move(callback).Run(info.TotalSize());
origin), } else {
std::move(callback)); std::move(callback).Run(0);
}
} }
void DatabaseQuotaClient::GetOriginsForType( void DatabaseQuotaClient::GetOriginsForType(
@ -128,10 +62,14 @@ void DatabaseQuotaClient::GetOriginsForType(
DCHECK(!callback.is_null()); DCHECK(!callback.is_null());
DCHECK_EQ(type, StorageType::kTemporary); DCHECK_EQ(type, StorageType::kTemporary);
db_tracker_->task_runner()->PostTaskAndReplyWithResult( std::vector<url::Origin> all_origins;
FROM_HERE, std::vector<std::string> origin_identifiers;
base::BindOnce(&GetOriginsOnDBThread, base::RetainedRef(db_tracker_)), if (db_tracker_.GetAllOriginIdentifiers(&origin_identifiers)) {
std::move(callback)); all_origins.reserve(origin_identifiers.size());
for (const auto& identifier : origin_identifiers)
all_origins.push_back(GetOriginFromIdentifier(identifier));
}
std::move(callback).Run(all_origins);
} }
void DatabaseQuotaClient::GetOriginsForHost( void DatabaseQuotaClient::GetOriginsForHost(
@ -142,11 +80,20 @@ void DatabaseQuotaClient::GetOriginsForHost(
DCHECK(!callback.is_null()); DCHECK(!callback.is_null());
DCHECK_EQ(type, StorageType::kTemporary); DCHECK_EQ(type, StorageType::kTemporary);
db_tracker_->task_runner()->PostTaskAndReplyWithResult( std::vector<url::Origin> host_origins;
FROM_HERE, // In the vast majority of cases, this vector will end up with exactly one
base::BindOnce(&GetOriginsForHostOnDBThread, // origin. The origin will be https://host or http://host.
base::RetainedRef(db_tracker_), host), host_origins.reserve(1);
std::move(callback));
std::vector<std::string> origin_identifiers;
if (db_tracker_.GetAllOriginIdentifiers(&origin_identifiers)) {
for (const auto& identifier : origin_identifiers) {
url::Origin origin = GetOriginFromIdentifier(identifier);
if (host == origin.host())
host_origins.push_back(std::move(origin));
}
}
std::move(callback).Run(host_origins);
} }
void DatabaseQuotaClient::DeleteOriginData(const url::Origin& origin, void DatabaseQuotaClient::DeleteOriginData(const url::Origin& origin,
@ -156,12 +103,15 @@ void DatabaseQuotaClient::DeleteOriginData(const url::Origin& origin,
DCHECK(!callback.is_null()); DCHECK(!callback.is_null());
DCHECK_EQ(type, StorageType::kTemporary); DCHECK_EQ(type, StorageType::kTemporary);
db_tracker_->task_runner()->PostTask( db_tracker_.DeleteDataForOrigin(
FROM_HERE, origin, base::BindOnce(
base::BindOnce(&DatabaseTracker::DeleteDataForOrigin, db_tracker_, origin, [](DeleteOriginDataCallback callback, int result) {
base::BindOnce(&DidDeleteOriginData, std::move(callback).Run(
base::SequencedTaskRunnerHandle::Get(), (result == net::OK)
std::move(callback)))); ? blink::mojom::QuotaStatusCode::kOk
: blink::mojom::QuotaStatusCode::kUnknown);
},
std::move(callback)));
} }
void DatabaseQuotaClient::PerformStorageCleanup( void DatabaseQuotaClient::PerformStorageCleanup(

@ -14,7 +14,7 @@
#include "base/sequence_checker.h" #include "base/sequence_checker.h"
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "base/thread_annotations.h" #include "base/thread_annotations.h"
#include "storage/browser/quota/quota_client.h" #include "components/services/storage/public/mojom/quota_client.mojom.h"
#include "storage/browser/quota/quota_client_type.h" #include "storage/browser/quota/quota_client_type.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
#include "url/origin.h" #include "url/origin.h"
@ -27,15 +27,16 @@ class DatabaseTracker;
// //
// This interface is used on the IO thread by the quota manager. // This interface is used on the IO thread by the quota manager.
class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseQuotaClient class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseQuotaClient
: public QuotaClient { : public mojom::QuotaClient {
public: public:
explicit DatabaseQuotaClient(scoped_refptr<DatabaseTracker> tracker); explicit DatabaseQuotaClient(DatabaseTracker& tracker);
DatabaseQuotaClient(const DatabaseQuotaClient&) = delete; DatabaseQuotaClient(const DatabaseQuotaClient&) = delete;
DatabaseQuotaClient& operator=(const DatabaseQuotaClient&) = delete; DatabaseQuotaClient& operator=(const DatabaseQuotaClient&) = delete;
~DatabaseQuotaClient() override;
// QuotaClient method overrides // QuotaClient method overrides
void OnQuotaManagerDestroyed() override;
void GetOriginUsage(const url::Origin& origin, void GetOriginUsage(const url::Origin& origin,
blink::mojom::StorageType type, blink::mojom::StorageType type,
GetOriginUsageCallback callback) override; GetOriginUsageCallback callback) override;
@ -51,15 +52,10 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseQuotaClient
PerformStorageCleanupCallback callback) override; PerformStorageCleanupCallback callback) override;
private: private:
~DatabaseQuotaClient() override;
SEQUENCE_CHECKER(sequence_checker_); SEQUENCE_CHECKER(sequence_checker_);
// The scoped_refptr is only be dereferenced on the QuotaClient's sequence. // Reference use is safe here because the DatabaseTracker owns this.
// However, the DatabaseTracker it points to must only be used on the database DatabaseTracker& db_tracker_ GUARDED_BY_CONTEXT(sequence_checker_);
// sequence.
scoped_refptr<DatabaseTracker> db_tracker_
GUARDED_BY_CONTEXT(sequence_checker_);
}; };
} // namespace storage } // namespace storage

@ -21,6 +21,7 @@
#include "base/test/bind.h" #include "base/test/bind.h"
#include "base/test/task_environment.h" #include "base/test/task_environment.h"
#include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/sequenced_task_runner_handle.h"
#include "components/services/storage/public/mojom/quota_client.mojom.h"
#include "net/base/completion_once_callback.h" #include "net/base/completion_once_callback.h"
#include "net/base/net_errors.h" #include "net/base/net_errors.h"
#include "storage/browser/database/database_quota_client.h" #include "storage/browser/database/database_quota_client.h"
@ -147,7 +148,7 @@ class DatabaseQuotaClientTest : public testing::Test {
run_loop.Run(); run_loop.Run();
} }
static int64_t GetOriginUsage(QuotaClient& client, static int64_t GetOriginUsage(mojom::QuotaClient& client,
const url::Origin& origin, const url::Origin& origin,
blink::mojom::StorageType type) { blink::mojom::StorageType type) {
int result = -1; int result = -1;
@ -163,7 +164,7 @@ class DatabaseQuotaClientTest : public testing::Test {
} }
static std::vector<url::Origin> GetOriginsForType( static std::vector<url::Origin> GetOriginsForType(
QuotaClient& client, mojom::QuotaClient& client,
blink::mojom::StorageType type) { blink::mojom::StorageType type) {
std::vector<url::Origin> result; std::vector<url::Origin> result;
base::RunLoop loop; base::RunLoop loop;
@ -178,7 +179,7 @@ class DatabaseQuotaClientTest : public testing::Test {
} }
static std::vector<url::Origin> GetOriginsForHost( static std::vector<url::Origin> GetOriginsForHost(
QuotaClient& client, mojom::QuotaClient& client,
blink::mojom::StorageType type, blink::mojom::StorageType type,
const std::string& host) { const std::string& host) {
std::vector<url::Origin> result; std::vector<url::Origin> result;
@ -194,7 +195,7 @@ class DatabaseQuotaClientTest : public testing::Test {
} }
static blink::mojom::QuotaStatusCode DeleteOriginData( static blink::mojom::QuotaStatusCode DeleteOriginData(
QuotaClient& client, mojom::QuotaClient& client,
blink::mojom::StorageType type, blink::mojom::StorageType type,
const url::Origin& origin) { const url::Origin& origin) {
blink::mojom::QuotaStatusCode result = blink::mojom::QuotaStatusCode result =
@ -216,62 +217,62 @@ class DatabaseQuotaClientTest : public testing::Test {
}; };
TEST_F(DatabaseQuotaClientTest, GetOriginUsage) { TEST_F(DatabaseQuotaClientTest, GetOriginUsage) {
auto client = base::MakeRefCounted<DatabaseQuotaClient>(mock_tracker_); DatabaseQuotaClient client(*mock_tracker_);
EXPECT_EQ(0, GetOriginUsage(*client, kOriginA, kTemp)); EXPECT_EQ(0, GetOriginUsage(client, kOriginA, kTemp));
mock_tracker_->AddMockDatabase(kOriginA, "fooDB", 1000); mock_tracker_->AddMockDatabase(kOriginA, "fooDB", 1000);
EXPECT_EQ(1000, GetOriginUsage(*client, kOriginA, kTemp)); EXPECT_EQ(1000, GetOriginUsage(client, kOriginA, kTemp));
EXPECT_EQ(0, GetOriginUsage(*client, kOriginB, kTemp)); EXPECT_EQ(0, GetOriginUsage(client, kOriginB, kTemp));
} }
TEST_F(DatabaseQuotaClientTest, GetOriginsForHost) { TEST_F(DatabaseQuotaClientTest, GetOriginsForHost) {
auto client = base::MakeRefCounted<DatabaseQuotaClient>(mock_tracker_); DatabaseQuotaClient client(*mock_tracker_);
EXPECT_EQ(kOriginA.host(), kOriginB.host()); EXPECT_EQ(kOriginA.host(), kOriginB.host());
EXPECT_NE(kOriginA.host(), kOriginOther.host()); EXPECT_NE(kOriginA.host(), kOriginOther.host());
std::vector<url::Origin> origins = std::vector<url::Origin> origins =
GetOriginsForHost(*client, kTemp, kOriginA.host()); GetOriginsForHost(client, kTemp, kOriginA.host());
EXPECT_TRUE(origins.empty()); EXPECT_TRUE(origins.empty());
mock_tracker_->AddMockDatabase(kOriginA, "fooDB", 1000); mock_tracker_->AddMockDatabase(kOriginA, "fooDB", 1000);
origins = GetOriginsForHost(*client, kTemp, kOriginA.host()); origins = GetOriginsForHost(client, kTemp, kOriginA.host());
EXPECT_EQ(origins.size(), 1ul); EXPECT_EQ(origins.size(), 1ul);
EXPECT_THAT(origins, testing::Contains(kOriginA)); EXPECT_THAT(origins, testing::Contains(kOriginA));
mock_tracker_->AddMockDatabase(kOriginB, "barDB", 1000); mock_tracker_->AddMockDatabase(kOriginB, "barDB", 1000);
origins = GetOriginsForHost(*client, kTemp, kOriginA.host()); origins = GetOriginsForHost(client, kTemp, kOriginA.host());
EXPECT_EQ(origins.size(), 2ul); EXPECT_EQ(origins.size(), 2ul);
EXPECT_THAT(origins, testing::Contains(kOriginA)); EXPECT_THAT(origins, testing::Contains(kOriginA));
EXPECT_THAT(origins, testing::Contains(kOriginB)); EXPECT_THAT(origins, testing::Contains(kOriginB));
EXPECT_TRUE(GetOriginsForHost(*client, kTemp, kOriginOther.host()).empty()); EXPECT_TRUE(GetOriginsForHost(client, kTemp, kOriginOther.host()).empty());
} }
TEST_F(DatabaseQuotaClientTest, GetOriginsForType) { TEST_F(DatabaseQuotaClientTest, GetOriginsForType) {
auto client = base::MakeRefCounted<DatabaseQuotaClient>(mock_tracker_); DatabaseQuotaClient client(*mock_tracker_);
EXPECT_TRUE(GetOriginsForType(*client, kTemp).empty()); EXPECT_TRUE(GetOriginsForType(client, kTemp).empty());
mock_tracker_->AddMockDatabase(kOriginA, "fooDB", 1000); mock_tracker_->AddMockDatabase(kOriginA, "fooDB", 1000);
std::vector<url::Origin> origins = GetOriginsForType(*client, kTemp); std::vector<url::Origin> origins = GetOriginsForType(client, kTemp);
EXPECT_EQ(origins.size(), 1ul); EXPECT_EQ(origins.size(), 1ul);
EXPECT_THAT(origins, testing::Contains(kOriginA)); EXPECT_THAT(origins, testing::Contains(kOriginA));
} }
TEST_F(DatabaseQuotaClientTest, DeleteOriginData) { TEST_F(DatabaseQuotaClientTest, DeleteOriginData) {
auto client = base::MakeRefCounted<DatabaseQuotaClient>(mock_tracker_); DatabaseQuotaClient client(*mock_tracker_);
mock_tracker_->set_async_delete(false); mock_tracker_->set_async_delete(false);
EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk,
DeleteOriginData(*client, kTemp, kOriginA)); DeleteOriginData(client, kTemp, kOriginA));
EXPECT_EQ(1, mock_tracker_->delete_called_count()); EXPECT_EQ(1, mock_tracker_->delete_called_count());
mock_tracker_->set_async_delete(true); mock_tracker_->set_async_delete(true);
EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk,
DeleteOriginData(*client, kTemp, kOriginA)); DeleteOriginData(client, kTemp, kOriginA));
EXPECT_EQ(2, mock_tracker_->delete_called_count()); EXPECT_EQ(2, mock_tracker_->delete_called_count());
} }

@ -17,6 +17,7 @@
#include "base/files/file_enumerator.h" #include "base/files/file_enumerator.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/location.h"
#include "base/memory/scoped_refptr.h" #include "base/memory/scoped_refptr.h"
#include "base/metrics/user_metrics.h" #include "base/metrics/user_metrics.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
@ -25,6 +26,10 @@
#include "base/task/thread_pool.h" #include "base/task/thread_pool.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "base/types/pass_key.h" #include "base/types/pass_key.h"
#include "components/services/storage/public/cpp/quota_client_callback_wrapper.h"
#include "components/services/storage/public/mojom/quota_client.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/net_errors.h" #include "net/base/net_errors.h"
#include "sql/database.h" #include "sql/database.h"
#include "sql/meta_table.h" #include "sql/meta_table.h"
@ -112,22 +117,44 @@ DatabaseTracker::DatabaseTracker(
quota_manager_proxy_(std::move(quota_manager_proxy)), quota_manager_proxy_(std::move(quota_manager_proxy)),
task_runner_(base::ThreadPool::CreateSequencedTaskRunner( task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
{base::MayBlock(), base::TaskPriority::USER_VISIBLE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) {} base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})),
quota_client_(std::make_unique<DatabaseQuotaClient>(*this)),
quota_client_wrapper_(
std::make_unique<QuotaClientCallbackWrapper>(quota_client_.get())),
quota_client_receiver_(quota_client_wrapper_.get()) {}
DatabaseTracker::~DatabaseTracker() { DatabaseTracker::~DatabaseTracker() {
// base::RefCountedThreadSafe inserts the appropriate barriers to ensure // base::RefCountedThreadSafe inserts the appropriate barriers to ensure
// member access in the destructor does not introduce data races. // member access in the destructor does not introduce data races.
DCHECK(dbs_to_be_deleted_.empty()); DCHECK(dbs_to_be_deleted_.empty());
DCHECK(deletion_callbacks_.empty()); DCHECK(deletion_callbacks_.empty());
DCHECK(!quota_client_);
DCHECK(!quota_client_wrapper_);
DCHECK(!quota_client_receiver_.is_bound());
} }
void DatabaseTracker::RegisterQuotaClient() { void DatabaseTracker::RegisterQuotaClient() {
if (quota_manager_proxy_) { if (!quota_manager_proxy_)
// TODO(crbug.com/1163048): Use mojo and switch to RegisterClient(). return;
quota_manager_proxy_->RegisterLegacyClient(
base::MakeRefCounted<DatabaseQuotaClient>(this), // QuotaManagerProxy::RegisterClient() must be called synchronously during
QuotaClientType::kDatabase, {blink::mojom::StorageType::kTemporary}); // DatabaseTracker creation until crbug.com/1182630 is fixed.
} mojo::PendingRemote<storage::mojom::QuotaClient> quota_client_remote;
mojo::PendingReceiver<storage::mojom::QuotaClient> quota_client_receiver =
quota_client_remote.InitWithNewPipeAndPassReceiver();
quota_manager_proxy_->RegisterClient(std::move(quota_client_remote),
storage::QuotaClientType::kDatabase,
{blink::mojom::StorageType::kTemporary});
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
[](scoped_refptr<DatabaseTracker> self,
mojo::PendingReceiver<storage::mojom::QuotaClient> receiver) {
self->quota_client_receiver_.Bind(std::move(receiver));
},
base::RetainedRef(this), std::move(quota_client_receiver)));
} }
void DatabaseTracker::DatabaseOpened(const std::string& origin_identifier, void DatabaseTracker::DatabaseOpened(const std::string& origin_identifier,
@ -924,6 +951,13 @@ void DatabaseTracker::Shutdown() {
return; return;
} }
shutting_down_ = true; shutting_down_ = true;
// The mojo receiver must be reset before the instance it calls into is
// destroyed.
quota_client_receiver_.reset();
quota_client_wrapper_.reset();
quota_client_.reset();
if (is_incognito_) if (is_incognito_)
DeleteIncognitoDBDirectory(); DeleteIncognitoDBDirectory();
else if (!force_keep_session_state_) else if (!force_keep_session_state_)

@ -25,6 +25,8 @@
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "base/types/pass_key.h" #include "base/types/pass_key.h"
#include "components/services/storage/public/mojom/quota_client.mojom.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "net/base/completion_once_callback.h" #include "net/base/completion_once_callback.h"
#include "storage/browser/database/database_connections.h" #include "storage/browser/database/database_connections.h"
#include "url/origin.h" #include "url/origin.h"
@ -36,6 +38,8 @@ class MetaTable;
namespace storage { namespace storage {
class DatabaseQuotaClient;
class QuotaClientCallbackWrapper;
class QuotaManagerProxy; class QuotaManagerProxy;
class SpecialStoragePolicy; class SpecialStoragePolicy;
@ -329,6 +333,9 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseTracker
// Sequence where file I/O is allowed. // Sequence where file I/O is allowed.
const scoped_refptr<base::SequencedTaskRunner> task_runner_; const scoped_refptr<base::SequencedTaskRunner> task_runner_;
std::unique_ptr<DatabaseQuotaClient> quota_client_;
std::unique_ptr<storage::QuotaClientCallbackWrapper> quota_client_wrapper_;
// When in Incognito mode, store a DELETE_ON_CLOSE handle to each // When in Incognito mode, store a DELETE_ON_CLOSE handle to each
// main DB and journal file that was accessed. When the Incognito profile // main DB and journal file that was accessed. When the Incognito profile
// goes away (or when the browser crashes), all these handles will be // goes away (or when the browser crashes), all these handles will be
@ -344,6 +351,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseTracker
std::map<std::string, std::u16string> incognito_origin_directories_; std::map<std::string, std::u16string> incognito_origin_directories_;
int incognito_origin_directories_generator_ = 0; int incognito_origin_directories_generator_ = 0;
mojo::Receiver<mojom::QuotaClient> quota_client_receiver_;
FRIEND_TEST_ALL_PREFIXES(DatabaseTracker, TestHelper); FRIEND_TEST_ALL_PREFIXES(DatabaseTracker, TestHelper);
}; };

@ -16,6 +16,7 @@
#include "base/memory/scoped_refptr.h" #include "base/memory/scoped_refptr.h"
#include "base/notreached.h" #include "base/notreached.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
#include "base/test/bind.h" #include "base/test/bind.h"
#include "base/test/task_environment.h" #include "base/test/task_environment.h"
#include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/sequenced_task_runner_handle.h"
@ -95,25 +96,27 @@ void CheckNotificationReceived(TestObserver* observer,
EXPECT_EQ(expected_database_size, observer->GetNotificationDatabaseSize()); EXPECT_EQ(expected_database_size, observer->GetNotificationDatabaseSize());
} }
// Must be destroyed on the sequence that called RegisterClient() most recently.
class TestQuotaManagerProxy : public QuotaManagerProxy { class TestQuotaManagerProxy : public QuotaManagerProxy {
public: public:
TestQuotaManagerProxy() TestQuotaManagerProxy()
: QuotaManagerProxy(nullptr, base::SequencedTaskRunnerHandle::Get()), : QuotaManagerProxy(
registered_client_(nullptr) {} /*quota_manager_impl=*/nullptr,
base::SequencedTaskRunnerHandle::Get()) {}
void RegisterLegacyClient( void RegisterLegacyClient(
scoped_refptr<QuotaClient> client, scoped_refptr<QuotaClient> client,
QuotaClientType client_type, QuotaClientType client_type,
const std::vector<blink::mojom::StorageType>& storage_types) override { const std::vector<blink::mojom::StorageType>& storage_types) override {
EXPECT_FALSE(registered_client_); NOTREACHED();
registered_client_ = client;
} }
void RegisterClient( void RegisterClient(
mojo::PendingRemote<mojom::QuotaClient> client, mojo::PendingRemote<mojom::QuotaClient> client,
QuotaClientType client_type, QuotaClientType client_type,
const std::vector<blink::mojom::StorageType>& storage_types) override { const std::vector<blink::mojom::StorageType>& storage_types) override {
NOTREACHED(); EXPECT_FALSE(registered_client_);
registered_client_.Bind(std::move(client));
} }
void NotifyStorageAccessed(const url::Origin& origin, void NotifyStorageAccessed(const url::Origin& origin,
@ -152,13 +155,6 @@ class TestQuotaManagerProxy : public QuotaManagerProxy {
scoped_refptr<base::SequencedTaskRunner> callback_task_runner, scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
UsageAndQuotaCallback callback) override {} UsageAndQuotaCallback callback) override {}
void SimulateQuotaManagerDestroyed() {
if (registered_client_) {
registered_client_->OnQuotaManagerDestroyed();
registered_client_ = nullptr;
}
}
bool WasAccessNotified(const url::Origin& origin) { bool WasAccessNotified(const url::Origin& origin) {
return accesses_[origin] != 0; return accesses_[origin] != 0;
} }
@ -173,7 +169,7 @@ class TestQuotaManagerProxy : public QuotaManagerProxy {
modifications_.clear(); modifications_.clear();
} }
scoped_refptr<QuotaClient> registered_client_; mojo::Remote<mojom::QuotaClient> registered_client_;
// Map from origin to count of access notifications. // Map from origin to count of access notifications.
std::map<url::Origin, int> accesses_; std::map<url::Origin, int> accesses_;
@ -182,7 +178,7 @@ class TestQuotaManagerProxy : public QuotaManagerProxy {
std::map<url::Origin, std::pair<int, int64_t>> modifications_; std::map<url::Origin, std::pair<int, int64_t>> modifications_;
protected: protected:
~TestQuotaManagerProxy() override { EXPECT_FALSE(registered_client_); } ~TestQuotaManagerProxy() override = default;
}; };
bool EnsureFileOfSize(const base::FilePath& file_path, int64_t length) { bool EnsureFileOfSize(const base::FilePath& file_path, int64_t length) {
@ -575,8 +571,6 @@ class DatabaseTracker_TestHelper_Test {
// Cleanup. // Cleanup.
crashed_renderer_connections.RemoveAllConnections(); crashed_renderer_connections.RemoveAllConnections();
test_quota_proxy->SimulateQuotaManagerDestroyed();
tracker->Shutdown(); tracker->Shutdown();
})); }));
run_loop.Run(); run_loop.Run();