Bug 1434579 - Fix infinite scrolling for indexedDB in storage inspector;r=miker

MozReview-Commit-ID: 7ZyxqDPxHTK

--HG--
extra : rebase_source : e6c4fd13ad514b52b7aa38c0f507cc1438a1e893
This commit is contained in:
Julian Descottes 2018-07-24 19:48:27 +02:00
Родитель 8c326e567e
Коммит d31555e033
6 изменённых файлов: 133 добавлений и 46 удалений

Просмотреть файл

@ -15,6 +15,7 @@ support-files =
storage-listings-usercontextid.html storage-listings-usercontextid.html
storage-listings-with-fragment.html storage-listings-with-fragment.html
storage-localstorage.html storage-localstorage.html
storage-overflow-indexeddb.html
storage-overflow.html storage-overflow.html
storage-search.html storage-search.html
storage-secured-iframe.html storage-secured-iframe.html
@ -57,6 +58,7 @@ tags = usercontextid
[browser_storage_indexeddb_delete.js] [browser_storage_indexeddb_delete.js]
[browser_storage_indexeddb_delete_blocked.js] [browser_storage_indexeddb_delete_blocked.js]
[browser_storage_indexeddb_duplicate_names.js] [browser_storage_indexeddb_duplicate_names.js]
[browser_storage_indexeddb_overflow.js]
[browser_storage_localstorage_add.js] [browser_storage_localstorage_add.js]
[browser_storage_localstorage_edit.js] [browser_storage_localstorage_edit.js]
[browser_storage_localstorage_error.js] [browser_storage_localstorage_error.js]

Просмотреть файл

@ -0,0 +1,35 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Test endless scrolling when a lot of items are present in the storage
// inspector table for IndexedDB.
"use strict";
const ITEMS_PER_PAGE = 50;
add_task(async function() {
await openTabAndSetupStorage(MAIN_DOMAIN + "storage-overflow-indexeddb.html");
info("Run the tests with short DevTools");
await runTests();
info("Close Toolbox");
const target = TargetFactory.forTab(gBrowser.selectedTab);
await gDevTools.closeToolbox(target);
await finishTests();
});
async function runTests() {
gUI.tree.expandAll();
await selectTreeItem(["indexedDB",
"http://test1.example.org",
"database (default)",
"store"]);
checkCellLength(ITEMS_PER_PAGE);
await scroll();
checkCellLength(ITEMS_PER_PAGE * 2);
}

Просмотреть файл

@ -1,3 +1,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Test endless scrolling when a lot of items are present in the storage // Test endless scrolling when a lot of items are present in the storage
// inspector table. // inspector table.
"use strict"; "use strict";
@ -47,14 +51,6 @@ async function runTests() {
checkCellValues("DEC"); checkCellValues("DEC");
} }
function checkCellLength(len) {
const cells = gPanelWindow.document
.querySelectorAll("#name .table-widget-cell");
const msg = `Table should initially display ${len} items`;
is(cells.length, len, msg);
}
function checkCellValues(order) { function checkCellValues(order) {
const cells = [...gPanelWindow.document const cells = [...gPanelWindow.document
.querySelectorAll("#name .table-widget-cell")]; .querySelectorAll("#name .table-widget-cell")];
@ -63,14 +59,3 @@ function checkCellValues(order) {
is(cell.value, `item-${i}`, `Cell value is correct (${order}).`); is(cell.value, `item-${i}`, `Cell value is correct (${order}).`);
}); });
} }
async function scroll() {
const $ = id => gPanelWindow.document.querySelector(id);
const table = $("#storage-table .table-widget-body");
const cell = $("#name .table-widget-cell");
const cellHeight = cell.getBoundingClientRect().height;
const onStoresUpdate = gUI.once("store-objects-updated");
table.scrollTop += cellHeight * 50;
await onStoresUpdate;
}

Просмотреть файл

@ -1003,3 +1003,21 @@ async function performAdd(store) {
is(rowId, value, `Row '${rowId}' was successfully added.`); is(rowId, value, `Row '${rowId}' was successfully added.`);
} }
function checkCellLength(len) {
const cells = gPanelWindow.document.querySelectorAll("#name .table-widget-cell");
const msg = `Table should initially display ${len} items`;
is(cells.length, len, msg);
}
async function scroll() {
const $ = id => gPanelWindow.document.querySelector(id);
const table = $("#storage-table .table-widget-body");
const cell = $("#name .table-widget-cell");
const cellHeight = cell.getBoundingClientRect().height;
const onStoresUpdate = gUI.once("store-objects-updated");
table.scrollTop += cellHeight * 50;
await onStoresUpdate;
}

Просмотреть файл

