blob: 511a700982669bd648c61fc6fcf78604667b98d0 [file] [log] [blame]
// Copyright 2016 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/devtools/protocol/storage_handler.h"
#include <unordered_set>
#include <utility>
#include <vector>
#include "base/strings/string_split.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/storage_partition.h"
#include "storage/browser/quota/quota_client.h"
#include "storage/browser/quota/quota_manager.h"
#include "storage/common/quota/quota_status_code.h"
namespace content {
namespace protocol {
namespace {
Storage::StorageType GetTypeName(storage::QuotaClient::ID id) {
switch (id) {
case storage::QuotaClient::kFileSystem:
return Storage::StorageTypeEnum::File_systems;
case storage::QuotaClient::kDatabase:
return Storage::StorageTypeEnum::Websql;
case storage::QuotaClient::kAppcache:
return Storage::StorageTypeEnum::Appcache;
case storage::QuotaClient::kIndexedDatabase:
return Storage::StorageTypeEnum::Indexeddb;
case storage::QuotaClient::kServiceWorkerCache:
return Storage::StorageTypeEnum::Cache_storage;
case storage::QuotaClient::kServiceWorker:
return Storage::StorageTypeEnum::Service_workers;
default:
return Storage::StorageTypeEnum::Other;
}
}
void ReportUsageAndQuotaDataOnUIThread(
std::unique_ptr<StorageHandler::GetUsageAndQuotaCallback> callback,
storage::QuotaStatusCode code,
int64_t usage,
int64_t quota,
base::flat_map<storage::QuotaClient::ID, int64_t> usage_breakdown) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (code != storage::kQuotaStatusOk) {
return callback->sendFailure(
Response::Error("Quota information is not available"));
}
std::unique_ptr<Array<Storage::UsageForType>> usageList =
Array<Storage::UsageForType>::create();
for (const auto& usage : usage_breakdown) {
std::unique_ptr<Storage::UsageForType> entry =
Storage::UsageForType::Create()
.SetStorageType(GetTypeName(usage.first))
.SetUsage(usage.second)
.Build();
usageList->addItem(std::move(entry));
}
callback->sendSuccess(usage, quota, std::move(usageList));
}
void GotUsageAndQuotaDataCallback(
std::unique_ptr<StorageHandler::GetUsageAndQuotaCallback> callback,
storage::QuotaStatusCode code,
int64_t usage,
int64_t quota,
base::flat_map<storage::QuotaClient::ID, int64_t> usage_breakdown) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(ReportUsageAndQuotaDataOnUIThread,
base::Passed(std::move(callback)), code,
usage, quota, std::move(usage_breakdown)));
}
void GetUsageAndQuotaOnIOThread(
storage::QuotaManager* manager,
const GURL& url,
std::unique_ptr<StorageHandler::GetUsageAndQuotaCallback> callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
manager->GetUsageAndQuotaWithBreakdown(
url, storage::kStorageTypeTemporary,
base::Bind(&GotUsageAndQuotaDataCallback,
base::Passed(std::move(callback))));
}
} // namespace
StorageHandler::StorageHandler()
: DevToolsDomainHandler(Storage::Metainfo::domainName),
host_(nullptr) {
}
StorageHandler::~StorageHandler() = default;
void StorageHandler::Wire(UberDispatcher* dispatcher) {
Storage::Dispatcher::wire(dispatcher, this);
}
void StorageHandler::SetRenderFrameHost(RenderFrameHostImpl* host) {
host_ = host;
}
Response StorageHandler::ClearDataForOrigin(
const std::string& origin,
const std::string& storage_types) {
if (!host_)
return Response::InternalError();
StoragePartition* partition = host_->GetProcess()->GetStoragePartition();
std::vector<std::string> types = base::SplitString(
storage_types, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
std::unordered_set<std::string> set(types.begin(), types.end());
uint32_t remove_mask = 0;
if (set.count(Storage::StorageTypeEnum::Appcache))
remove_mask |= StoragePartition::REMOVE_DATA_MASK_APPCACHE;
if (set.count(Storage::StorageTypeEnum::Cookies))
remove_mask |= StoragePartition::REMOVE_DATA_MASK_COOKIES;
if (set.count(Storage::StorageTypeEnum::File_systems))
remove_mask |= StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS;
if (set.count(Storage::StorageTypeEnum::Indexeddb))
remove_mask |= StoragePartition::REMOVE_DATA_MASK_INDEXEDDB;
if (set.count(Storage::StorageTypeEnum::Local_storage))
remove_mask |= StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE;
if (set.count(Storage::StorageTypeEnum::Shader_cache))
remove_mask |= StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE;
if (set.count(Storage::StorageTypeEnum::Websql))
remove_mask |= StoragePartition::REMOVE_DATA_MASK_WEBSQL;
if (set.count(Storage::StorageTypeEnum::Service_workers))
remove_mask |= StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS;
if (set.count(Storage::StorageTypeEnum::Cache_storage))
remove_mask |= StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE;
if (set.count(Storage::StorageTypeEnum::All))
remove_mask |= StoragePartition::REMOVE_DATA_MASK_ALL;
if (!remove_mask)
return Response::InvalidParams("No valid storage type specified");
partition->ClearDataForOrigin(
remove_mask,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
GURL(origin),
partition->GetURLRequestContext(),
base::Bind(&base::DoNothing));
return Response::OK();
}
void StorageHandler::GetUsageAndQuota(
const String& origin,
std::unique_ptr<GetUsageAndQuotaCallback> callback) {
if (!host_)
return callback->sendFailure(Response::InternalError());
GURL origin_url(origin);
if (!origin_url.is_valid()) {
return callback->sendFailure(
Response::Error(origin + " is not a valid URL"));
}
storage::QuotaManager* manager =
host_->GetProcess()->GetStoragePartition()->GetQuotaManager();
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&GetUsageAndQuotaOnIOThread, manager, origin_url,
base::Passed(std::move(callback))));
}
} // namespace protocol
} // namespace content