Skip to content

Commit

Permalink
cachestorage: Make CacheStorageContextImpl sequence bound
Browse files Browse the repository at this point in the history
Rather than have CacheStorageContextImpl be accessed across multiple
sequences, have it only live on the cache storage task runner.  This
also allows it to be singly owned instead of refcounted and cleans
up a bunch of task bouncing and init/destruction behavior.

Bug: 1147642
Change-Id: Ie80046e35a909b40d3f553328b730bab3715b65a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2687890
Auto-Submit: enne <enne@chromium.org>
Commit-Queue: Kinuko Yasuda <kinuko@chromium.org>
Reviewed-by: Kinuko Yasuda <kinuko@chromium.org>
Reviewed-by: Ben Kelly <wanderview@chromium.org>
Cr-Commit-Position: refs/heads/master@{#855612}
  • Loading branch information
quisquous authored and Chromium LUCI CQ committed Feb 19, 2021
1 parent a9fbb42 commit 0197921
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 259 deletions.
226 changes: 63 additions & 163 deletions content/browser/cache_storage/cache_storage_context_impl.cc
Expand Up @@ -25,66 +25,76 @@

namespace content {

namespace {

scoped_refptr<base::SequencedTaskRunner> CreateSchedulerTaskRunner() {
return base::ThreadPool::CreateSequencedTaskRunner(
{base::TaskPriority::USER_VISIBLE});
CacheStorageContextImpl::CacheStorageContextImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}

} // namespace
CacheStorageContextImpl::~CacheStorageContextImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

for (const auto& origin : origins_to_purge_on_shutdown_) {
cache_manager_->DeleteOriginData(
origin, storage::mojom::CacheStorageOwner::kCacheAPI,

CacheStorageContextImpl::CacheStorageContextImpl()
: CacheStorageContext(GetUIThreadTaskRunner({})),
task_runner_(CreateSchedulerTaskRunner()) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Retain a reference to the manager until the deletion is
// complete, since it internally uses weak pointers for
// the various stages of deletion and nothing else will
// keep it alive during shutdown.
base::BindOnce([](scoped_refptr<CacheStorageManager> cache_manager,
blink::mojom::QuotaStatusCode) {},
cache_manager_));
}
}

CacheStorageContextImpl::~CacheStorageContextImpl() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
task_runner_->ReleaseSoon(FROM_HERE, std::move(cache_manager_));
// static
scoped_refptr<base::SequencedTaskRunner>
CacheStorageContextImpl::CreateSchedulerTaskRunner() {
return base::ThreadPool::CreateSequencedTaskRunner(
{base::TaskPriority::USER_VISIBLE});
}

void CacheStorageContextImpl::Init(
mojo::PendingReceiver<storage::mojom::CacheStorageControl> control,
const base::FilePath& user_data_directory,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
mojo::PendingRemote<storage::mojom::BlobStorageContext>
blob_storage_context) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

receivers_.Add(this, std::move(control));
is_incognito_ = user_data_directory.empty();

scoped_refptr<base::SequencedTaskRunner> cache_task_runner =
base::ThreadPool::CreateSequencedTaskRunner(
{base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});

task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&CacheStorageContextImpl::CreateCacheStorageManagerOnTaskRunner, this,
user_data_directory, std::move(cache_task_runner),
quota_manager_proxy, std::move(blob_storage_context)));
}

void CacheStorageContextImpl::Shutdown() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);

// Break reference cycle with |this|.
if (dispatcher_host_)
dispatcher_host_.AsyncCall(&CacheStorageDispatcherHost::Shutdown);
DCHECK(!cache_manager_);
cache_manager_ = LegacyCacheStorageManager::Create(
user_data_directory, std::move(cache_task_runner),
base::SequencedTaskRunnerHandle::Get(), quota_manager_proxy,
base::MakeRefCounted<BlobStorageContextWrapper>(
std::move(blob_storage_context)));

receivers_.Clear();
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&CacheStorageContextImpl::ShutdownOnTaskRunner, this,
std::move(origins_to_purge_on_shutdown_)));
}
mojo::PendingRemote<storage::mojom::QuotaClient> cache_storage_client;
mojo::MakeSelfOwnedReceiver(
std::make_unique<CacheStorageQuotaClient>(
cache_manager_, storage::mojom::CacheStorageOwner::kCacheAPI),
cache_storage_client.InitWithNewPipeAndPassReceiver());
quota_manager_proxy->RegisterClient(
std::move(cache_storage_client),
storage::QuotaClientType::kServiceWorkerCache,
{blink::mojom::StorageType::kTemporary});

void CacheStorageContextImpl::Bind(
mojo::PendingReceiver<storage::mojom::CacheStorageControl> control) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
receivers_.Add(this, std::move(control));
mojo::PendingRemote<storage::mojom::QuotaClient> background_fetch_client;
mojo::MakeSelfOwnedReceiver(
std::make_unique<CacheStorageQuotaClient>(
cache_manager_, storage::mojom::CacheStorageOwner::kBackgroundFetch),
background_fetch_client.InitWithNewPipeAndPassReceiver());
quota_manager_proxy->RegisterClient(
std::move(background_fetch_client),
storage::QuotaClientType::kBackgroundFetch,
{blink::mojom::StorageType::kTemporary});
}

