--- a/devtools/client/framework/test/shared-head.js
+++ b/devtools/client/framework/test/shared-head.js
@@ -106,25 +106,27 @@ registerCleanupFunction(function* cleanu
});
/**
* Add a new test tab in the browser and load the given url.
* @param {String} url The url to be loaded in the new tab
* @param {Object} options Object with various optional fields:
* - {Boolean} background If true, open the tab in background
* - {ChromeWindow} window Firefox top level window we should use to open the tab
+ * - {Number} userContextId The userContextId of the tab.
* @return a promise that resolves to the tab object when the url is loaded
*/
var addTab = Task.async(function* (url, options = { background: false, window: window }) {
info("Adding a new tab with URL: " + url);
let { background } = options;
let { gBrowser } = options.window ? options.window : window;
+ let { userContextId } = options;
- let tab = gBrowser.addTab(url);
+ let tab = gBrowser.addTab(url, {userContextId});
if (!background) {
gBrowser.selectedTab = tab;
}
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
info("Tab added and finished loading");
return tab;
--- a/devtools/client/storage/test/browser.ini
+++ b/devtools/client/storage/test/browser.ini
@@ -4,39 +4,46 @@ 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-usercontextid.html
storage-listings-with-fragment.html
storage-localstorage.html
storage-overflow.html
storage-search.html
storage-secured-iframe.html
+ storage-secured-iframe-usercontextid.html
storage-sessionstorage.html
storage-unsecured-iframe.html
+ storage-unsecured-iframe-usercontextid.html
storage-updates.html
head.js
!/devtools/client/framework/test/shared-head.js
[browser_storage_basic.js]
+[browser_storage_basic_usercontextid.js]
+tags = usercontextid
[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]
[browser_storage_delete_all.js]
[browser_storage_delete_tree.js]
+[browser_storage_delete_usercontextid.js]
+tags = usercontextid
[browser_storage_dom_cache_disabled.js]
[browser_storage_dynamic_updates_cookies.js]
[browser_storage_dynamic_updates_localStorage.js]
[browser_storage_dynamic_updates_sessionStorage.js]
[browser_storage_empty_objectstores.js]
[browser_storage_indexeddb_delete.js]
[browser_storage_indexeddb_delete_blocked.js]
[browser_storage_indexeddb_duplicate_names.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/storage/test/browser_storage_basic_usercontextid.js
@@ -0,0 +1,184 @@
+/* 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/. */
+
+// A test to check that the storage inspector is working correctly with
+// userContextId.
+
+"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"]],
+];
+
+const testCasesUserContextId = [
+ [
+ ["cookies", "http://test1.example.org"],
+ [
+ getCookieId("c1uc1", "test1.example.org", "/browser"),
+ getCookieId("cs2uc1", ".example.org", "/"),
+ getCookieId("c3uc1", "test1.example.org", "/"),
+ getCookieId("uc1uc1", ".example.org", "/")
+ ]
+ ],
+ [
+ ["cookies", "https://sectest1.example.org"],
+ [
+ getCookieId("uc1uc1", ".example.org", "/"),
+ getCookieId("cs2uc1", ".example.org", "/"),
+ getCookieId("sc1uc1", "sectest1.example.org",
+ "/browser/devtools/client/storage/test/")
+ ]
+ ],
+ [["localStorage", "http://test1.example.org"],
+ ["ls1uc1", "ls2uc1"]],
+ [["localStorage", "http://sectest1.example.org"],
+ ["iframe-u-ls1uc1"]],
+ [["localStorage", "https://sectest1.example.org"],
+ ["iframe-s-ls1uc1"]],
+ [["sessionStorage", "http://test1.example.org"],
+ ["ss1uc1"]],
+ [["sessionStorage", "http://sectest1.example.org"],
+ ["iframe-u-ss1uc1", "iframe-u-ss2uc1"]],
+ [["sessionStorage", "https://sectest1.example.org"],
+ ["iframe-s-ss1uc1"]],
+ [["indexedDB", "http://test1.example.org"],
+ ["idb1uc1 (default)", "idb2uc1 (default)"]],
+ [["indexedDB", "http://test1.example.org", "idb1uc1 (default)"],
+ ["obj1uc1", "obj2uc1"]],
+ [["indexedDB", "http://test1.example.org", "idb2uc1 (default)"],
+ ["obj3uc1"]],
+ [["indexedDB", "http://test1.example.org", "idb1uc1 (default)", "obj1uc1"],
+ [1, 2, 3]],
+ [["indexedDB", "http://test1.example.org", "idb1uc1 (default)", "obj2uc1"],
+ [1]],
+ [["indexedDB", "http://test1.example.org", "idb2uc1 (default)", "obj3uc1"],
+ []],
+ [["indexedDB", "http://sectest1.example.org"],
+ []],
+ [["indexedDB", "https://sectest1.example.org"],
+ ["idb-s1uc1 (default)", "idb-s2uc1 (default)"]],
+ [["indexedDB", "https://sectest1.example.org", "idb-s1uc1 (default)"],
+ ["obj-s1uc1"]],
+ [["indexedDB", "https://sectest1.example.org", "idb-s2uc1 (default)"],
+ ["obj-s2uc1"]],
+ [["indexedDB", "https://sectest1.example.org", "idb-s1uc1 (default)", "obj-s1uc1"],
+ [6, 7]],
+ [["indexedDB", "https://sectest1.example.org", "idb-s2uc1 (default)", "obj-s2uc1"],
+ [16]],
+ [["Cache", "http://test1.example.org", "plopuc1"],
+ [MAIN_DOMAIN + "404_cached_file.js",
+ MAIN_DOMAIN + "browser_storage_basic.js"]],
+];
+
+/**
+ * Test that the desired number of tree items are present
+ */
+function testTree(tests) {
+ let doc = gPanelWindow.document;
+ for (let [item] of tests) {
+ 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(tests) {
+ 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 tests[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 tests.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.html");
+
+ testTree(testCases);
+ yield testTables(testCases);
+
+ yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-listings-usercontextid.html",
+ {userContextId: 1});
+
+ testTree(testCasesUserContextId);
+ yield testTables(testCasesUserContextId);
+
+ yield finishTests();
+});
new file mode 100644
--- /dev/null
+++ b/devtools/client/storage/test/browser_storage_delete_usercontextid.js
@@ -0,0 +1,174 @@
+/* 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 ../../framework/test/shared-head.js */
+
+"use strict";
+
+// Test deleting storage items with userContextId.
+
+// The items that will be deleted.
+const TEST_CASES = [
+ [["localStorage", "http://test1.example.org"],
+ "ls1", "name"],
+ [["sessionStorage", "http://test1.example.org"],
+ "ss1", "name"],
+ [
+ ["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"],
+];
+
+// The storage items that should exist for default userContextId
+const storageItemsForDefault = [
+ [
+ ["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(tests) {
+ let doc = gPanelWindow.document;
+ for (let [item] of tests) {
+ 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(tests) {
+ 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 tests[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 tests.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* () {
+ // First, open a tab with the default userContextId and setup its storages.
+ let tabDefault = yield openTab(MAIN_DOMAIN + "storage-listings.html");
+
+ // Second, start testing for userContextId 1.
+ // We use the same item name as the default page has to see deleting items
+ // from userContextId 1 will affect default one or not.
+ yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-listings.html", {userContextId: 1});
+
+ let contextMenu = gPanelWindow.document.getElementById("storage-table-popup");
+ let menuDeleteItem = contextMenu.querySelector("#storage-table-popup-delete");
+
+ for (let [ treeItem, rowName, cellToClick] of TEST_CASES) {
+ let treeItemName = treeItem.join(" > ");
+
+ info(`Selecting tree item ${treeItemName}`);
+ yield selectTreeItem(treeItem);
+
+ let row = getRowCells(rowName);
+ ok(gUI.table.items.has(rowName), `There is a row '${rowName}' in ${treeItemName}`);
+
+ let eventWait = gUI.once("store-objects-updated");
+
+ yield waitForContextMenu(contextMenu, row[cellToClick], () => {
+ info(`Opened context menu in ${treeItemName}, row '${rowName}'`);
+ menuDeleteItem.click();
+ let truncatedRowName = String(rowName).replace(SEPARATOR_GUID, "-").substr(0, 16);
+ ok(menuDeleteItem.getAttribute("label").includes(truncatedRowName),
+ `Context menu item label contains '${rowName}' (maybe truncated)`);
+ });
+
+ yield eventWait;
+
+ ok(!gUI.table.items.has(rowName),
+ `There is no row '${rowName}' in ${treeItemName} after deletion`);
+ }
+
+ // Final, we see that the default tab is intact or not.
+ yield BrowserTestUtils.switchTab(gBrowser, tabDefault);
+ yield openStoragePanel();
+
+ testTree(storageItemsForDefault);
+ yield testTables(storageItemsForDefault);
+
+ yield finishTests();
+});
--- a/devtools/client/storage/test/head.js
+++ b/devtools/client/storage/test/head.js
@@ -44,26 +44,25 @@ registerCleanupFunction(() => {
Services.prefs.clearUserPref(DOM_CACHE);
Services.prefs.clearUserPref(DUMPEMIT_PREF);
Services.prefs.clearUserPref(SPLIT_CONSOLE_PREF);
Services.prefs.clearUserPref(STORAGE_PREF);
});
/**
* This generator function opens the given url in a new tab, then sets up the
- * page by waiting for all cookies, indexedDB items etc. to be created; Then
- * opens the storage inspector and waits for the storage tree and table to be
- * populated.
+ * page by waiting for all cookies, indexedDB items etc.
*
* @param url {String} The url to be opened in the new tab
+ * @param options {Object} The tab options for the new tab
*
- * @return {Promise} A promise that resolves after storage inspector is ready
+ * @return {Promise} A promise that resolves after the tab is ready
*/
-function* openTabAndSetupStorage(url) {
- let tab = yield addTab(url);
+function* openTab(url, options = {}) {
+ let tab = yield addTab(url, options);
let content = tab.linkedBrowser.contentWindow;
gWindow = content.wrappedJSObject;
// Setup the async storages in main window and for all its iframes
yield ContentTask.spawn(gBrowser.selectedBrowser, null, function* () {
/**
* Get all windows including frames recursively.
@@ -103,16 +102,34 @@ function* openTabAndSetupStorage(url) {
});
}
if (win.setup) {
yield win.setup();
}
}
});
+ return tab;
+}
+
+/**
+ * This generator function opens the given url in a new tab, then sets up the
+ * page by waiting for all cookies, indexedDB items etc. to be created; Then
+ * opens the storage inspector and waits for the storage tree and table to be
+ * populated.
+ *
+ * @param url {String} The url to be opened in the new tab
+ * @param options {Object} The tab options for the new tab
+ *
+ * @return {Promise} A promise that resolves after storage inspector is ready
+ */
+function* openTabAndSetupStorage(url, options = {}) {
+ // open tab
+ yield openTab(url, options);
+
// open storage inspector
return yield openStoragePanel();
}
/**
* Open the toolbox, with the storage tool visible.
*
* @param cb {Function} Optional callback, if you don't want to use the returned
@@ -199,56 +216,60 @@ function forceCollections() {
}
/**
* Cleans up and finishes the test
*/
function* finishTests() {
// Bug 1233497 makes it so that we can no longer yield CPOWs from Tasks.
// We work around this by calling clear() via a ContentTask instead.
- yield ContentTask.spawn(gBrowser.selectedBrowser, null, function* () {
- /**
- * Get all windows including frames recursively.
- *
- * @param {Window} [baseWindow]
- * The base window at which to start looking for child windows
- * (optional).
- * @return {Set}
- * A set of windows.
- */
- function getAllWindows(baseWindow) {
- let windows = new Set();
-
- let _getAllWindows = function (win) {
- windows.add(win.wrappedJSObject);
+ while (gBrowser.tabs.length > 1) {
+ yield ContentTask.spawn(gBrowser.selectedBrowser, null, function* () {
+ /**
+ * Get all windows including frames recursively.
+ *
+ * @param {Window} [baseWindow]
+ * The base window at which to start looking for child windows
+ * (optional).
+ * @return {Set}
+ * A set of windows.
+ */
+ function getAllWindows(baseWindow) {
+ let windows = new Set();
- for (let i = 0; i < win.length; i++) {
- _getAllWindows(win[i]);
- }
- };
- _getAllWindows(baseWindow);
-
- return windows;
- }
+ let _getAllWindows = function (win) {
+ windows.add(win.wrappedJSObject);
- let windows = getAllWindows(content);
- for (let win of windows) {
- // Some windows (e.g., about: URLs) don't have storage available
- try {
- win.localStorage.clear();
- win.sessionStorage.clear();
- } catch (ex) {
- // ignore
+ for (let i = 0; i < win.length; i++) {
+ _getAllWindows(win[i]);
+ }
+ };
+ _getAllWindows(baseWindow);
+
+ return windows;
}
- if (win.clear) {
- yield win.clear();
+ let windows = getAllWindows(content);
+ for (let win of windows) {
+ // Some windows (e.g., about: URLs) don't have storage available
+ try {
+ win.localStorage.clear();
+ win.sessionStorage.clear();
+ } catch (ex) {
+ // ignore
+ }
+
+ if (win.clear) {
+ yield win.clear();
+ }
}
- }
- });
+ });
+
+ yield closeTabAndToolbox(gBrowser.selectedTab);
+ }
Services.cookies.removeAll();
forceCollections();
finish();
}
// Sends a click event on the passed DOM node in an async manner
function* click(node) {
new file mode 100644
--- /dev/null
+++ b/devtools/client/storage/test/storage-listings-usercontextid.html
@@ -0,0 +1,131 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Storage inspector front end for userContextId - 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-usercontextid.html"></iframe>
+<iframe src="https://sectest1.example.org:443/browser/devtools/client/storage/test/storage-secured-iframe-usercontextid.html"></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 = "c1uc1=foobar; expires=" +
+ new Date(cookieExpiresTime1).toGMTString() + "; path=/browser";
+document.cookie = "cs2uc1=sessionCookie; path=/; domain=" + partialHostname;
+document.cookie = "c3uc1=foobar-2; expires=" +
+ new Date(cookieExpiresTime2).toGMTString() + "; path=/";
+// ... and some local storage items ..
+localStorage.setItem("ls1uc1", "foobar");
+localStorage.setItem("ls2uc1", "foobar-2");
+// ... and finally some session storage items too
+sessionStorage.setItem("ss1uc1", "foobar-3");
+dump("added cookies and storage from main page\n");
+
+let idbGenerator = async function() {
+ let request = indexedDB.open("idb1uc1", 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("obj1uc1", { keyPath: "id" });
+ store1.createIndex("name", "name", { unique: false });
+ store1.createIndex("email", "email", { unique: true });
+ let store2 = db.createObjectStore("obj2uc1", { keyPath: "id2" });
+ store1.transaction.oncomplete = () => {
+ done(db);
+ };
+ };
+ });
+
+ // Prevents AbortError
+ await new Promise(done => {
+ request.onsuccess = done;
+ });
+
+ let transaction = db.transaction(["obj1uc1", "obj2uc1"], "readwrite");
+ let store1 = transaction.objectStore("obj1uc1");
+ let store2 = transaction.objectStore("obj2uc1");
+ 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("idb2uc1", 1);
+ let db2 = await new Promise(done => {
+ request.onupgradeneeded = event => {
+ let db2 = event.target.result;
+ let store3 = db2.createObjectStore("obj3uc1", { 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("plopuc1");
+ 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("idb1uc1");
+ yield deleteDB("idb2uc1");
+
+ if (window.caches) {
+ yield caches.delete("plopuc1");
+ }
+
+ dump("removed indexedDB and cache data from " + document.location + "\n");
+};
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/devtools/client/storage/test/storage-secured-iframe-usercontextid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Iframe for testing multiple host detetion in storage actor
+-->
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+<script type="application/javascript;version=1.7">
+"use strict";
+document.cookie = "sc1uc1=foobar;";
+localStorage.setItem("iframe-s-ls1uc1", "foobar");
+sessionStorage.setItem("iframe-s-ss1uc1", "foobar-2");
+dump("added cookies and storage from secured iframe\n");
+
+let idbGenerator = function*() {
+ let request = indexedDB.open("idb-s1uc1", 1);
+ request.onerror = function() {
+ throw new Error("error opening db connection");
+ };
+ let db = yield new Promise(done => {
+ request.onupgradeneeded = event => {
+ let db = event.target.result;
+ let store1 = db.createObjectStore("obj-s1uc1", { keyPath: "id" });
+ store1.transaction.oncomplete = () => {
+ done(db);
+ };
+ };
+ });
+ yield new Promise(done => {
+ request.onsuccess = done;
+ });
+
+ let transaction = db.transaction(["obj-s1uc1"], "readwrite");
+ let store1 = transaction.objectStore("obj-s1uc1");
+ store1.add({id: 6, name: "foo", email: "foo@bar.com"});
+ store1.add({id: 7, name: "foo2", email: "foo2@bar.com"});
+ yield new Promise(success => {
+ transaction.oncomplete = success;
+ });
+
+ db.close();
+
+ request = indexedDB.open("idb-s2uc1", 1);
+ let db2 = yield new Promise(done => {
+ request.onupgradeneeded = event => {
+ let db2 = event.target.result;
+ let store3 =
+ db2.createObjectStore("obj-s2uc1", { keyPath: "id3", autoIncrement: true });
+ store3.createIndex("name2", "name2", { unique: true });
+ store3.transaction.oncomplete = () => {
+ done(db2);
+ };
+ };
+ });
+ yield new Promise(done => {
+ request.onsuccess = done;
+ });
+
+ transaction = db2.transaction(["obj-s2uc1"], "readwrite");
+ let store3 = transaction.objectStore("obj-s2uc1");
+ store3.add({id3: 16, name2: "foo", email: "foo@bar.com"});
+ yield new Promise(success => {
+ transaction.oncomplete = success;
+ });
+
+ db2.close();
+ dump("added indexedDB from secured iframe\n");
+};
+
+function deleteDB(dbName) {
+ return new Promise(resolve => {
+ dump("removing database " + dbName + " from " + document.location + "\n");
+ indexedDB.deleteDatabase(dbName).onsuccess = resolve;
+ });
+}
+
+window.setup = function*() {
+ yield idbGenerator();
+};
+
+window.clear = function*() {
+ yield deleteDB("idb-s1uc1");
+ yield deleteDB("idb-s2uc1");
+
+ dump("removed indexedDB data from " + document.location + "\n");
+};
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/devtools/client/storage/test/storage-unsecured-iframe-usercontextid.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Iframe for testing multiple host detetion in storage actor
+-->
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+<script>
+"use strict";
+document.cookie = "uc1uc1=foobar; domain=.example.org; path=/";
+localStorage.setItem("iframe-u-ls1uc1", "foobar");
+sessionStorage.setItem("iframe-u-ss1uc1", "foobar1");
+sessionStorage.setItem("iframe-u-ss2uc1", "foobar2");
+dump("added cookies and storage from unsecured iframe\n");
+</script>
+</body>
+</html>