--- a/devtools/client/storage/test/browser.ini
+++ b/devtools/client/storage/test/browser.ini
@@ -4,27 +4,29 @@ subsuite = devtools
support-files =
storage-cache-error.html
storage-complex-values.html
storage-cookies.html
storage-empty-objectstores.html
storage-idb-delete-blocked.html
storage-indexeddb-duplicate-names.html
storage-listings.html
+ storage-listings-with-fragment.html
storage-localstorage.html
storage-overflow.html
storage-search.html
storage-secured-iframe.html
storage-sessionstorage.html
storage-unsecured-iframe.html
storage-updates.html
head.js
!/devtools/client/framework/test/shared-head.js
[browser_storage_basic.js]
+[browser_storage_basic_with_fragment.js]
[browser_storage_cache_delete.js]
[browser_storage_cache_error.js]
[browser_storage_cookies_delete_all.js]
[browser_storage_cookies_domain.js]
[browser_storage_cookies_edit.js]
[browser_storage_cookies_edit_keyboard.js]
[browser_storage_cookies_tab_navigation.js]
[browser_storage_delete.js]
--- a/devtools/client/storage/test/browser_storage_basic.js
+++ b/devtools/client/storage/test/browser_storage_basic.js
@@ -19,26 +19,26 @@
// These entries are formed by the cookies, local storage, session storage and
// indexedDB entries created in storage-listings.html,
// storage-secured-iframe.html and storage-unsecured-iframe.html
"use strict";
const testCases = [
[
- ["cookies", "test1.example.org"],
+ ["cookies", "http://test1.example.org"],
[
getCookieId("c1", "test1.example.org", "/browser"),
getCookieId("cs2", ".example.org", "/"),
getCookieId("c3", "test1.example.org", "/"),
getCookieId("uc1", ".example.org", "/")
]
],
[
- ["cookies", "sectest1.example.org"],
+ ["cookies", "https://sectest1.example.org"],
[
getCookieId("uc1", ".example.org", "/"),
getCookieId("cs2", ".example.org", "/"),
getCookieId("sc1", "sectest1.example.org", "/browser/devtools/client/storage/test/")
]
],
[["localStorage", "http://test1.example.org"],
["ls1", "ls2"]],
@@ -81,18 +81,18 @@ const testCases = [
MAIN_DOMAIN + "browser_storage_basic.js"]],
];
/**
* Test that the desired number of tree items are present
*/
function testTree() {
let doc = gPanelWindow.document;
- for (let item of testCases) {
- ok(doc.querySelector("[data-id='" + JSON.stringify(item[0]) + "']"),
+ for (let [item] of testCases) {
+ ok(doc.querySelector("[data-id='" + JSON.stringify(item) + "']"),
"Tree item " + item[0] + " should be present in the storage tree");
}
}
/**
* Test that correct table entries are shown for each of the tree item
*/
function* testTables() {
@@ -102,26 +102,26 @@ function* testTables() {
// First tree item is already selected so no clicking and waiting for update
for (let id of testCases[0][1]) {
ok(doc.querySelector(".table-widget-cell[data-id='" + id + "']"),
"Table item " + id + " should be present");
}
// Click rest of the tree items and wait for the table to be updated
- for (let item of testCases.slice(1)) {
- yield selectTreeItem(item[0]);
+ for (let [treeItem, items] of testCases.slice(1)) {
+ yield selectTreeItem(treeItem);
// Check whether correct number of items are present in the table
is(doc.querySelectorAll(
".table-widget-wrapper:first-of-type .table-widget-cell"
- ).length, item[1].length, "Number of items in table is correct");
+ ).length, items.length, "Number of items in table is correct");
// Check if all the desired items are present in the table
- for (let id of item[1]) {
+ for (let id of items) {
ok(doc.querySelector(".table-widget-cell[data-id='" + id + "']"),
"Table item " + id + " should be present");
}
}
}
add_task(function* () {
yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-listings.html");
new file mode 100644
--- /dev/null
+++ b/devtools/client/storage/test/browser_storage_basic_with_fragment.js
@@ -0,0 +1,139 @@
+/* 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/. */
+
+/* import-globals-from head.js */
+
+// A second basic test to assert that the storage tree and table corresponding
+// to each item in the storage tree is correctly displayed.
+
+// This test differs from browser_storage_basic.js because the URLs we load
+// include fragments e.g. http://example.com/test.js#abcdefg
+// ^^^^^^^^
+// fragment
+
+// Entries that should be present in the tree for this test
+// Format for each entry in the array :
+// [
+// ["path", "to", "tree", "item"], - The path to the tree item to click formed
+// by id of each item
+// ["key_value1", "key_value2", ...] - The value of the first (unique) column
+// for each row in the table corresponding
+// to the tree item selected.
+// ]
+// These entries are formed by the cookies, local storage, session storage and
+// indexedDB entries created in storage-listings.html,
+// storage-secured-iframe.html and storage-unsecured-iframe.html
+
+"use strict";
+
+const testCases = [
+ [
+ ["cookies", "http://test1.example.org"],
+ [
+ getCookieId("c1", "test1.example.org", "/browser"),
+ getCookieId("cs2", ".example.org", "/"),
+ getCookieId("c3", "test1.example.org", "/"),
+ getCookieId("uc1", ".example.org", "/")
+ ]
+ ],
+ [
+ ["cookies", "https://sectest1.example.org"],
+ [
+ getCookieId("uc1", ".example.org", "/"),
+ getCookieId("cs2", ".example.org", "/"),
+ getCookieId("sc1", "sectest1.example.org", "/browser/devtools/client/storage/test/")
+ ]
+ ],
+ [["localStorage", "http://test1.example.org"],
+ ["ls1", "ls2"]],
+ [["localStorage", "http://sectest1.example.org"],
+ ["iframe-u-ls1"]],
+ [["localStorage", "https://sectest1.example.org"],
+ ["iframe-s-ls1"]],
+ [["sessionStorage", "http://test1.example.org"],
+ ["ss1"]],
+ [["sessionStorage", "http://sectest1.example.org"],
+ ["iframe-u-ss1", "iframe-u-ss2"]],
+ [["sessionStorage", "https://sectest1.example.org"],
+ ["iframe-s-ss1"]],
+ [["indexedDB", "http://test1.example.org"],
+ ["idb1 (default)", "idb2 (default)"]],
+ [["indexedDB", "http://test1.example.org", "idb1 (default)"],
+ ["obj1", "obj2"]],
+ [["indexedDB", "http://test1.example.org", "idb2 (default)"],
+ ["obj3"]],
+ [["indexedDB", "http://test1.example.org", "idb1 (default)", "obj1"],
+ [1, 2, 3]],
+ [["indexedDB", "http://test1.example.org", "idb1 (default)", "obj2"],
+ [1]],
+ [["indexedDB", "http://test1.example.org", "idb2 (default)", "obj3"],
+ []],
+ [["indexedDB", "http://sectest1.example.org"],
+ []],
+ [["indexedDB", "https://sectest1.example.org"],
+ ["idb-s1 (default)", "idb-s2 (default)"]],
+ [["indexedDB", "https://sectest1.example.org", "idb-s1 (default)"],
+ ["obj-s1"]],
+ [["indexedDB", "https://sectest1.example.org", "idb-s2 (default)"],
+ ["obj-s2"]],
+ [["indexedDB", "https://sectest1.example.org", "idb-s1 (default)", "obj-s1"],
+ [6, 7]],
+ [["indexedDB", "https://sectest1.example.org", "idb-s2 (default)", "obj-s2"],
+ [16]],
+ [["Cache", "http://test1.example.org", "plop"],
+ [MAIN_DOMAIN + "404_cached_file.js",
+ MAIN_DOMAIN + "browser_storage_basic.js"]],
+];
+
+/**
+ * Test that the desired number of tree items are present
+ */
+function testTree() {
+ let doc = gPanelWindow.document;
+ for (let [item] of testCases) {
+ ok(doc.querySelector("[data-id='" + JSON.stringify(item) + "']"),
+ "Tree item " + item[0] + " should be present in the storage tree");
+ }
+}
+
+/**
+ * Test that correct table entries are shown for each of the tree item
+ */
+function* testTables() {
+ let doc = gPanelWindow.document;
+ // Expand all nodes so that the synthesized click event actually works
+ gUI.tree.expandAll();
+
+ // First tree item is already selected so no clicking and waiting for update
+ for (let id of testCases[0][1]) {
+ ok(doc.querySelector(".table-widget-cell[data-id='" + id + "']"),
+ "Table item " + id + " should be present");
+ }
+
+ // Click rest of the tree items and wait for the table to be updated
+ for (let [treeItem, items] of testCases.slice(1)) {
+ yield selectTreeItem(treeItem);
+
+ // Check whether correct number of items are present in the table
+ is(doc.querySelectorAll(
+ ".table-widget-wrapper:first-of-type .table-widget-cell"
+ ).length, items.length, "Number of items in table is correct");
+
+ // Check if all the desired items are present in the table
+ for (let id of items) {
+ ok(doc.querySelector(".table-widget-cell[data-id='" + id + "']"),
+ "Table item " + id + " should be present");
+ }
+ }
+}
+
+add_task(function* () {
+ yield openTabAndSetupStorage(
+ MAIN_DOMAIN + "storage-listings-with-fragment.html#abc");
+
+ testTree();
+ yield testTables();
+
+ yield finishTests();
+});
--- a/devtools/client/storage/test/browser_storage_cookies_delete_all.js
+++ b/devtools/client/storage/test/browser_storage_cookies_delete_all.js
@@ -39,66 +39,66 @@ function* performDelete(store, rowName,
}
add_task(function* () {
yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-listings.html");
info("test state before delete");
yield checkState([
[
- ["cookies", "test1.example.org"], [
+ ["cookies", "http://test1.example.org"], [
getCookieId("c1", "test1.example.org", "/browser"),
getCookieId("c3", "test1.example.org", "/"),
getCookieId("cs2", ".example.org", "/"),
getCookieId("uc1", ".example.org", "/")
]
],
[
- ["cookies", "sectest1.example.org"], [
+ ["cookies", "https://sectest1.example.org"], [
getCookieId("cs2", ".example.org", "/"),
getCookieId("sc1", "sectest1.example.org",
"/browser/devtools/client/storage/test/"),
getCookieId("uc1", ".example.org", "/")
]
],
]);
info("delete all from domain");
// delete only cookies that match the host exactly
let id = getCookieId("c1", "test1.example.org", "/browser");
- yield performDelete(["cookies", "test1.example.org"], id, false);
+ yield performDelete(["cookies", "http://test1.example.org"], id, false);
info("test state after delete all from domain");
yield checkState([
// Domain cookies (.example.org) must not be deleted.
[
- ["cookies", "test1.example.org"],
+ ["cookies", "http://test1.example.org"],
[
getCookieId("cs2", ".example.org", "/"),
getCookieId("uc1", ".example.org", "/")
]
],
[
- ["cookies", "sectest1.example.org"],
+ ["cookies", "https://sectest1.example.org"],
[
getCookieId("cs2", ".example.org", "/"),
getCookieId("uc1", ".example.org", "/"),
getCookieId("sc1", "sectest1.example.org",
"/browser/devtools/client/storage/test/"),
]
],
]);
info("delete all");
// delete all cookies for host, including domain cookies
id = getCookieId("uc1", ".example.org", "/");
- yield performDelete(["cookies", "sectest1.example.org"], id, true);
+ yield performDelete(["cookies", "http://sectest1.example.org"], id, true);
info("test state after delete all");
yield checkState([
// Domain cookies (.example.org) are deleted too, so deleting in sectest1
// also removes stuff from test1.
- [["cookies", "test1.example.org"], []],
- [["cookies", "sectest1.example.org"], []],
+ [["cookies", "http://test1.example.org"], []],
+ [["cookies", "https://sectest1.example.org"], []],
]);
yield finishTests();
});
--- a/devtools/client/storage/test/browser_storage_cookies_domain.js
+++ b/devtools/client/storage/test/browser_storage_cookies_domain.js
@@ -9,17 +9,17 @@
// Test that cookies with domain equal to full host name are listed.
// E.g., ".example.org" vs. example.org). Bug 1149497.
add_task(function* () {
yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-cookies.html");
yield checkState([
[
- ["cookies", "test1.example.org"],
+ ["cookies", "http://test1.example.org"],
[
getCookieId("test1", ".test1.example.org", "/browser"),
getCookieId("test2", "test1.example.org", "/browser"),
getCookieId("test3", ".test1.example.org", "/browser"),
getCookieId("test4", "test1.example.org", "/browser"),
getCookieId("test5", ".test1.example.org", "/browser")
]
],
--- a/devtools/client/storage/test/browser_storage_delete.js
+++ b/devtools/client/storage/test/browser_storage_delete.js
@@ -9,17 +9,17 @@
// Test deleting storage items
const TEST_CASES = [
[["localStorage", "http://test1.example.org"],
"ls1", "name"],
[["sessionStorage", "http://test1.example.org"],
"ss1", "name"],
[
- ["cookies", "test1.example.org"],
+ ["cookies", "http://test1.example.org"],
getCookieId("c1", "test1.example.org", "/browser"), "name"
],
[["indexedDB", "http://test1.example.org", "idb1 (default)", "obj1"],
1, "name"],
[["Cache", "http://test1.example.org", "plop"],
MAIN_DOMAIN + "404_cached_file.js", "url"],
];
--- a/devtools/client/storage/test/browser_storage_delete_tree.js
+++ b/devtools/client/storage/test/browser_storage_delete_tree.js
@@ -13,34 +13,34 @@ add_task(function* () {
let contextMenu = gPanelWindow.document.getElementById("storage-tree-popup");
let menuDeleteAllItem = contextMenu.querySelector(
"#storage-tree-popup-delete-all");
info("test state before delete");
yield checkState([
[
- ["cookies", "test1.example.org"],
+ ["cookies", "http://test1.example.org"],
[
getCookieId("c1", "test1.example.org", "/browser"),
getCookieId("cs2", ".example.org", "/"),
getCookieId("c3", "test1.example.org", "/"),
getCookieId("uc1", ".example.org", "/")
]
],
[["localStorage", "http://test1.example.org"], ["ls1", "ls2"]],
[["sessionStorage", "http://test1.example.org"], ["ss1"]],
[["indexedDB", "http://test1.example.org", "idb1 (default)", "obj1"], [1, 2, 3]],
[["Cache", "http://test1.example.org", "plop"],
[MAIN_DOMAIN + "404_cached_file.js", MAIN_DOMAIN + "browser_storage_basic.js"]],
]);
info("do the delete");
const deleteHosts = [
- ["cookies", "test1.example.org"],
+ ["cookies", "http://test1.example.org"],
["localStorage", "http://test1.example.org"],
["sessionStorage", "http://test1.example.org"],
["indexedDB", "http://test1.example.org", "idb1 (default)", "obj1"],
["Cache", "http://test1.example.org", "plop"],
];
for (let store of deleteHosts) {
let storeName = store.join(" > ");
@@ -59,17 +59,17 @@ add_task(function* () {
menuDeleteAllItem.click();
});
yield eventWait;
}
info("test state after delete");
yield checkState([
- [["cookies", "test1.example.org"], []],
+ [["cookies", "http://test1.example.org"], []],
[["localStorage", "http://test1.example.org"], []],
[["sessionStorage", "http://test1.example.org"], []],
[["indexedDB", "http://test1.example.org", "idb1 (default)", "obj1"], []],
[["Cache", "http://test1.example.org", "plop"], []],
]);
yield finishTests();
});
--- a/devtools/client/storage/test/browser_storage_dynamic_updates_cookies.js
+++ b/devtools/client/storage/test/browser_storage_dynamic_updates_cookies.js
@@ -38,34 +38,34 @@ add_task(function* () {
// Check that sidebar shows correct initial value
yield findVariableViewProperties(initialValue[0], false);
yield findVariableViewProperties(initialValue[1], true);
// Check if table shows correct initial value
yield checkState([
[
- ["cookies", "test1.example.org"],
+ ["cookies", "http://test1.example.org"],
[
getCookieId("c1", "test1.example.org", "/browser"),
getCookieId("c2", "test1.example.org", "/browser")
]
],
]);
checkCell(c1id, "value", "1.2.3.4.5.6.7");
gWindow.addCookie("c1", '{"foo": 4,"bar":6}', "/browser");
yield gUI.once("sidebar-updated");
yield findVariableViewProperties(finalValue[0], false);
yield findVariableViewProperties(finalValue[1], true);
yield checkState([
[
- ["cookies", "test1.example.org"],
+ ["cookies", "http://test1.example.org"],
[
getCookieId("c1", "test1.example.org", "/browser"),
getCookieId("c2", "test1.example.org", "/browser")
]
],
]);
checkCell(c1id, "value", '{"foo": 4,"bar":6}');
@@ -73,17 +73,17 @@ add_task(function* () {
gWindow.addCookie("c3", "booyeah");
// Wait once for update and another time for value fetching
yield gUI.once("store-objects-updated");
yield gUI.once("store-objects-updated");
yield checkState([
[
- ["cookies", "test1.example.org"],
+ ["cookies", "http://test1.example.org"],
[
getCookieId("c1", "test1.example.org", "/browser"),
getCookieId("c2", "test1.example.org", "/browser"),
getCookieId("c3", "test1.example.org",
"/browser/devtools/client/storage/test/")
]
],
]);
@@ -95,17 +95,17 @@ add_task(function* () {
gWindow.addCookie("c4", "booyeah");
// Wait once for update and another time for value fetching
yield gUI.once("store-objects-updated");
yield gUI.once("store-objects-updated");
yield checkState([
[
- ["cookies", "test1.example.org"],
+ ["cookies", "http://test1.example.org"],
[
getCookieId("c1", "test1.example.org", "/browser"),
getCookieId("c2", "test1.example.org", "/browser"),
getCookieId("c3", "test1.example.org",
"/browser/devtools/client/storage/test/"),
getCookieId("c4", "test1.example.org",
"/browser/devtools/client/storage/test/")
]
@@ -117,17 +117,17 @@ add_task(function* () {
// Removing cookies
gWindow.removeCookie("c1", "/browser");
yield gUI.once("sidebar-updated");
yield checkState([
[
- ["cookies", "test1.example.org"],
+ ["cookies", "http://test1.example.org"],
[
getCookieId("c2", "test1.example.org", "/browser"),
getCookieId("c3", "test1.example.org",
"/browser/devtools/client/storage/test/"),
getCookieId("c4", "test1.example.org",
"/browser/devtools/client/storage/test/")
]
],
@@ -140,17 +140,17 @@ add_task(function* () {
// Keep deleting till no rows
gWindow.removeCookie("c3");
yield gUI.once("store-objects-updated");
yield checkState([
[
- ["cookies", "test1.example.org"],
+ ["cookies", "http://test1.example.org"],
[
getCookieId("c2", "test1.example.org", "/browser"),
getCookieId("c4", "test1.example.org",
"/browser/devtools/client/storage/test/")
]
],
]);
@@ -158,31 +158,31 @@ add_task(function* () {
yield findVariableViewProperties([{name: "c2", value: "foobar"}]);
gWindow.removeCookie("c2", "/browser");
yield gUI.once("sidebar-updated");
yield checkState([
[
- ["cookies", "test1.example.org"],
+ ["cookies", "http://test1.example.org"],
[
getCookieId("c4", "test1.example.org",
"/browser/devtools/client/storage/test/")
]
],
]);
// Check if next element's value is visible in sidebar
yield findVariableViewProperties([{name: "c4", value: "booyeah"}]);
gWindow.removeCookie("c4");
yield gUI.once("store-objects-updated");
yield checkState([
- [["cookies", "test1.example.org"], [ ]],
+ [["cookies", "http://test1.example.org"], [ ]],
]);
ok(gUI.sidebar.hidden, "Sidebar is hidden when no rows");
yield finishTests();
});
--- a/devtools/client/storage/test/browser_storage_sidebar.js
+++ b/devtools/client/storage/test/browser_storage_sidebar.js
@@ -11,17 +11,17 @@
// <do we wait for the async "sidebar-updated" event>,
// <is the sidebar open>
// ]
"use strict";
const testCases = [
{
- location: ["cookies", "sectest1.example.org"],
+ location: ["cookies", "https://sectest1.example.org"],
sidebarHidden: true
},
{
location: getCookieId("cs2", ".example.org", "/"),
sidebarHidden: false
},
{
sendEscape: true
new file mode 100644
--- /dev/null
+++ b/devtools/client/storage/test/storage-listings-with-fragment.html
@@ -0,0 +1,134 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+This test differs from browser_storage_listings.html only because the URLs we load
+include fragments e.g. http://example.com/test.js#abcdefg
+ ^^^^^^^^
+ fragment
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Storage inspector test for listing hosts and storages with URL fragments</title>
+</head>
+<body>
+<iframe src="http://sectest1.example.org/browser/devtools/client/storage/test/storage-unsecured-iframe.html#def"></iframe>
+<iframe src="https://sectest1.example.org:443/browser/devtools/client/storage/test/storage-secured-iframe.html#ghi"></iframe>
+<script type="application/javascript;version=1.7">
+"use strict";
+let partialHostname = location.hostname.match(/^[^.]+(\..*)$/)[1];
+let cookieExpiresTime1 = 2000000000000;
+let cookieExpiresTime2 = 2000000001000;
+// Setting up some cookies to eat.
+document.cookie = "c1=foobar; expires=" +
+ new Date(cookieExpiresTime1).toGMTString() + "; path=/browser";
+document.cookie = "cs2=sessionCookie; path=/; domain=" + partialHostname;
+document.cookie = "c3=foobar-2; expires=" +
+ new Date(cookieExpiresTime2).toGMTString() + "; path=/";
+// ... and some local storage items ..
+localStorage.setItem("ls1", "foobar");
+localStorage.setItem("ls2", "foobar-2");
+// ... and finally some session storage items too
+sessionStorage.setItem("ss1", "foobar-3");
+dump("added cookies and storage from main page\n");
+
+let idbGenerator = async function() {
+ let request = indexedDB.open("idb1", 1);
+ request.onerror = function() {
+ throw new Error("error opening db connection");
+ };
+ let db = await new Promise(done => {
+ request.onupgradeneeded = event => {
+ let db = event.target.result;
+ let store1 = db.createObjectStore("obj1", { keyPath: "id" });
+ store1.createIndex("name", "name", { unique: false });
+ store1.createIndex("email", "email", { unique: true });
+ let store2 = db.createObjectStore("obj2", { keyPath: "id2" });
+ store1.transaction.oncomplete = () => {
+ done(db);
+ };
+ };
+ });
+
+ // Prevents AbortError
+ await new Promise(done => {
+ request.onsuccess = done;
+ });
+
+ let transaction = db.transaction(["obj1", "obj2"], "readwrite");
+ let store1 = transaction.objectStore("obj1");
+ let store2 = transaction.objectStore("obj2");
+ store1.add({id: 1, name: "foo", email: "foo@bar.com"});
+ store1.add({id: 2, name: "foo2", email: "foo2@bar.com"});
+ store1.add({id: 3, name: "foo2", email: "foo3@bar.com"});
+ store2.add({
+ id2: 1,
+ name: "foo",
+ email: "foo@bar.com",
+ extra: "baz"
+ });
+ // Prevents AbortError during close()
+ await new Promise(success => {
+ transaction.oncomplete = success;
+ });
+
+ db.close();
+
+ request = indexedDB.open("idb2", 1);
+ let db2 = await new Promise(done => {
+ request.onupgradeneeded = event => {
+ let db2 = event.target.result;
+ let store3 = db2.createObjectStore("obj3", { keyPath: "id3" });
+ store3.createIndex("name2", "name2", { unique: true });
+ store3.transaction.oncomplete = () => {
+ done(db2);
+ }
+ };
+ });
+ // Prevents AbortError during close()
+ await new Promise(done => {
+ request.onsuccess = done;
+ });
+ db2.close();
+
+ dump("added indexedDB from main page\n");
+};
+
+function deleteDB(dbName) {
+ return new Promise(resolve => {
+ dump("removing database " + dbName + " from " + document.location + "\n");
+ indexedDB.deleteDatabase(dbName).onsuccess = resolve;
+ });
+}
+
+async function fetchPut(cache, url) {
+ let response = await fetch(url);
+ await cache.put(url, response);
+}
+
+let cacheGenerator = async function() {
+ let cache = await caches.open("plop");
+ await fetchPut(cache, "404_cached_file.js");
+ await fetchPut(cache, "browser_storage_basic.js");
+};
+
+window.setup = function*() {
+ yield idbGenerator();
+
+ if (window.caches) {
+ yield cacheGenerator();
+ }
+};
+
+window.clear = function*() {
+ yield deleteDB("idb1");
+ yield deleteDB("idb2");
+
+ if (window.caches) {
+ yield caches.delete("plop");
+ }
+
+ dump("removed indexedDB and cache data from " + document.location + "\n");
+};
+</script>
+</body>
+</html>
--- a/devtools/client/storage/test/storage-listings.html
+++ b/devtools/client/storage/test/storage-listings.html
@@ -1,12 +1,12 @@
<!DOCTYPE HTML>
<html>
<!--
-Bug 970517 - Storage inspector front end - tests
+Storage inspector front end - tests
-->
<head>
<meta charset="utf-8">
<title>Storage inspector test for listing hosts and storages</title>
</head>
<body>
<iframe src="http://sectest1.example.org/browser/devtools/client/storage/test/storage-unsecured-iframe.html"></iframe>
<iframe src="https://sectest1.example.org:443/browser/devtools/client/storage/test/storage-secured-iframe.html"></iframe>
--- a/devtools/server/actors/storage.js
+++ b/devtools/server/actors/storage.js
@@ -121,37 +121,63 @@ StorageActors.defaults = function (typeN
/**
* Returns a list of currently knwon hosts for the target window. This list
* contains unique hosts from the window + all inner windows.
*/
get hosts() {
let hosts = new Set();
for (let {location} of this.storageActor.windows) {
- hosts.add(this.getHostName(location));
+ let host = this.getHostName(location);
+
+ if (host) {
+ hosts.add(host);
+ }
}
return hosts;
},
/**
* Returns all the windows present on the page. Includes main window + inner
* iframe windows.
*/
get windows() {
return this.storageActor.windows;
},
/**
- * Converts the window.location object into host.
+ * Converts the window.location object into a URL (e.g. http://domain.com).
*/
getHostName(location) {
- if (location.protocol === "chrome:") {
- return location.href;
+ if (!location) {
+ // Debugging a legacy Firefox extension... no hostname available and no
+ // storage possible.
+ return null;
}
- return location.hostname || location.href;
+
+ switch (location.protocol) {
+ case "data:":
+ // data: URLs do not support storage of any type.
+ return null;
+ case "about:":
+ // Fallthrough.
+ case "chrome:":
+ // Fallthrough.
+ case "file:":
+ return location.protocol + location.pathname;
+ case "resource:":
+ return location.origin + location.pathname;
+ case "moz-extension:":
+ return location.origin;
+ case "javascript:":
+ return location.href;
+ default:
+ // http: or unknown protocol.
+ return `${location.protocol}//${location.host}`;
+ }
},
initialize(storageActor) {
protocol.Actor.prototype.initialize.call(this, null);
this.storageActor = storageActor;
this.populateStoresForHosts();
@@ -201,17 +227,17 @@ StorageActors.defaults = function (typeN
* When a new window is added to the page. This generally means that a new
* iframe is created, or the current window is completely reloaded.
*
* @param {window} window
* The window which was added.
*/
onWindowReady: Task.async(function* (window) {
let host = this.getHostName(window.location);
- if (!this.hostVsStores.has(host)) {
+ if (host && !this.hostVsStores.has(host)) {
yield this.populateStoresForHost(host, window);
let data = {};
data[host] = this.getNamesForHost(host);
this.storageActor.update("added", typeName, data);
}
}),
/**
@@ -222,17 +248,17 @@ StorageActors.defaults = function (typeN
* The window which was removed.
*/
onWindowDestroyed(window) {
if (!window.location) {
// Nothing can be done if location object is null
return;
}
let host = this.getHostName(window.location);
- if (!this.hosts.has(host)) {
+ if (host && !this.hosts.has(host)) {
this.hostVsStores.delete(host);
let data = {};
data[host] = [];
this.storageActor.update("deleted", typeName, data);
}
},
form(form, detail) {
@@ -462,22 +488,26 @@ StorageActors.createActor({
/**
* Given a cookie object and a host, figure out if the cookie is valid for
* that host.
*/
isCookieAtHost(cookie, host) {
if (cookie.host == null) {
return host == null;
}
+
+ host = trimHttpHttps(host);
+
if (cookie.host.startsWith(".")) {
return ("." + host).endsWith(cookie.host);
}
if (cookie.host === "") {
return host.startsWith("file://" + cookie.path);
}
+
return cookie.host == host;
},
toStoreObject(cookie) {
if (!cookie) {
return null;
}
@@ -709,16 +739,18 @@ StorageActors.createActor({
var cookieHelpers = {
getCookiesFromHost(host, originAttributes) {
// Local files have no host.
if (host.startsWith("file:///")) {
host = "";
}
+ host = trimHttpHttps(host);
+
let cookies = Services.cookies.getCookiesFromHost(host, originAttributes);
let store = [];
while (cookies.hasMoreElements()) {
let cookie = cookies.getNext().QueryInterface(Ci.nsICookie2);
store.push(cookie);
}
@@ -843,16 +875,18 @@ var cookieHelpers = {
// extract the cookie name to remove the correct cookie.
if (opts.name) {
let split = opts.name.split(SEPARATOR_GUID);
opts.name = split[0];
opts.path = split[2];
}
+ host = trimHttpHttps(host);
+
function hostMatches(cookieHost, matchHost) {
if (cookieHost == null) {
return matchHost == null;
}
if (cookieHost.startsWith(".")) {
return ("." + matchHost).endsWith(cookieHost);
}
return cookieHost == host;
@@ -1049,38 +1083,31 @@ function getObjectForLocalOrSessionStora
return [];
}
return Object.keys(storage).map(key => ({
name: key,
value: storage.getItem(key)
}));
},
- getHostName(location) {
- if (!location.host) {
- return location.href;
- }
- if (location.protocol === "chrome:") {
- return location.href;
- }
- return location.protocol + "//" + location.host;
- },
-
populateStoresForHost(host, window) {
try {
this.hostVsStores.set(host, window[type]);
} catch (ex) {
console.warn(`Failed to enumerate ${type} for host ${host}: ${ex}`);
}
},
populateStoresForHosts() {
this.hostVsStores = new Map();
for (let window of this.windows) {
- this.populateStoresForHost(this.getHostName(window.location), window);
+ let host = this.getHostName(window.location);
+ if (host) {
+ this.populateStoresForHost(host, window);
+ }
}
},
getFields: Task.async(function* () {
return [
{ name: "name", editable: true },
{ name: "value", editable: true }
];
@@ -1269,26 +1296,16 @@ StorageActors.createActor({
getFields: Task.async(function* () {
return [
{ name: "url", editable: false },
{ name: "status", editable: false }
];
}),
- getHostName(location) {
- if (!location.host) {
- return location.href;
- }
- if (location.protocol === "chrome:") {
- return location.href;
- }
- return location.protocol + "//" + location.host;
- },
-
populateStoresForHost: Task.async(function* (host) {
let storeMap = new Map();
let caches = yield this.getCachesForHost(host);
try {
for (let name of (yield caches.keys())) {
storeMap.set(name, (yield caches.open(name)));
}
} catch (ex) {
@@ -1554,26 +1571,16 @@ StorageActors.createActor({
if (!win) {
return;
}
let principal = win.document.nodePrincipal;
this.removeDBRecord(host, principal, db, store, id);
}),
- getHostName(location) {
- if (!location.host) {
- return location.href;
- }
- if (location.protocol === "chrome:") {
- return location.href;
- }
- return location.protocol + "//" + location.host;
- },
-
/**
* This method is overriden and left blank as for indexedDB, this operation
* cannot be performed synchronously. Thus, the preListStores method exists to
* do the same task asynchronously.
*/
populateStoresForHosts() {},
getNamesForHost(host) {
@@ -2405,16 +2412,29 @@ exports.setupParentProcessForIndexedDB =
return {
onBrowserSwap: setMessageManager,
onDisconnected: () => setMessageManager(null),
};
};
/**
+ * General helpers
+ */
+function trimHttpHttps(url) {
+ if (url.startsWith("http://")) {
+ return url.substr(7);
+ }
+ if (url.startsWith("https://")) {
+ return url.substr(8);
+ }
+ return url;
+}
+
+/**
* The main Storage Actor.
*/
let StorageActor = protocol.ActorClassWithSpec(specs.storageSpec, {
typeName: "storage",
get window() {
return this.parentActor.window;
},
--- a/devtools/server/tests/browser/browser_storage_cookies-duplicate-names.js
+++ b/devtools/server/tests/browser/browser_storage_cookies-duplicate-names.js
@@ -6,17 +6,17 @@
// Test that the storage panel is able to display multiple cookies with the same
// name (and different paths).
const {StorageFront} = require("devtools/shared/fronts/storage");
Services.scriptloader.loadSubScript("chrome://mochitests/content/browser/devtools/server/tests/browser/storage-helpers.js", this);
const TESTDATA = {
- "test1.example.org": [
+ "http://test1.example.org": [
{
name: "name",
value: "value1",
expires: 0,
path: "/",
host: "test1.example.org",
isDomain: false,
isSecure: false,
--- a/devtools/server/tests/browser/browser_storage_dynamic_windows.js
+++ b/devtools/server/tests/browser/browser_storage_dynamic_windows.js
@@ -4,18 +4,18 @@
"use strict";
const {StorageFront} = require("devtools/shared/fronts/storage");
Services.scriptloader.loadSubScript("chrome://mochitests/content/browser/devtools/server/tests/browser/storage-helpers.js", this);
const beforeReload = {
cookies: {
- "test1.example.org": ["c1", "cs2", "c3", "uc1"],
- "sectest1.example.org": ["uc1", "cs2"]
+ "http://test1.example.org": ["c1", "cs2", "c3", "uc1"],
+ "http://sectest1.example.org": ["uc1", "cs2"]
},
localStorage: {
"http://test1.example.org": ["ls1", "ls2"],
"http://sectest1.example.org": ["iframe-u-ls1"]
},
sessionStorage: {
"http://test1.example.org": ["ss1"],
"http://sectest1.example.org": ["iframe-u-ss1", "iframe-u-ss2"]
@@ -94,17 +94,22 @@ function testAddIframe(front) {
let shouldBeEmpty = {
localStorage: {
"https://sectest1.example.org": ["iframe-s-ls1"]
},
sessionStorage: {
"https://sectest1.example.org": ["iframe-s-ss1"]
},
cookies: {
- "sectest1.example.org": [
+ "https://sectest1.example.org": [
+ getCookieId("cs2", ".example.org", "/"),
+ getCookieId("sc1", "sectest1.example.org",
+ "/browser/devtools/server/tests/browser/")
+ ],
+ "http://sectest1.example.org": [
getCookieId("sc1", "sectest1.example.org",
"/browser/devtools/server/tests/browser/")
]
},
indexedDB: {
// empty because indexed db creation happens after the page load, so at
// the time of window-ready, there was no indexed db present.
"https://sectest1.example.org": []
--- a/devtools/server/tests/browser/browser_storage_listings.js
+++ b/devtools/server/tests/browser/browser_storage_listings.js
@@ -4,17 +4,17 @@
"use strict";
const {StorageFront} = require("devtools/shared/fronts/storage");
Services.scriptloader.loadSubScript("chrome://mochitests/content/browser/devtools/server/tests/browser/storage-helpers.js", this);
const storeMap = {
cookies: {
- "test1.example.org": [
+ "http://test1.example.org": [
{
name: "c1",
value: "foobar",
expires: 2000000000000,
path: "/browser",
host: "test1.example.org",
isDomain: false,
isSecure: false,
@@ -33,17 +33,39 @@ const storeMap = {
value: "foobar-2",
expires: 2000000001000,
path: "/",
host: "test1.example.org",
isDomain: false,
isSecure: true,
}
],
- "sectest1.example.org": [
+
+ "http://sectest1.example.org": [
+ {
+ name: "cs2",
+ value: "sessionCookie",
+ path: "/",
+ host: ".example.org",
+ expires: 0,
+ isDomain: true,
+ isSecure: false,
+ },
+ {
+ name: "sc1",
+ value: "foobar",
+ path: "/browser/devtools/server/tests/browser/",
+ host: "sectest1.example.org",
+ expires: 0,
+ isDomain: false,
+ isSecure: false,
+ }
+ ],
+
+ "https://sectest1.example.org": [
{
name: "uc1",
value: "foobar",
host: ".example.org",
path: "/",
expires: 0,
isDomain: true,
isSecure: true,
@@ -323,17 +345,17 @@ function* testStores(data) {
ok(data.indexedDB, "Indexed DB storage actor is present");
yield testCookies(data.cookies);
yield testLocalStorage(data.localStorage);
yield testSessionStorage(data.sessionStorage);
yield testIndexedDB(data.indexedDB);
}
function testCookies(cookiesActor) {
- is(Object.keys(cookiesActor.hosts).length, 2,
+ is(Object.keys(cookiesActor.hosts).length, 3,
"Correct number of host entries for cookies");
return testCookiesObjects(0, cookiesActor.hosts, cookiesActor);
}
var testCookiesObjects = Task.async(function* (index, hosts, cookiesActor) {
let host = Object.keys(hosts)[index];
let matchItems = data => {
let cookiesLength = 0;
--- a/devtools/server/tests/browser/browser_storage_updates.js
+++ b/devtools/server/tests/browser/browser_storage_updates.js
@@ -1,17 +1,17 @@
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const {StorageFront} = require("devtools/shared/fronts/storage");
const beforeReload = {
- cookies: ["test1.example.org", "sectest1.example.org"],
+ cookies: ["http://test1.example.org", "https://sectest1.example.org"],
localStorage: ["http://test1.example.org", "http://sectest1.example.org"],
sessionStorage: ["http://test1.example.org", "http://sectest1.example.org"],
};
const TESTS = [
// index 0
{
action: function (win) {
@@ -22,17 +22,17 @@ const TESTS = [
win.addCookie("c2", "foobar2");
info('win.localStorage.setItem("l1", "foobar1")');
win.localStorage.setItem("l1", "foobar1");
},
expected: {
added: {
cookies: {
- "test1.example.org": [
+ "http://test1.example.org": [
getCookieId("c1", "test1.example.org",
"/browser/devtools/server/tests/browser/"),
getCookieId("c2", "test1.example.org",
"/browser/devtools/server/tests/browser/")
]
},
localStorage: {
"http://test1.example.org": ["l1"]
@@ -48,17 +48,17 @@ const TESTS = [
win.addCookie("c1", "new_foobar1");
info('win.localStorage.setItem("l2", "foobar2")');
win.localStorage.setItem("l2", "foobar2");
},
expected: {
changed: {
cookies: {
- "test1.example.org": [
+ "http://test1.example.org": [
getCookieId("c1", "test1.example.org",
"/browser/devtools/server/tests/browser/"),
]
}
},
added: {
localStorage: {
"http://test1.example.org": ["l2"]
@@ -77,17 +77,17 @@ const TESTS = [
win.localStorage.removeItem("l1");
info('win.localStorage.setItem("l3", "foobar3")');
win.localStorage.setItem("l3", "foobar3");
},
expected: {
deleted: {
cookies: {
- "test1.example.org": [
+ "http://test1.example.org": [
getCookieId("c2", "test1.example.org",
"/browser/devtools/server/tests/browser/"),
]
},
localStorage: {
"http://test1.example.org": ["l1"]
}
},
@@ -118,33 +118,33 @@ const TESTS = [
win.sessionStorage.setItem("s2", "foobar2");
info('win.localStorage.setItem("l3", "new_foobar3")');
win.localStorage.setItem("l3", "new_foobar3");
},
expected: {
added: {
cookies: {
- "test1.example.org": [
+ "http://test1.example.org": [
getCookieId("c3", "test1.example.org",
"/browser/devtools/server/tests/browser/"),
]
},
sessionStorage: {
"http://test1.example.org": ["s1", "s2"]
}
},
changed: {
localStorage: {
"http://test1.example.org": ["l3"]
}
},
deleted: {
cookies: {
- "test1.example.org": [
+ "http://test1.example.org": [
getCookieId("c1", "test1.example.org",
"/browser/devtools/server/tests/browser/"),
]
},
localStorage: {
"http://test1.example.org": ["l2"]
}
}
@@ -170,17 +170,17 @@ const TESTS = [
{
action: function (win) {
info("win.clearCookies()");
win.clearCookies();
},
expected: {
deleted: {
cookies: {
- "test1.example.org": [
+ "http://test1.example.org": [
getCookieId("c3", "test1.example.org",
"/browser/devtools/server/tests/browser/"),
]
}
}
}
}
];