void CacheStorageContextImpl::AddReceiver(
Expand All @@ -94,86 +104,37 @@ void CacheStorageContextImpl::AddReceiver(
const url::Origin& origin,
storage::mojom::CacheStorageOwner owner,
mojo::PendingReceiver<blink::mojom::CacheStorage> receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

if (!dispatcher_host_) {
dispatcher_host_ =
base::SequenceBound<CacheStorageDispatcherHost>(task_runner_);
dispatcher_host_.AsyncCall(&CacheStorageDispatcherHost::Init)
.WithArgs(base::RetainedRef(this));
}
dispatcher_host_.AsyncCall(&CacheStorageDispatcherHost::AddReceiver)
.WithArgs(cross_origin_embedder_policy, std::move(coep_reporter), origin,
owner, std::move(receiver));
if (!dispatcher_host_)
dispatcher_host_ = std::make_unique<CacheStorageDispatcherHost>(this);
dispatcher_host_->AddReceiver(cross_origin_embedder_policy,
std::move(coep_reporter), origin, owner,
std::move(receiver));
}

void CacheStorageContextImpl::GetAllOriginsInfo(
storage::mojom::CacheStorageControl::GetAllOriginsInfoCallback callback) {
callback = base::BindOnce(
[](scoped_refptr<base::SequencedTaskRunner> reply_task_runner,
storage::mojom::CacheStorageControl::GetAllOriginsInfoCallback
callback,
std::vector<storage::mojom::StorageUsageInfoPtr> usage_info) {
reply_task_runner->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback), std::move(usage_info)));
},
base::SequencedTaskRunnerHandle::Get(), std::move(callback));

task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
[](scoped_refptr<CacheStorageContextImpl> context,
storage::mojom::CacheStorageControl::GetAllOriginsInfoCallback
callback) {
scoped_refptr<CacheStorageManager> manager =
context->cache_manager();
if (!manager) {
std::move(callback).Run(
std::vector<storage::mojom::StorageUsageInfoPtr>());
return;
}
manager->GetAllOriginsUsage(
storage::mojom::CacheStorageOwner::kCacheAPI,
std::move(callback));
},
base::RetainedRef(this), std::move(callback)));
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
cache_manager_->GetAllOriginsUsage(
storage::mojom::CacheStorageOwner::kCacheAPI, std::move(callback));
}

void CacheStorageContextImpl::DeleteForOrigin(const url::Origin& origin) {
task_runner_->PostTask(
FROM_HERE, base::BindOnce(
[](scoped_refptr<CacheStorageContextImpl> context,
const url::Origin& origin) {
scoped_refptr<CacheStorageManager> manager =
context->cache_manager();
if (!manager)
return;
manager->DeleteOriginData(
origin,
storage::mojom::CacheStorageOwner::kCacheAPI);
},
base::RetainedRef(this), origin));
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
cache_manager_->DeleteOriginData(
origin, storage::mojom::CacheStorageOwner::kCacheAPI);
}

void CacheStorageContextImpl::AddObserver(
mojo::PendingRemote<storage::mojom::CacheStorageObserver> observer) {
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
[](scoped_refptr<CacheStorageContextImpl> context,
mojo::PendingRemote<storage::mojom::CacheStorageObserver>
observer) {
auto manager = context->cache_manager();
if (!manager)
return;
manager->AddObserver(std::move(observer));
},
base::RetainedRef(this), std::move(observer)));
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
cache_manager_->AddObserver(std::move(observer));
}

void CacheStorageContextImpl::ApplyPolicyUpdates(
std::vector<storage::mojom::StoragePolicyUpdatePtr> policy_updates) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
for (const auto& update : policy_updates) {
if (!update->purge_on_shutdown)
origins_to_purge_on_shutdown_.erase(update->origin);
Expand All @@ -182,65 +143,4 @@ void CacheStorageContextImpl::ApplyPolicyUpdates(
}
}

void CacheStorageContextImpl::CreateCacheStorageManagerOnTaskRunner(
const base::FilePath& user_data_directory,
scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
mojo::PendingRemote<storage::mojom::BlobStorageContext>
blob_storage_context) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());

DCHECK(!cache_manager_);
cache_manager_ = LegacyCacheStorageManager::Create(
user_data_directory, std::move(cache_task_runner), task_runner_,
quota_manager_proxy,
base::MakeRefCounted<BlobStorageContextWrapper>(
std::move(blob_storage_context)));

mojo::PendingRemote<storage::mojom::QuotaClient> cache_storage_client;
mojo::MakeSelfOwnedReceiver(
std::make_unique<CacheStorageQuotaClient>(
cache_manager_, storage::mojom::CacheStorageOwner::kCacheAPI),
cache_storage_client.InitWithNewPipeAndPassReceiver());
quota_manager_proxy->RegisterClient(
std::move(cache_storage_client),
storage::QuotaClientType::kServiceWorkerCache,
{blink::mojom::StorageType::kTemporary});

