blob: 044ff29e9b2f21af55bd1bdfed1f960f65d60af2 [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/browsing_data/browsing_data_quota_helper_impl.h"
#include <map>
#include <set>
#include "base/barrier_closure.h"
#include "base/check_op.h"
#include "base/functional/bind.h"
#include "base/notreached.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/url_constants.h"
#include "components/browsing_data/content/browsing_data_helper.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#include "storage/browser/quota/quota_manager.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"
using blink::mojom::StorageType;
using content::BrowserThread;
using content::BrowserContext;
// static
scoped_refptr<BrowsingDataQuotaHelper> BrowsingDataQuotaHelper::Create(
content::StoragePartition* storage_partition) {
return base::MakeRefCounted<BrowsingDataQuotaHelperImpl>(
storage_partition->GetQuotaManager());
}
void BrowsingDataQuotaHelperImpl::StartFetching(FetchResultCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(!callback.is_null());
content::GetIOThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(&BrowsingDataQuotaHelperImpl::FetchQuotaInfoOnIOThread,
this, std::move(callback)));
}
void BrowsingDataQuotaHelperImpl::DeleteHostData(const std::string& host,
StorageType type) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
content::GetIOThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(&BrowsingDataQuotaHelperImpl::DeleteHostDataOnIOThread,
this, host, type));
}
BrowsingDataQuotaHelperImpl::BrowsingDataQuotaHelperImpl(
storage::QuotaManager* quota_manager)
: BrowsingDataQuotaHelper(), quota_manager_(quota_manager) {
DCHECK(quota_manager);
}
BrowsingDataQuotaHelperImpl::~BrowsingDataQuotaHelperImpl() {}
void BrowsingDataQuotaHelperImpl::FetchQuotaInfoOnIOThread(
FetchResultCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
const StorageType types[] = {StorageType::kTemporary, StorageType::kSyncable};
// Query storage keys for each storage types. When complete, process the
// collected quota info.
QuotaInfoMap* quota_info = new QuotaInfoMap();
base::RepeatingClosure completion = base::BarrierClosure(
std::size(types),
base::BindOnce(&BrowsingDataQuotaHelperImpl::OnGetHostsUsageComplete,
weak_factory_.GetWeakPtr(), std::move(callback),
base::Owned(quota_info)));
for (const StorageType& type : types) {
quota_manager_->GetStorageKeysForType(
type, base::BindOnce(&BrowsingDataQuotaHelperImpl::GotStorageKeys,
weak_factory_.GetWeakPtr(), quota_info, completion,
type));
}
}
void BrowsingDataQuotaHelperImpl::GotStorageKeys(
QuotaInfoMap* quota_info,
base::OnceClosure completion,
StorageType type,
const std::set<blink::StorageKey>& storage_keys) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
int storage_key_count = base::ranges::count_if(
storage_keys, [](const blink::StorageKey& storage_key) {
return browsing_data::IsWebScheme(storage_key.origin().scheme());
});
auto storage_key_completion =
base::BarrierClosure(storage_key_count, std::move(completion));
for (const blink::StorageKey& storage_key : storage_keys) {
if (!browsing_data::IsWebScheme(storage_key.origin().scheme()))
continue; // Non-websafe state is not considered browsing data.
quota_manager_->GetStorageKeyUsageWithBreakdown(
storage_key, type,
base::BindOnce(&BrowsingDataQuotaHelperImpl::GotStorageKeyUsage,
weak_factory_.GetWeakPtr(), quota_info, storage_key,
type)
.Then(storage_key_completion));
}
}
void BrowsingDataQuotaHelperImpl::GotStorageKeyUsage(
QuotaInfoMap* quota_info,
const blink::StorageKey& storage_key,
StorageType type,
int64_t usage,
blink::mojom::UsageBreakdownPtr usage_breakdown) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
switch (type) {
case StorageType::kTemporary:
(*quota_info)[storage_key.origin().host()].temporary_usage += usage;
break;
case StorageType::kSyncable:
(*quota_info)[storage_key.origin().host()].syncable_usage += usage;
break;
default:
NOTREACHED();
}
}
void BrowsingDataQuotaHelperImpl::OnGetHostsUsageComplete(
FetchResultCallback callback,
QuotaInfoMap* quota_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
QuotaInfoArray result;
for (auto& pair : *quota_info) {
QuotaInfo& info = pair.second;
// Skip unused entries
if (info.temporary_usage <= 0 && info.syncable_usage <= 0)
continue;
info.host = pair.first;
result.push_back(info);
}
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), result));
}
void BrowsingDataQuotaHelperImpl::DeleteHostDataOnIOThread(
const std::string& host,
blink::mojom::StorageType type) {
quota_manager_->DeleteHostData(
host, type, base::DoNothingAs<void(blink::mojom::QuotaStatusCode)>());
}