@ -0,0 +1,51 @@
<!DOCTYPE HTML>
<html>
<!--
Bug 1171903 - Storage Inspector endless scrolling
-->
<head>
<meta charset="utf-8">
<title>Storage inspector endless scrolling test</title>
</head>
<body>
<script type="text/javascript">
"use strict";
window.setup = async function() {
await new Promise(resolve => {
const open = indexedDB.open("database", 1);
open.onupgradeneeded = function() {
const db = open.result;
const store = db.createObjectStore("store", {keyPath: "id"});
store.transaction.oncomplete = () => {
const transaction = db.transaction(["store"], "readwrite");
for (let i = 1; i < 150; i++) {
transaction.objectStore("store").add({id: i});
}
transaction.oncomplete = function() {
db.close();
resolve();
};
};
};
});
};
function deleteDB(dbName, storage) {
return new Promise(resolve => {
indexedDB.deleteDatabase(dbName, { storage: storage }).onsuccess = resolve;
});
}
window.clear = async function() {
await deleteDB("database", "temporary");
await deleteDB("database", "default");
await deleteDB("database", "persistent");
dump(`removed indexedDB data from ${document.location}\n`);
};
</script>
</body>
</html>

Просмотреть файл

@ -337,7 +337,7 @@ StorageActors.defaults = function(typeName, observationTopics) {
* - data - The requested values. * - data - The requested values.
*/ */
async getStoreObjects(host, names, options = {}) { async getStoreObjects(host, names, options = {}) {
let offset = options.offset || 0; const offset = options.offset || 0;
let size = options.size || MAX_STORE_OBJECT_COUNT; let size = options.size || MAX_STORE_OBJECT_COUNT;
if (size > MAX_STORE_OBJECT_COUNT) { if (size > MAX_STORE_OBJECT_COUNT) {
size = MAX_STORE_OBJECT_COUNT; size = MAX_STORE_OBJECT_COUNT;
@ -381,6 +381,16 @@ StorageActors.defaults = function(typeName, observationTopics) {
} }
toReturn.total = this.getObjectsSize(host, names, options); toReturn.total = this.getObjectsSize(host, names, options);
} else {
let obj = await this.getValuesForHost(host, undefined, undefined,
this.hostVsStores, principal);
if (obj.dbs) {
obj = obj.dbs;
}
toReturn.total = obj.length;
toReturn.data = obj;
}
if (offset > toReturn.total) { if (offset > toReturn.total) {
// In this case, toReturn.data is an empty array. // In this case, toReturn.data is an empty array.
@ -391,31 +401,17 @@ StorageActors.defaults = function(typeName, observationTopics) {
const sorted = toReturn.data.sort((a, b) => { const sorted = toReturn.data.sort((a, b) => {
return naturalSortCaseInsensitive(a[sortOn], b[sortOn]); return naturalSortCaseInsensitive(a[sortOn], b[sortOn]);
}); });
const sliced = sorted.slice(offset, offset + size); let sliced;
if (this.typeName === "indexedDB") {
// indexedDB's getValuesForHost never returns *all* values available but only
// a slice, starting at the expected offset. Therefore the result is already
// sliced as expected.
sliced = sorted;
} else {
sliced = sorted.slice(offset, offset + size);
}
toReturn.data = sliced.map(a => this.toStoreObject(a)); toReturn.data = sliced.map(a => this.toStoreObject(a));
} }
} else {
let obj = await this.getValuesForHost(host, undefined, undefined,
this.hostVsStores, principal);
if (obj.dbs) {
obj = obj.dbs;
}
toReturn.total = obj.length;
if (offset > toReturn.total) {
// In this case, toReturn.data is an empty array.
toReturn.offset = offset = toReturn.total;
toReturn.data = [];
} else {
// We need to use natural sort before slicing.
const sorted = obj.sort((a, b) => {
return naturalSortCaseInsensitive(a[sortOn], b[sortOn]);
});
const sliced = sorted.slice(offset, offset + size);
toReturn.data = sliced.map(object => this.toStoreObject(object));
}
}
return toReturn; return toReturn;
}, },
@ -2358,15 +2354,15 @@ var indexedDBHelpers = {
objectStore: objectStore, objectStore: objectStore,
id: id, id: id,
index: options.index, index: options.index,
offset: 0, offset: options.offset,
size: options.size size: options.size
}); });
return this.backToChild("getValuesForHost", {result: result}); return this.backToChild("getValuesForHost", {result: result});
}, },
/** /**
* Returns all or requested entries from a particular objectStore from the db * Returns requested entries (or at most MAX_STORE_OBJECT_COUNT) from a particular
* in the given host. * objectStore from the db in the given host.
* *
* @param {string} host * @param {string} host
* The given host. * The given host.