blob: b2c3b6b2aa1b87cb80a951decda627b3bd8e7eba [file] [log] [blame]
// Copyright 2015 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 "content/browser/cache_storage/cache_storage_context_impl.h"
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/sequenced_task_runner.h"
#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/cache_storage/cache_storage_dispatcher_host.h"
#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "storage/browser/blob/blob_storage_context.h"
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/browser/quota/special_storage_policy.h"
#include "url/origin.h"
namespace content {
CacheStorageContextImpl::CacheStorageContextImpl(
BrowserContext* browser_context)
: task_runner_(
base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
CacheStorageContextImpl::~CacheStorageContextImpl() {
// Can be destroyed on any thread.
}
void CacheStorageContextImpl::Init(
const base::FilePath& user_data_directory,
scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
is_incognito_ = user_data_directory.empty();
special_storage_policy_ = std::move(special_storage_policy);
scoped_refptr<base::SequencedTaskRunner> cache_task_runner =
base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&CacheStorageContextImpl::CreateCacheStorageManager, this,
user_data_directory, std::move(cache_task_runner),
std::move(quota_manager_proxy)));
}
void CacheStorageContextImpl::Shutdown() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&CacheStorageContextImpl::ShutdownOnTaskRunner, this));
}
void CacheStorageContextImpl::AddBinding(
blink::mojom::CacheStorageRequest request,
const url::Origin& origin) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!dispatcher_host_) {
dispatcher_host_ =
base::SequenceBound<CacheStorageDispatcherHost>(task_runner_);
dispatcher_host_.Post(FROM_HERE, &CacheStorageDispatcherHost::Init,
base::RetainedRef(this));
}
dispatcher_host_.Post(FROM_HERE, &CacheStorageDispatcherHost::AddBinding,
std::move(request), origin);
}
CacheStorageManager* CacheStorageContextImpl::cache_manager() const {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
return cache_manager_.get();
}
void CacheStorageContextImpl::SetBlobParametersForCache(
ChromeBlobStorageContext* blob_storage_context) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&CacheStorageContextImpl::SetBlobParametersForCacheOnTaskRunner, this,
base::RetainedRef(blob_storage_context)));
}
void CacheStorageContextImpl::GetAllOriginsInfo(
CacheStorageContext::GetUsageInfoCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!cache_manager_) {
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(std::move(callback), std::vector<StorageUsageInfo>()));
return;
}
cache_manager_->GetAllOriginsUsage(CacheStorageOwner::kCacheAPI,
std::move(callback));
}
void CacheStorageContextImpl::DeleteForOrigin(const GURL& origin) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (cache_manager_)
cache_manager_->DeleteOriginData(url::Origin::Create(origin),
CacheStorageOwner::kCacheAPI);
}
void CacheStorageContextImpl::AddObserver(
CacheStorageContextImpl::Observer* observer) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (cache_manager_)
cache_manager_->AddObserver(observer);
}
void CacheStorageContextImpl::RemoveObserver(
CacheStorageContextImpl::Observer* observer) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (cache_manager_)
cache_manager_->RemoveObserver(observer);
}
void CacheStorageContextImpl::CreateCacheStorageManager(
const base::FilePath& user_data_directory,
scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
DCHECK(!cache_manager_);
cache_manager_ = CacheStorageManager::Create(
user_data_directory, std::move(cache_task_runner), task_runner_,
std::move(quota_manager_proxy));
}
void CacheStorageContextImpl::ShutdownOnTaskRunner() {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
// Delete session-only ("clear on exit") origins.
if (special_storage_policy_ &&
special_storage_policy_->HasSessionOnlyOrigins()) {
cache_manager_->GetAllOriginsUsage(
CacheStorageOwner::kCacheAPI,
// TODO(jsbell): Make this BindOnce.
base::BindRepeating(
[](scoped_refptr<CacheStorageManager> cache_manager,
scoped_refptr<storage::SpecialStoragePolicy>
special_storage_policy,
const std::vector<StorageUsageInfo>& usage_info) {
for (const auto& info : usage_info) {
if (special_storage_policy->IsStorageSessionOnly(
info.origin.GetURL()) &&
!special_storage_policy->IsStorageProtected(
info.origin.GetURL())) {
cache_manager->DeleteOriginData(
info.origin, 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));
}
}
},
cache_manager_, special_storage_policy_));
}
// 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;
}
void CacheStorageContextImpl::SetBlobParametersForCacheOnTaskRunner(
ChromeBlobStorageContext* blob_storage_context) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
if (cache_manager_ && blob_storage_context) {
cache_manager_->SetBlobParametersForCache(
blob_storage_context->context()->AsWeakPtr());
}
}
} // namespace content