Commit 19f69e90 authored by kristipark's avatar kristipark Committed by Commit Bot

[DevTools] [Quota] Display usage per storage type

Bug: 729772
Change-Id: I34b16707b790f65faba01bdcc44bbd98c911b93b
Reviewed-on: https://chromium-review.googlesource.com/541981
Commit-Queue: Kristi Park <kristipark@chromium.org>
Reviewed-by: default avatarDmitry Gozman <dgozman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#481713}
parent 26834276
......@@ -12,6 +12,7 @@
#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"
......@@ -19,40 +20,61 @@ namespace content {
namespace protocol {
namespace {
static const char kAppCache[] = "appcache";
static const char kCookies[] = "cookies";
static const char kFileSystems[] = "filesystems";
static const char kIndexedDB[] = "indexeddb";
static const char kLocalStorage[] = "local_storage";
static const char kShaderCache[] = "shader_cache";
static const char kWebSQL[] = "websql";
static const char kServiceWorkers[] = "service_workers";
static const char kCacheStorage[] = "cache_storage";
static const char kAll[] = "all";
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) {
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"));
}
callback->sendSuccess(usage, quota);
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) {
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));
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(ReportUsageAndQuotaDataOnUIThread,
base::Passed(std::move(callback)), code,
usage, quota, std::move(usage_breakdown)));
}
void GetUsageAndQuotaOnIOThread(
......@@ -60,7 +82,7 @@ void GetUsageAndQuotaOnIOThread(
const GURL& url,
std::unique_ptr<StorageHandler::GetUsageAndQuotaCallback> callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
manager->GetUsageAndQuotaForWebApps(
manager->GetUsageAndQuotaWithBreakdown(
url, storage::kStorageTypeTemporary,
base::Bind(&GotUsageAndQuotaDataCallback,
base::Passed(std::move(callback))));
......@@ -93,25 +115,25 @@ Response StorageHandler::ClearDataForOrigin(
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(kAppCache))
if (set.count(Storage::StorageTypeEnum::Appcache))
remove_mask |= StoragePartition::REMOVE_DATA_MASK_APPCACHE;
if (set.count(kCookies))
if (set.count(Storage::StorageTypeEnum::Cookies))
remove_mask |= StoragePartition::REMOVE_DATA_MASK_COOKIES;
if (set.count(kFileSystems))
if (set.count(Storage::StorageTypeEnum::File_systems))
remove_mask |= StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS;
if (set.count(kIndexedDB))
if (set.count(Storage::StorageTypeEnum::Indexeddb))
remove_mask |= StoragePartition::REMOVE_DATA_MASK_INDEXEDDB;
if (set.count(kLocalStorage))
if (set.count(Storage::StorageTypeEnum::Local_storage))
remove_mask |= StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE;
if (set.count(kShaderCache))
if (set.count(Storage::StorageTypeEnum::Shader_cache))
remove_mask |= StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE;
if (set.count(kWebSQL))
if (set.count(Storage::StorageTypeEnum::Websql))
remove_mask |= StoragePartition::REMOVE_DATA_MASK_WEBSQL;
if (set.count(kServiceWorkers))
if (set.count(Storage::StorageTypeEnum::Service_workers))
remove_mask |= StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS;
if (set.count(kCacheStorage))
if (set.count(Storage::StorageTypeEnum::Cache_storage))
remove_mask |= StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE;
if (set.count(kAll))
if (set.count(Storage::StorageTypeEnum::All))
remove_mask |= StoragePartition::REMOVE_DATA_MASK_ALL;
if (!remove_mask)
......
......@@ -5,8 +5,11 @@ Tests quota reporting.
Tree element found: true
Clear storage view is visible: true
0 B storage quota used out of -
0 B used out of -- storage quota
Usage breakdown:
Running: Now with data
9.5 MB storage quota used out of -
9.5 MB used out of -- storage quota
Usage breakdown:
IndexedDB: 9.5 MB
......@@ -30,8 +30,21 @@ async function test() {
});
// Quota will vary between setups, rather strip it altogether
var clean = view._quotaRow.innerHTML.replace(/\&nbsp;/g, ' ');
var quotaStripped = clean.replace(/(.*) \d+ .?B([^\d]*)/, '$1 -$2');
var quotaStripped = clean.replace(/(.*) \d+ .?B([^\d]*)/, '$1 --$2');
InspectorTest.addResult(quotaStripped);
InspectorTest.addResult('Usage breakdown:');
for (var i = 0; i < view._pieChartLegend.children.length; i++) {
var typeUsage = ': ';
var children = view._pieChartLegend.children[i].children;
for (var j = 0; j < children.length; j++) {
if (children[j].classList.contains('usage-breakdown-legend-title'))
typeUsage = children[j].textContent + typeUsage;
if (children[j].classList.contains('usage-breakdown-legend-value'))
typeUsage = typeUsage + children[j].textContent;
}
InspectorTest.addResult(typeUsage);
}
}
UI.viewManager.showView('resources');
......
......@@ -4593,9 +4593,19 @@
"websql",
"service_workers",
"cache_storage",
"all"
"all",
"other"
],
"description": "Enum of possible storage types."
},
{
"id": "UsageForType",
"type": "object",
"description": "Usage for a storage type.",
"properties": [
{ "name": "storageType", "$ref": "StorageType", "description": "Name of storage type." },
{ "name": "usage", "type": "number", "description": "Storage usage (bytes)." }
]
}
],
"commands": [
......@@ -4614,7 +4624,8 @@
],
"returns": [
{ "name": "usage", "type": "number", "description": "Storage usage (bytes)." },
{ "name": "quota", "type": "number", "description": "Storage quota (bytes)." }
{ "name": "quota", "type": "number", "description": "Storage quota (bytes)." },
{ "name": "usageBreakdown", "type": "array", "items": { "$ref": "UsageForType" }, "description": "Storage usage per type (bytes)." }
],
"description": "Returns usage and quota in bytes."
}
......
......@@ -7,6 +7,15 @@
Resources.ClearStorageView = class extends UI.ThrottledWidget {
constructor() {
super(true, 1000);
this._pieColors = [
'rgba(110, 161, 226, 1)', // blue
'rgba(229, 113, 113, 1)', // red
'rgba(239, 196, 87, 1)', // yellow
'rgba(155, 127, 230, 1)', // purple
'rgba(116, 178, 102, 1)', // green
'rgba(255, 167, 36, 1)', // orange
'rgba(203, 220, 56, 1)', // lime
];
this._reportView = new UI.ReportView(Common.UIString('Clear storage'));
this._reportView.registerRequiredCSS('resources/clearStorageView.css');
......@@ -27,13 +36,18 @@ Resources.ClearStorageView = class extends UI.ThrottledWidget {
var quota = this._reportView.appendSection(Common.UIString('Usage'));
this._quotaRow = quota.appendRow();
this._pieChart = new PerfUI.PieChart(110, Number.bytesToString, true);
this._pieChartLegend = createElementWithClass('div', 'legend');
var usageBreakdownRow = quota.appendRow();
usageBreakdownRow.appendChild(this._pieChart.element);
usageBreakdownRow.appendChild(this._pieChartLegend);
var application = this._reportView.appendSection(Common.UIString('Application'));
this._appendItem(application, Common.UIString('Unregister service workers'), 'service_workers');
var storage = this._reportView.appendSection(Common.UIString('Storage'));
this._appendItem(storage, Common.UIString('Local and session storage'), 'local_storage');
this._appendItem(storage, Common.UIString('Indexed DB'), 'indexeddb');
this._appendItem(storage, Common.UIString('IndexedDB'), 'indexeddb');
this._appendItem(storage, Common.UIString('Web SQL'), 'websql');
this._appendItem(storage, Common.UIString('Cookies'), 'cookies');
......@@ -176,19 +190,82 @@ Resources.ClearStorageView = class extends UI.ThrottledWidget {
var response = await this._target.storageAgent().invoke_getUsageAndQuota({origin: securityOrigin});
if (response[Protocol.Error]) {
this._quotaRow.textContent = '';
this._resetPieChart(0);
return;
}
this._quotaRow.textContent = Common.UIString(
'%s storage quota used out of %s', Number.bytesToString(response.usage), Number.bytesToString(response.quota));
'%s used out of %s storage quota', Number.bytesToString(response.usage), Number.bytesToString(response.quota));
this._usageUpdatedForTest(response.usage, response.quota);
this._resetPieChart(response.usage);
var colorIndex = 0;
for (var usageForType of response.usageBreakdown) {
if (!usageForType.usage)
continue;
if (colorIndex === this._pieColors.length)
colorIndex = 0;
this._appendLegendRow(
this._getStorageTypeName(usageForType.storageType), usageForType.usage, this._pieColors[colorIndex++]);
}
this._usageUpdatedForTest(response.usage, response.quota, response.usageBreakdown);
this.update();
}
_formatPieChartBytes(value) {
return Number.bytesToString(value);
}
/**
* @param {number} total
*/
_resetPieChart(total) {
this._pieChart.setTotal(total);
this._pieChartLegend.removeChildren();
}
/**
* @param {string} title
* @param {number} value
* @param {string} color
*/
_appendLegendRow(title, value, color) {
if (!value)
return;
this._pieChart.addSlice(value, color);
var rowElement = this._pieChartLegend.createChild('div');
rowElement.createChild('span', 'usage-breakdown-legend-value').textContent = Number.bytesToString(value);
rowElement.createChild('span', 'usage-breakdown-legend-swatch').style.backgroundColor = color;
rowElement.createChild('span', 'usage-breakdown-legend-title').textContent = title;
}
/**
* @param {string} type
* @return {string}
*/
_getStorageTypeName(type) {
switch (type) {
case Protocol.Storage.StorageType.File_systems:
return Common.UIString('File System');
case Protocol.Storage.StorageType.Websql:
return Common.UIString('Web SQL');
case Protocol.Storage.StorageType.Appcache:
return Common.UIString('Application Cache');
case Protocol.Storage.StorageType.Indexeddb:
return Common.UIString('IndexedDB');
case Protocol.Storage.StorageType.Cache_storage:
return Common.UIString('Cache Storage');
case Protocol.Storage.StorageType.Service_workers:
return Common.UIString('Service Workers');
default:
return Common.UIString('Other');
}
}
/**
* @param {number} usage
* @param {number} quota
* @param {!Array<!Protocol.Storage.UsageForType>} usageBreakdown
*/
_usageUpdatedForTest(usage, quota) {
_usageUpdatedForTest(usage, quota, usageBreakdown) {
}
};
......@@ -22,3 +22,23 @@
.report-row:hover .link {
display: inline;
}
.usage-breakdown-legend-title {
display: inline-block;
}
.usage-breakdown-legend-value {
display: inline-block;
width: 70px;
text-align: right;
}
.usage-breakdown-legend-swatch {
display: inline-block;
width: 11px;
height: 11px;
margin: 0 6px;
position: relative;
top: 1px;
border: 1px solid rgba(0, 0, 0, 0.2);
}
......@@ -23,6 +23,7 @@
"data_grid",
"components",
"object_ui",
"perf_ui",
"mobile_throttling"
],
"scripts": [
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment