Commit 45237b83 authored by Harley Li's avatar Harley Li Committed by Commit Bot

[DevTools] Add entry counter to Application>Cache Storage

Without an entry counter, users might get confused how many entries
are in a cache storage, because the UI indication is not obvious enough.
Besides, adding an entry counter is consistent with IndexedDB tables.

When the path filter is not an empty string, the count reflects how
many responses were matched in total.

Bug: 930865
Change-Id: I058562a251163459eeb2adc24def4888f9a9e863
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1537254
Commit-Queue: Haihong Li (Harley) <hhli@chromium.org>
Reviewed-by: default avatarDmitry Gozman <dgozman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#644523}
parent a05d263c
......@@ -1332,8 +1332,9 @@ experimental domain CacheStorage
returns
# Array of object store data entries.
array of DataEntry cacheDataEntries
# If true, there are more entries to fetch in the given range.
boolean hasMore
# Count of returned entries from this storage. If pathFilter is empty, it
# is the count of all entries from this storage.
number returnCount
# A domain for interacting with Cast, Presentation API, and Remote Playback API
# functionalities.
......
......@@ -16,7 +16,7 @@ ApplicationTestRunner.dumpCacheTree = async function(pathFilter) {
};
ApplicationTestRunner.dumpCacheTreeNoRefresh = async function(pathFilter) {
function _dumpDataGrid(dataGrid, indentSpaces) {
function _dumpDataGrid(dataGrid) {
for (const node of dataGrid.rootNode().children) {
const children = Array.from(node.element().children).filter(function(element) {
return !element.classList.contains('responseTime-column');
......@@ -57,6 +57,7 @@ ApplicationTestRunner.dumpCacheTreeNoRefresh = async function(pathFilter) {
if (!pathFilter) {
_dumpDataGrid(view._dataGrid);
TestRunner.addResult(' totalCount: ' + String(view._returnCount));
continue;
}
......@@ -68,6 +69,7 @@ ApplicationTestRunner.dumpCacheTreeNoRefresh = async function(pathFilter) {
}
_dumpDataGrid(cacheTreeElement._view._dataGrid);
TestRunner.addResult(' totalCount: ' + String(view._returnCount));
}
};
......@@ -98,7 +100,7 @@ ApplicationTestRunner.dumpCachedEntryContentNoRefresh = async function(cacheName
await view._updateData(true);
const promiseDumpContent = new Promise(resolve => {
view._model.loadCacheData(view._cache, 0, 50, '', async function(entries, hasMore) {
view._model.loadCacheData(view._cache, 0, 50, '', async function(entries, totalCount) {
for (const entry of entries) {
if (entry.requestURL !== requestUrl)
continue;
......
......@@ -69,6 +69,8 @@ Resources.ServiceWorkerCacheView = class extends UI.SimpleView {
this._pageSize = 50;
this._skipCount = 0;
this._returnCount = /** @type {?number} */ (null);
this._summaryBarElement = /** @type {?Element} */ (null);
this.update(cache);
}
......@@ -77,7 +79,9 @@ Resources.ServiceWorkerCacheView = class extends UI.SimpleView {
if (this._dataGrid)
this._dataGrid.asWidget().detach();
this._dataGrid = this._createDataGrid();
this._splitWidget.setSidebarWidget(this._dataGrid.asWidget());
const dataGridWidget = this._dataGrid.asWidget();
this._splitWidget.setSidebarWidget(dataGridWidget);
dataGridWidget.setMinimumSize(0, 250);
this._skipCount = 0;
}
......@@ -102,7 +106,7 @@ Resources.ServiceWorkerCacheView = class extends UI.SimpleView {
* @param {?UI.Widget} preview
*/
_showPreview(preview) {
if (this._preview === preview)
if (preview && this._preview === preview)
return;
if (this._preview)
this._preview.detach();
......@@ -117,6 +121,7 @@ Resources.ServiceWorkerCacheView = class extends UI.SimpleView {
*/
_createDataGrid() {
const columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([
{id: 'number', title: '#', sortable: false, width: '3px'},
{id: 'path', title: Common.UIString('Path'), weight: 4, sortable: true},
{id: 'responseType', title: ls`Response-Type`, weight: 1, align: DataGrid.DataGrid.Align.Right, sortable: true},
{id: 'contentType', title: Common.UIString('Content-Type'), weight: 1, sortable: true}, {
......@@ -209,16 +214,31 @@ Resources.ServiceWorkerCacheView = class extends UI.SimpleView {
this._updateData(true);
}
_updateSummaryBar() {
if (!this._summaryBarElement)
this._summaryBarElement = this.element.createChild('div', 'cache-storage-summary-bar');
this._summaryBarElement.removeChildren();
const span = this._summaryBarElement.createChild('span');
if (this._entryPathFilter)
span.textContent = ls`Matching entries: ${this._returnCount}`;
else
span.textContent = ls`Total entries: ${this._returnCount}`;
}
/**
* @param {number} skipCount
* @param {!Array<!Protocol.CacheStorage.DataEntry>} entries
* @param {boolean} hasMore
* @param {number} returnCount
* @this {Resources.ServiceWorkerCacheView}
*/
_updateDataCallback(skipCount, entries, hasMore) {
_updateDataCallback(skipCount, entries, returnCount) {
const selected = this._dataGrid.selectedNode && this._dataGrid.selectedNode.data.url();
this._refreshButton.setEnabled(true);
this._entriesForTest = entries;
this._returnCount = returnCount;
this._updateSummaryBar();
const hasMore = (this._skipCount + this._pageSize) < returnCount;
/** @type {!Map<string, !DataGrid.DataGridNode>} */
const oldEntries = new Map();
......@@ -227,11 +247,15 @@ Resources.ServiceWorkerCacheView = class extends UI.SimpleView {
oldEntries.set(node.data.url, node);
rootNode.removeChildren();
let selectedNode = null;
for (const entry of entries) {
for (let i = 0; i < entries.length; ++i) {
const entry = entries[i];
let node = oldEntries.get(entry.requestURL);
if (!node || node.data.responseTime !== entry.responseTime) {
node = new Resources.ServiceWorkerCacheView.DataGridNode(this._createRequest(entry), entry.responseType);
node = new Resources.ServiceWorkerCacheView.DataGridNode(
i + this._skipCount, this._createRequest(entry), entry.responseType);
node.selectable = true;
} else {
node.data.number = i + this._skipCount;
}
rootNode.appendChild(node);
if (entry.requestURL === selected)
......@@ -264,8 +288,8 @@ Resources.ServiceWorkerCacheView = class extends UI.SimpleView {
this._lastSkipCount = skipCount;
return new Promise(resolve => {
this._model.loadCacheData(this._cache, skipCount, pageSize, this._entryPathFilter, (entries, hasMore) => {
this._updateDataCallback(skipCount, entries, hasMore);
this._model.loadCacheData(this._cache, skipCount, pageSize, this._entryPathFilter, (entries, returnCount) => {
this._updateDataCallback(skipCount, entries, returnCount);
resolve();
});
});
......@@ -356,11 +380,13 @@ Resources.ServiceWorkerCacheView._RESPONSE_CACHE_SIZE = 10;
Resources.ServiceWorkerCacheView.DataGridNode = class extends DataGrid.DataGridNode {
/**
* @param {number} number
* @param {!SDK.NetworkRequest} request
* @param {!Protocol.CacheStorage.CachedResponseType} responseType
*/
constructor(request, responseType) {
constructor(number, request, responseType) {
super(request);
this._number = number;
this._path = Common.ParsedURL.extractPath(request.url());
if (!this._path)
this._path = request.url();
......@@ -376,7 +402,9 @@ Resources.ServiceWorkerCacheView.DataGridNode = class extends DataGrid.DataGridN
createCell(columnId) {
const cell = this.createTD(columnId);
let value;
if (columnId === 'path') {
if (columnId === 'number') {
value = String(this._number);
} else if (columnId === 'path') {
value = this._path;
} else if (columnId === 'responseType') {
if (this._responseType === 'opaqueResponse')
......
......@@ -61,3 +61,14 @@
height: 4px;
border-bottom: 1px solid rgb(64%, 64%, 64%);
}
.cache-storage-summary-bar {
flex: 0 0 27px;
line-height: 27px;
padding-left: 5px;
background-color: #eee;
border-top: 1px solid #ccc;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
......@@ -92,7 +92,7 @@ SDK.ServiceWorkerCacheModel = class extends SDK.SDKModel {
* @param {number} skipCount
* @param {number} pageSize
* @param {string} pathFilter
* @param {function(!Array.<!Protocol.CacheStorage.DataEntry>, boolean)} callback
* @param {function(!Array.<!Protocol.CacheStorage.DataEntry>, number)} callback
*/
loadCacheData(cache, skipCount, pageSize, pathFilter, callback) {
this._requestEntries(cache, skipCount, pageSize, pathFilter, callback);
......@@ -235,7 +235,7 @@ SDK.ServiceWorkerCacheModel = class extends SDK.SDKModel {
* @param {number} skipCount
* @param {number} pageSize
* @param {string} pathFilter
* @param {function(!Array<!Protocol.CacheStorage.DataEntry>, boolean)} callback
* @param {function(!Array<!Protocol.CacheStorage.DataEntry>, number)} callback
*/
async _requestEntries(cache, skipCount, pageSize, pathFilter, callback) {
const response =
......@@ -244,7 +244,7 @@ SDK.ServiceWorkerCacheModel = class extends SDK.SDKModel {
console.error('ServiceWorkerCacheAgent error while requesting entries: ', response[Protocol.Error]);
return;
}
callback(response.cacheDataEntries, response.hasMore);
callback(response.cacheDataEntries, response.returnCount);
}
/**
......
......@@ -242,7 +242,7 @@ class ResponsesAccumulator : public RefCounted<ResponsesAccumulator> {
}
wtf_size_t requestSize = requests.size();
if (!requestSize) {
callback_->sendSuccess(Array<DataEntry>::create(), false);
callback_->sendSuccess(Array<DataEntry>::create(), 0);
return;
}
......@@ -310,13 +310,12 @@ class ResponsesAccumulator : public RefCounted<ResponsesAccumulator> {
return WTF::CodePointCompareLessThan(a.request_url,
b.request_url);
});
size_t returned_entries_count = responses_.size();
if (params_.skip_count > 0)
responses_.EraseAt(0, params_.skip_count);
bool has_more = false;
if (static_cast<size_t>(params_.page_size) < responses_.size()) {
responses_.EraseAt(params_.page_size,
responses_.size() - params_.page_size);
has_more = true;
}
std::unique_ptr<Array<DataEntry>> array = Array<DataEntry>::create();
for (const auto& request_response : responses_) {
......@@ -336,7 +335,8 @@ class ResponsesAccumulator : public RefCounted<ResponsesAccumulator> {
.build();
array->addItem(std::move(entry));
}
callback_->sendSuccess(std::move(array), has_more);
callback_->sendSuccess(std::move(array), returned_entries_count);
}
void SendFailure(const mojom::blink::CacheStorageError& error) {
......@@ -401,7 +401,7 @@ class GetCacheKeysForRequestData {
if (result->get_keys().IsEmpty()) {
std::unique_ptr<Array<DataEntry>> array =
Array<DataEntry>::create();
self->callback_->sendSuccess(std::move(array), false);
self->callback_->sendSuccess(std::move(array), 0);
return;
}
scoped_refptr<ResponsesAccumulator> accumulator =
......
......@@ -11,24 +11,29 @@ Dumping CacheStorage tree:
(cache empty)
Dumping CacheStorage tree:
cache: testCache1 - http://127.0.0.1:8000
/1, default, text/plain, 0
/2, default, text/plain, 0
/T, default, image/png, 0
0, /1, default, text/plain, 0
1, /2, default, text/plain, 0
2, /T, default, image/png, 0
totalCount: 3
cache: testCache2 - http://127.0.0.1:8000
/1, default, text/plain, 0
/2, default, text/plain, 0
/H/22, default, text/plain, 0
/L/11, default, text/plain, 0
/T, default, text/javascript, 0
0, /1, default, text/plain, 0
1, /2, default, text/plain, 0
2, /H/22, default, text/plain, 0
3, /L/11, default, text/plain, 0
4, /T, default, text/javascript, 0
totalCount: 5
cache: testCache3 - http://127.0.0.1:8000
/devtools/resources/image.png, basic, image/png, 647
/vars, default, text/plain, 0
0, /devtools/resources/image.png, basic, image/png, 647
1, /vars, default, text/plain, 0
totalCount: 2
Dumping CacheStorage tree with URL path filter string "2"
cache: testCache1 - http://127.0.0.1:8000
/2, default, text/plain, 0
0, /2, default, text/plain, 0
totalCount: 1
cache: testCache2 - http://127.0.0.1:8000
/2, default, text/plain, 0
/H/22, default, text/plain, 0
0, /2, default, text/plain, 0
1, /H/22, default, text/plain, 0
totalCount: 2
cache: testCache3 - http://127.0.0.1:8000
(no matching entries)
Dumping CacheStorage tree with URL path filter string "image"
......@@ -37,7 +42,8 @@ Dumping CacheStorage tree with URL path filter string "image"
cache: testCache2 - http://127.0.0.1:8000
(no matching entries)
cache: testCache3 - http://127.0.0.1:8000
/devtools/resources/image.png, basic, image/png, 647
0, /devtools/resources/image.png, basic, image/png, 647
totalCount: 1
Dumping testCache2's entry with request URL: http://fake.request.com/1
Y
Dumping testCache3's entry with request URL: http://fake.request.com/vars
......
......@@ -9,11 +9,13 @@ Dumping CacheStorage tree:
(cache empty)
Dumping CacheStorage tree:
cache: testCache1 - http://127.0.0.1:8000
/1, default, text/plain, 0
/2, default, text/plain, 0
0, /1, default, text/plain, 0
1, /2, default, text/plain, 0
totalCount: 2
cache: testCache2 - http://127.0.0.1:8000
/1, default, text/plain, 0
/2, default, text/plain, 0
0, /1, default, text/plain, 0
1, /2, default, text/plain, 0
totalCount: 2
Deleting CacheStorage cache testCache2
Dumping CacheStorage tree:
(empty)
......
......@@ -4,15 +4,19 @@ Dumping CacheStorage tree:
(empty)
Dumping CacheStorage tree:
cache: testCache1 - http://127.0.0.1:8000
/1, default, text/plain, 0
/2, default, text/plain, 0
0, /1, default, text/plain, 0
1, /2, default, text/plain, 0
totalCount: 2
cache: testCache2 - http://127.0.0.1:8000
/1, default, text/plain, 0
/2, default, text/plain, 0
0, /1, default, text/plain, 0
1, /2, default, text/plain, 0
totalCount: 2
Deleting CacheStorage entry http://fake.request2.com/2 in cache testCache2
Dumping CacheStorage tree:
cache: testCache1 - http://127.0.0.1:8000
/1, default, text/plain, 0
0, /1, default, text/plain, 0
totalCount: 1
cache: testCache2 - http://127.0.0.1:8000
/1, default, text/plain, 0
0, /1, default, text/plain, 0
totalCount: 1
......@@ -8,7 +8,8 @@ Dumping CacheStorage tree:
Added entry
Dumping CacheStorage tree:
cache: testCache1 - http://127.0.0.1:8000
/1, default, text/plain, 0
0, /1, default, text/plain, 0
totalCount: 1
Deleted entry
Dumping CacheStorage tree:
cache: testCache1 - http://127.0.0.1:8000
......
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