mojo::PendingRemote<storage::mojom::QuotaClient> background_fetch_client;
mojo::MakeSelfOwnedReceiver(
std::make_unique<CacheStorageQuotaClient>(
cache_manager_, storage::mojom::CacheStorageOwner::kBackgroundFetch),
background_fetch_client.InitWithNewPipeAndPassReceiver());
quota_manager_proxy->RegisterClient(
std::move(background_fetch_client),
storage::QuotaClientType::kBackgroundFetch,
{blink::mojom::StorageType::kTemporary});
}

void CacheStorageContextImpl::ShutdownOnTaskRunner(
std::set<url::Origin> origins_to_purge_on_shutdown) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());

for (const auto& origin : origins_to_purge_on_shutdown) {
cache_manager_->DeleteOriginData(
origin, storage::mojom::CacheStorageOwner::kCacheAPI,

// Retain a reference to the manager until the deletion is
// complete, since it internally uses weak pointers for
// the various stages of deletion and nothing else will
// keep it alive during shutdown.
base::BindOnce([](scoped_refptr<CacheStorageManager> cache_manager,
blink::mojom::QuotaStatusCode) {},
cache_manager_));
}

// Release |cache_manager_|. New clients will get a nullptr if they request
// an instance of CacheStorageManager after this. Any other client that
// ref-wrapped |cache_manager_| will be able to continue using it, and the
// CacheStorageManager will be destroyed when all the references are
// destroyed.
cache_manager_ = nullptr;
}

} // namespace content
49 changes: 17 additions & 32 deletions content/browser/cache_storage/cache_storage_context_impl.h
Expand Up @@ -16,7 +16,6 @@
#include "components/services/storage/public/mojom/cache_storage_control.mojom.h"
#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/common/content_export.h"
#include "content/public/browser/cache_storage_context.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
Expand All @@ -42,23 +41,25 @@ namespace content {
class CacheStorageDispatcherHost;
class CacheStorageManager;

// One instance of this exists per StoragePartition, and services multiple
// child processes/origins. Most logic is delegated to the owned
// CacheStorageManager instance, which is only accessed on the target
// sequence.
class CONTENT_EXPORT CacheStorageContextImpl : public CacheStorageContext {
// This class is an implementation of the CacheStorageControl mojom that is
// called from the browser. One instance of this exists per StoragePartition,
// and services multiple child processes/origins. (Compare this with
// CacheStorageDispatcherHost which handles renderer <-> storage service mojo
// messages.) All functions must be called on the same sequence that the
// object is constructed on.
class CONTENT_EXPORT CacheStorageContextImpl
: public storage::mojom::CacheStorageControl {
public:
CacheStorageContextImpl();
~CacheStorageContextImpl() override;

static scoped_refptr<base::SequencedTaskRunner> CreateSchedulerTaskRunner();

// Init and Shutdown are for use on the UI thread when the profile,
// storagepartition is being setup and torn down.
void Init(const base::FilePath& user_data_directory,
void Init(mojo::PendingReceiver<storage::mojom::CacheStorageControl> control,
const base::FilePath& user_data_directory,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
mojo::PendingRemote<storage::mojom::BlobStorageContext>
blob_storage_context);
void Shutdown();

void Bind(mojo::PendingReceiver<storage::mojom::CacheStorageControl> control);

// storage::mojom::CacheStorageControl implementation.
void AddReceiver(
Expand All @@ -78,43 +79,27 @@ class CONTENT_EXPORT CacheStorageContextImpl : public CacheStorageContext {
policy_updates) override;

scoped_refptr<CacheStorageManager> cache_manager() {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return cache_manager_;
}

bool is_incognito() const { return is_incognito_; }

protected:
~CacheStorageContextImpl() override;

private:
void CreateCacheStorageManagerOnTaskRunner(
const base::FilePath& user_data_directory,
scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
mojo::PendingRemote<storage::mojom::BlobStorageContext>
blob_storage_context);

void ShutdownOnTaskRunner(std::set<url::Origin> origins_to_purge_on_shutdown);

// Initialized at construction.
const scoped_refptr<base::SequencedTaskRunner> task_runner_;
SEQUENCE_CHECKER(sequence_checker_);

// The set of origins whose storage should be cleared on shutdown.
std::set<url::Origin> origins_to_purge_on_shutdown_;

// Initialized in Init(); true if the user data directory is empty.
bool is_incognito_ = false;

// Created and accessed on the target sequence. Released on the target
// sequence in ShutdownOnTaskRunner() or the destructor via
// SequencedTaskRunner::ReleaseSoon().
// Released during Shutdown() or the destructor.
scoped_refptr<CacheStorageManager> cache_manager_;

mojo::ReceiverSet<storage::mojom::CacheStorageControl> receivers_;

// Initialized from the UI thread and bound to |task_runner_|.
base::SequenceBound<CacheStorageDispatcherHost> dispatcher_host_;
std::unique_ptr<CacheStorageDispatcherHost> dispatcher_host_;
};

} // namespace content
Expand Down

0 comments on commit 0197921

Please sign in to comment.