Bug 1276339 - Storage inspector doesn't work on chrome:// pages and web extensions r=jdescottes
authorMichael Ratcliffe <mratcliffe@mozilla.com>
Tue, 22 Nov 2016 14:47:22 +0000
changeset 324669 8cdeaf29cac0a8708d02e31ae1723eb0fd351a68
parent 324636 b3e47c42f93f7e5d17e3fc0c33e8041337607aaa
child 324670 19d1b588f308767bbd3c8cc720f29b5e6ef70a3f
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersjdescottes
bugs1276339
milestone53.0a1
Bug 1276339 - Storage inspector doesn't work on chrome:// pages and web extensions r=jdescottes MozReview-Commit-ID: IP33bBo0yfn
devtools/client/locales/en-US/storage.properties
devtools/client/storage/test/browser.ini
devtools/client/storage/test/browser_storage_basic.js
devtools/client/storage/test/browser_storage_delete.js
devtools/client/storage/test/browser_storage_delete_all.js
devtools/client/storage/test/browser_storage_delete_tree.js
devtools/client/storage/test/browser_storage_empty_objectstores.js
devtools/client/storage/test/browser_storage_indexeddb_delete.js
devtools/client/storage/test/browser_storage_indexeddb_delete_blocked.js
devtools/client/storage/test/browser_storage_indexeddb_duplicate_names.js
devtools/client/storage/test/browser_storage_sidebar.js
devtools/client/storage/test/browser_storage_values.js
devtools/client/storage/test/head.js
devtools/client/storage/test/storage-indexeddb-duplicate-names.html
devtools/client/storage/ui.js
devtools/server/actors/storage.js
devtools/server/tests/browser/browser_storage_listings.js
devtools/shared/specs/storage.js
--- a/devtools/client/locales/en-US/storage.properties
+++ b/devtools/client/locales/en-US/storage.properties
@@ -55,17 +55,17 @@ table.headers.Cache.status=Status
 
 table.headers.indexedDB.name=Key
 table.headers.indexedDB.db=Database Name
 table.headers.indexedDB.objectStore=Object Store Name
 table.headers.indexedDB.value=Value
 table.headers.indexedDB.origin=Origin
 table.headers.indexedDB.version=Version
 table.headers.indexedDB.objectStores=Object Stores
-table.headers.indexedDB.keyPath=Key
+table.headers.indexedDB.keyPath2=Key Path
 table.headers.indexedDB.autoIncrement=Auto Increment
 table.headers.indexedDB.indexes=Indexes
 
 # LOCALIZATION NOTE (label.expires.session):
 # This string is displayed in the expires column when the cookie is Session
 # Cookie
 label.expires.session=Session
 
--- a/devtools/client/storage/test/browser.ini
+++ b/devtools/client/storage/test/browser.ini
@@ -2,16 +2,17 @@
 tags = devtools
 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-localstorage.html
   storage-overflow.html
   storage-search.html
   storage-secured-iframe.html
   storage-sessionstorage.html
   storage-unsecured-iframe.html
   storage-updates.html
@@ -30,16 +31,17 @@ support-files =
 [browser_storage_delete_all.js]
 [browser_storage_delete_tree.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]
 [browser_storage_localstorage_edit.js]
 [browser_storage_localstorage_error.js]
 [browser_storage_overflow.js]
 [browser_storage_search.js]
 [browser_storage_search_keyboard_trap.js]
 [browser_storage_sessionstorage_edit.js]
 [browser_storage_sidebar.js]
 [browser_storage_sidebar_update.js]
--- a/devtools/client/storage/test/browser_storage_basic.js
+++ b/devtools/client/storage/test/browser_storage_basic.js
@@ -48,38 +48,38 @@ const testCases = [
    ["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", "idb2"]],
-  [["indexedDB", "http://test1.example.org", "idb1"],
+   ["idb1 (default)", "idb2 (default)"]],
+  [["indexedDB", "http://test1.example.org", "idb1 (default)"],
    ["obj1", "obj2"]],
-  [["indexedDB", "http://test1.example.org", "idb2"],
+  [["indexedDB", "http://test1.example.org", "idb2 (default)"],
    ["obj3"]],
-  [["indexedDB", "http://test1.example.org", "idb1", "obj1"],
+  [["indexedDB", "http://test1.example.org", "idb1 (default)", "obj1"],
    [1, 2, 3]],
-  [["indexedDB", "http://test1.example.org", "idb1", "obj2"],
+  [["indexedDB", "http://test1.example.org", "idb1 (default)", "obj2"],
    [1]],
-  [["indexedDB", "http://test1.example.org", "idb2", "obj3"],
+  [["indexedDB", "http://test1.example.org", "idb2 (default)", "obj3"],
    []],
   [["indexedDB", "http://sectest1.example.org"],
    []],
   [["indexedDB", "https://sectest1.example.org"],
-   ["idb-s1", "idb-s2"]],
-  [["indexedDB", "https://sectest1.example.org", "idb-s1"],
+   ["idb-s1 (default)", "idb-s2 (default)"]],
+  [["indexedDB", "https://sectest1.example.org", "idb-s1 (default)"],
    ["obj-s1"]],
-  [["indexedDB", "https://sectest1.example.org", "idb-s2"],
+  [["indexedDB", "https://sectest1.example.org", "idb-s2 (default)"],
    ["obj-s2"]],
-  [["indexedDB", "https://sectest1.example.org", "idb-s1", "obj-s1"],
+  [["indexedDB", "https://sectest1.example.org", "idb-s1 (default)", "obj-s1"],
    [6, 7]],
-  [["indexedDB", "https://sectest1.example.org", "idb-s2", "obj-s2"],
+  [["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
--- a/devtools/client/storage/test/browser_storage_delete.js
+++ b/devtools/client/storage/test/browser_storage_delete.js
@@ -12,17 +12,17 @@ const TEST_CASES = [
   [["localStorage", "http://test1.example.org"],
     "ls1", "name"],
   [["sessionStorage", "http://test1.example.org"],
     "ss1", "name"],
   [
     ["cookies", "test1.example.org"],
     getCookieId("c1", "test1.example.org", "/browser"), "name"
   ],
-  [["indexedDB", "http://test1.example.org", "idb1", "obj1"],
+  [["indexedDB", "http://test1.example.org", "idb1 (default)", "obj1"],
     1, "name"],
   [["Cache", "http://test1.example.org", "plop"],
     MAIN_DOMAIN + "404_cached_file.js", "url"],
 ];
 
 add_task(function* () {
   yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-listings.html");
 
--- a/devtools/client/storage/test/browser_storage_delete_all.js
+++ b/devtools/client/storage/test/browser_storage_delete_all.js
@@ -24,29 +24,29 @@ add_task(function* () {
     [["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", "obj1"],
+    [["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"]],
   ];
 
   yield checkState(beforeState);
 
   info("do the delete");
   const deleteHosts = [
     [["localStorage", "https://sectest1.example.org"], "iframe-s-ls1", "name"],
     [["sessionStorage", "https://sectest1.example.org"], "iframe-s-ss1", "name"],
-    [["indexedDB", "http://test1.example.org", "idb1", "obj1"], 1, "name"],
+    [["indexedDB", "http://test1.example.org", "idb1 (default)", "obj1"], 1, "name"],
     [["Cache", "http://test1.example.org", "plop"],
       MAIN_DOMAIN + "404_cached_file.js", "url"],
   ];
 
   for (let [store, rowName, cellToClick] of deleteHosts) {
     let storeName = store.join(" > ");
 
     yield selectTreeItem(store);
@@ -73,17 +73,17 @@ add_task(function* () {
     [["localStorage", "https://sectest1.example.org"],
       []],
     [["sessionStorage", "http://test1.example.org"],
       ["ss1"]],
     [["sessionStorage", "http://sectest1.example.org"],
       ["iframe-u-ss1", "iframe-u-ss2"]],
     [["sessionStorage", "https://sectest1.example.org"],
       []],
-    [["indexedDB", "http://test1.example.org", "idb1", "obj1"],
+    [["indexedDB", "http://test1.example.org", "idb1 (default)", "obj1"],
       []],
     [["Cache", "http://test1.example.org", "plop"],
       []],
   ];
 
   yield checkState(afterState);
 
   yield finishTests();
--- a/devtools/client/storage/test/browser_storage_delete_tree.js
+++ b/devtools/client/storage/test/browser_storage_delete_tree.js
@@ -23,27 +23,27 @@ add_task(function* () {
         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", "obj1"], [1, 2, 3]],
+    [["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"],
     ["localStorage", "http://test1.example.org"],
     ["sessionStorage", "http://test1.example.org"],
-    ["indexedDB", "http://test1.example.org", "idb1", "obj1"],
+    ["indexedDB", "http://test1.example.org", "idb1 (default)", "obj1"],
     ["Cache", "http://test1.example.org", "plop"],
   ];
 
   for (let store of deleteHosts) {
     let storeName = store.join(" > ");
 
     yield selectTreeItem(store);
 
@@ -62,14 +62,14 @@ add_task(function* () {
     yield eventWait;
   }
 
   info("test state after delete");
   yield checkState([
     [["cookies", "test1.example.org"], []],
     [["localStorage", "http://test1.example.org"], []],
     [["sessionStorage", "http://test1.example.org"], []],
-    [["indexedDB", "http://test1.example.org", "idb1", "obj1"], []],
+    [["indexedDB", "http://test1.example.org", "idb1 (default)", "obj1"], []],
     [["Cache", "http://test1.example.org", "plop"], []],
   ]);
 
   yield finishTests();
 });
--- a/devtools/client/storage/test/browser_storage_empty_objectstores.js
+++ b/devtools/client/storage/test/browser_storage_empty_objectstores.js
@@ -16,24 +16,24 @@
 //   - 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
 const storeItems = [
   [["indexedDB", "http://test1.example.org"],
-   ["idb1", "idb2"]],
-  [["indexedDB", "http://test1.example.org", "idb1"],
+   ["idb1 (default)", "idb2 (default)"]],
+  [["indexedDB", "http://test1.example.org", "idb1 (default)"],
    ["obj1", "obj2"]],
-  [["indexedDB", "http://test1.example.org", "idb2"],
+  [["indexedDB", "http://test1.example.org", "idb2 (default)"],
    []],
-  [["indexedDB", "http://test1.example.org", "idb1", "obj1"],
+  [["indexedDB", "http://test1.example.org", "idb1 (default)", "obj1"],
    [1, 2, 3]],
-  [["indexedDB", "http://test1.example.org", "idb1", "obj2"],
+  [["indexedDB", "http://test1.example.org", "idb1 (default)", "obj2"],
    [1]]
 ];
 
 /**
  * Test that the desired number of tree items are present
  */
 function testTree() {
   let doc = gPanelWindow.document;
--- a/devtools/client/storage/test/browser_storage_indexeddb_delete.js
+++ b/devtools/client/storage/test/browser_storage_indexeddb_delete.js
@@ -11,21 +11,21 @@
 add_task(function* () {
   yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-empty-objectstores.html");
 
   let contextMenu = gPanelWindow.document.getElementById("storage-tree-popup");
   let menuDeleteDb = contextMenu.querySelector("#storage-tree-popup-delete");
 
   info("test state before delete");
   yield checkState([
-    [["indexedDB", "http://test1.example.org"], ["idb1", "idb2"]],
+    [["indexedDB", "http://test1.example.org"], ["idb1 (default)", "idb2 (default)"]],
   ]);
 
   info("do the delete");
-  const deletedDb = ["indexedDB", "http://test1.example.org", "idb1"];
+  const deletedDb = ["indexedDB", "http://test1.example.org", "idb1 (default)"];
 
   yield selectTreeItem(deletedDb);
 
   // Wait once for update and another time for value fetching
   let eventWait = gUI.once("store-objects-updated").then(
     () => gUI.once("store-objects-updated"));
 
   let selector = `[data-id='${JSON.stringify(deletedDb)}'] > .tree-widget-item`;
@@ -35,13 +35,13 @@ add_task(function* () {
     info(`Opened tree context menu in ${deletedDb.join(" > ")}`);
     menuDeleteDb.click();
   });
 
   yield eventWait;
 
   info("test state after delete");
   yield checkState([
-    [["indexedDB", "http://test1.example.org"], ["idb2"]],
+    [["indexedDB", "http://test1.example.org"], ["idb2 (default)"]],
   ]);
 
   yield finishTests();
 });
--- a/devtools/client/storage/test/browser_storage_indexeddb_delete_blocked.js
+++ b/devtools/client/storage/test/browser_storage_indexeddb_delete_blocked.js
@@ -8,29 +8,29 @@
 
 // Test what happens when deleting indexedDB database is blocked
 
 add_task(function* () {
   yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-idb-delete-blocked.html");
 
   info("test state before delete");
   yield checkState([
-    [["indexedDB", "http://test1.example.org"], ["idb"]]
+    [["indexedDB", "http://test1.example.org"], ["idb (default)"]]
   ]);
 
   info("do the delete");
   yield selectTreeItem(["indexedDB", "http://test1.example.org"]);
   let actor = gUI.getCurrentActor();
-  let result = yield actor.removeDatabase("http://test1.example.org", "idb");
+  let result = yield actor.removeDatabase("http://test1.example.org", "idb (default)");
 
   ok(result.blocked, "removeDatabase attempt is blocked");
 
   info("test state after blocked delete");
   yield checkState([
-    [["indexedDB", "http://test1.example.org"], ["idb"]]
+    [["indexedDB", "http://test1.example.org"], ["idb (default)"]]
   ]);
 
   let eventWait = gUI.once("store-objects-updated");
 
   info("telling content to close the db");
   yield ContentTask.spawn(gBrowser.selectedBrowser, null, function* () {
     let win = content.wrappedJSObject;
     yield win.closeDb();
@@ -42,17 +42,17 @@ add_task(function* () {
   info("test state after real delete");
   yield checkState([
     [["indexedDB", "http://test1.example.org"], []]
   ]);
 
   info("try to delete database from nonexistent host");
   let errorThrown = false;
   try {
-    result = yield actor.removeDatabase("http://test2.example.org", "idb");
+    result = yield actor.removeDatabase("http://test2.example.org", "idb (default)");
   } catch (ex) {
     errorThrown = true;
   }
 
   ok(errorThrown, "error was reported when trying to delete");
 
   yield finishTests();
 });
new file mode 100644
--- /dev/null
+++ b/devtools/client/storage/test/browser_storage_indexeddb_duplicate_names.js
@@ -0,0 +1,31 @@
+/* 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 to verify that indexedDBs with duplicate names (different types / paths)
+// work as expected.
+
+"use strict";
+
+add_task(function* () {
+  const TESTPAGE = MAIN_DOMAIN + "storage-indexeddb-duplicate-names.html";
+
+  setPermission(TESTPAGE, "indexedDB");
+
+  yield openTabAndSetupStorage(TESTPAGE);
+
+  yield checkState([
+    [
+      ["indexedDB", "http://test1.example.org"], [
+        "idb1 (default)",
+        "idb1 (temporary)",
+        "idb1 (persistent)",
+        "idb2 (default)",
+        "idb2 (temporary)",
+        "idb2 (persistent)"
+      ]
+    ]
+  ]);
+
+  yield finishTests();
+});
--- a/devtools/client/storage/test/browser_storage_sidebar.js
+++ b/devtools/client/storage/test/browser_storage_sidebar.js
@@ -67,27 +67,27 @@ const testCases = [
     sendEscape: true
   },
 
   {
     location: ["indexedDB", "http://test1.example.org"],
     sidebarHidden: true
   },
   {
-    location: "idb2",
+    location: "idb2 (default)",
     sidebarHidden: false
   },
 
   {
-    location: ["indexedDB", "http://test1.example.org", "idb2", "obj3"],
+    location: ["indexedDB", "http://test1.example.org", "idb2 (default)", "obj3"],
     sidebarHidden: true
   },
 
   {
-    location: ["indexedDB", "https://sectest1.example.org", "idb-s2"],
+    location: ["indexedDB", "https://sectest1.example.org", "idb-s2 (default)"],
     sidebarHidden: true
   },
   {
     location: "obj-s2",
     sidebarHidden: false
   },
   {
     sendEscape: true
--- a/devtools/client/storage/test/browser_storage_values.js
+++ b/devtools/client/storage/test/browser_storage_values.js
@@ -119,26 +119,26 @@ const testCases = [
   ["ss5", [
     {name: "ss5", value: "Array"},
     {name: "ss5.0", value: LONG_WORD},
     {name: "ss5.1", value: LONG_WORD},
     {name: "ss5.2", value: LONG_WORD},
     {name: "ss5.3", value: `${LONG_WORD}&${LONG_WORD}`},
     {name: "ss5.4", value: `${LONG_WORD}&${LONG_WORD}`},
   ], true],
-  [["indexedDB", "http://test1.example.org", "idb1", "obj1"]],
+  [["indexedDB", "http://test1.example.org", "idb1 (default)", "obj1"]],
   [1, [
     {name: 1, value: JSON.stringify({id: 1, name: "foo", email: "foo@bar.com"})}
   ]],
   [null, [
     {name: "1.id", value: "1"},
     {name: "1.name", value: "foo"},
     {name: "1.email", value: "foo@bar.com"},
   ], true],
-  [["indexedDB", "http://test1.example.org", "idb1", "obj2"]],
+  [["indexedDB", "http://test1.example.org", "idb1 (default)", "obj2"]],
   [1, [
     {name: 1, value: JSON.stringify({
       id2: 1, name: "foo", email: "foo@bar.com", extra: "baz"
     })}
   ]],
   [null, [
     {name: "1.id2", value: "1"},
     {name: "1.name", value: "foo"},
--- a/devtools/client/storage/test/head.js
+++ b/devtools/client/storage/test/head.js
@@ -875,8 +875,24 @@ var focusSearchBoxUsingShortcut = Task.a
   if (callback) {
     callback();
   }
 });
 
 function getCookieId(name, domain, path) {
   return `${name}${SEPARATOR_GUID}${domain}${SEPARATOR_GUID}${path}`;
 }
+
+function setPermission(url, permission) {
+  const nsIPermissionManager = Components.interfaces.nsIPermissionManager;
+
+  let uri = Components.classes["@mozilla.org/network/io-service;1"]
+                      .getService(Components.interfaces.nsIIOService)
+                      .newURI(url, null, null);
+  let ssm = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
+                      .getService(Ci.nsIScriptSecurityManager);
+  let principal = ssm.createCodebasePrincipal(uri, {});
+
+  Components.classes["@mozilla.org/permissionmanager;1"]
+            .getService(nsIPermissionManager)
+            .addFromPrincipal(principal, permission,
+                              nsIPermissionManager.ALLOW_ACTION);
+}
new file mode 100644
--- /dev/null
+++ b/devtools/client/storage/test/storage-indexeddb-duplicate-names.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+  <meta charset="utf-8">
+  <title>Storage inspector IndexedDBs with duplicate names</title>
+
+  <script type="application/javascript;version=1.7">
+    "use strict";
+
+    function createIndexedDBs() {
+      createIndexedDB("idb1", "temporary");
+      createIndexedDB("idb1", "default");
+      createIndexedDB("idb1", "persistent");
+      createIndexedDB("idb2", "temporary");
+      createIndexedDB("idb2", "default");
+      createIndexedDB("idb2", "persistent");
+    }
+
+    function createIndexedDB(name, storage) {
+      let open = indexedDB.open(name, {storage: storage});
+
+      open.onsuccess = function () {
+        let db = open.result;
+        db.close();
+      };
+    }
+
+    function deleteDB(dbName, storage) {
+      return new Promise(resolve => {
+        dump(`removing database ${dbName} (${storage}) from ${document.location}\n`);
+        indexedDB.deleteDatabase(dbName, { storage: storage }).onsuccess = resolve;
+      });
+    }
+
+    window.clear = function* () {
+      yield deleteDB("idb1", "temporary");
+      yield deleteDB("idb1", "default");
+      yield deleteDB("idb1", "persistent");
+      yield deleteDB("idb2", "temporary");
+      yield deleteDB("idb2", "default");
+      yield deleteDB("idb2", "persistent");
+
+      dump(`removed indexedDB data from ${document.location}\n`);
+    };
+  </script>
+</head>
+<body onload="createIndexedDBs()">
+  <h1>storage-indexeddb-duplicate-names.html</h1>
+</body>
+</html>
--- a/devtools/client/storage/ui.js
+++ b/devtools/client/storage/ui.js
@@ -804,17 +804,20 @@ StorageUI.prototype = {
 
       if (f.private) {
         privateFields.push(f.name);
       }
 
       columns[f.name] = f.name;
       let columnName;
       try {
-        columnName = L10N.getStr("table.headers." + type + "." + f.name);
+        // Path key names for l10n in the case of a string change.
+        let name = f.name === "keyPath" ? "keyPath2" : f.name;
+
+        columnName = L10N.getStr("table.headers." + type + "." + name);
       } catch (e) {
         columnName = COOKIE_KEY_MAP[f.name];
       }
 
       if (!columnName) {
         console.error("Unable to localize table header type:" + type + " key:" + f.name);
       } else {
         columns[f.name] = columnName;
--- a/devtools/server/actors/storage.js
+++ b/devtools/server/actors/storage.js
@@ -1,12 +1,14 @@
 /* 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/. */
 
+/* globals StopIteration */
+
 "use strict";
 
 const {Cc, Ci, Cu, CC} = require("chrome");
 const events = require("sdk/event/core");
 const protocol = require("devtools/shared/protocol");
 const {LongStringActor} = require("devtools/server/actors/string");
 const {DebuggerServer} = require("devtools/server/main");
 const Services = require("Services");
@@ -88,17 +90,17 @@ var StorageActors = {};
  * Creates a default object with the common methods required by all storage
  * actors.
  *
  * This default object is missing a couple of required methods that should be
  * implemented seperately for each actor. They are namely:
  *   - observe : Method which gets triggered on the notificaiton of the watched
  *               topic.
  *   - getNamesForHost : Given a host, get list of all known store names.
- *   - getValuesForHost : Given a host (and optianally a name) get all known
+ *   - getValuesForHost : Given a host (and optionally a name) get all known
  *                        store objects.
  *   - toStoreObject : Given a store object, convert it to the required format
  *                     so that it can be transferred over wire.
  *   - populateStoresForHost : Given a host, populate the map of all store
  *                             objects for it
  *   - getFields: Given a subType(optional), get an array of objects containing
  *                column field info. The info includes,
  *                "name" is name of colume key.
@@ -136,16 +138,19 @@ StorageActors.defaults = function (typeN
     get windows() {
       return this.storageActor.windows;
     },
 
     /**
      * Converts the window.location object into host.
      */
     getHostName(location) {
+      if (location.protocol === "chrome:") {
+        return location.href;
+      }
       return location.hostname || location.href;
     },
 
     initialize(storageActor) {
       protocol.Actor.prototype.initialize.call(this, null);
 
       this.storageActor = storageActor;
 
@@ -746,16 +751,17 @@ var cookieHelpers = {
     let {field, oldValue, newValue} = data;
     let origName = field === "name" ? oldValue : data.items.name;
     let origHost = field === "host" ? oldValue : data.items.host;
     let origPath = field === "path" ? oldValue : data.items.path;
     let cookie = null;
 
     let enumerator =
       Services.cookies.getCookiesFromHost(origHost, data.originAttributes || {});
+
     while (enumerator.hasMoreElements()) {
       let nsiCookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
       if (nsiCookie.name === origName &&
           nsiCookie.host === origHost &&
           nsiCookie.path === origPath) {
         cookie = {
           host: nsiCookie.host,
           path: nsiCookie.path,
@@ -1043,16 +1049,19 @@ function getObjectForLocalOrSessionStora
         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}`);
@@ -1253,16 +1262,19 @@ StorageActors.createActor({
       { 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())) {
@@ -1425,22 +1437,25 @@ ObjectStoreMetadata.prototype = {
 
 /**
  * Meta data object for a particular indexed db in a host.
  *
  * @param {string} origin
  *        The host associated with this indexed db.
  * @param {IDBDatabase} db
  *        The particular indexed db.
+ * @param {String} storage
+ *        Storage type, either "temporary", "default" or "persistent".
  */
-function DatabaseMetadata(origin, db) {
+function DatabaseMetadata(origin, db, storage) {
   this._origin = origin;
   this._name = db.name;
   this._version = db.version;
   this._objectStores = [];
+  this.storage = storage;
 
   if (db.objectStoreNames.length) {
     let transaction = db.transaction(db.objectStoreNames, "readonly");
 
     for (let i = 0; i < transaction.objectStoreNames.length; i++) {
       let objectStore =
         transaction.objectStore(transaction.objectStoreNames[i]);
       this._objectStores.push([transaction.objectStoreNames[i],
@@ -1450,17 +1465,17 @@ function DatabaseMetadata(origin, db) {
 }
 DatabaseMetadata.prototype = {
   get objectStores() {
     return this._objectStores;
   },
 
   toObject() {
     return {
-      name: this._name,
+      name: `${this._name} (${this.storage})`,
       origin: this._origin,
       version: this._version,
       objectStores: this._objectStores.size
     };
   }
 };
 
 StorageActors.createActor({
@@ -1530,16 +1545,19 @@ StorageActors.createActor({
     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.
    */
@@ -1622,25 +1640,27 @@ StorageActors.createActor({
     for (let host of this.hosts) {
       yield this.populateStoresForHost(host);
     }
   }),
 
   populateStoresForHost: Task.async(function* (host) {
     let storeMap = new Map();
     let {names} = yield this.getDBNamesForHost(host);
+
     let win = this.storageActor.getWindowFromHost(host);
     if (win) {
       let principal = win.document.nodePrincipal;
 
-      for (let name of names) {
-        let metadata = yield this.getDBMetaData(host, principal, name);
+      for (let {name, storage} of names) {
+        let metadata = yield this.getDBMetaData(host, principal, name, storage);
 
         metadata = indexedDBHelpers.patchMetadataMapsAndProtos(metadata);
-        storeMap.set(name, metadata);
+
+        storeMap.set(`${name} (${storage})`, metadata);
       }
     }
 
     this.hostVsStores.set(host, storeMap);
   }),
 
   /**
    * Returns the over-the-wire implementation of the indexed db entity.
@@ -1663,20 +1683,32 @@ StorageActors.createActor({
       // DB meta data
       return {
         db: item.name,
         origin: item.origin,
         version: item.version,
         objectStores: item.objectStores
       };
     }
+
+    let value = JSON.stringify(item.value);
+
+    // FIXME: Bug 1318029 - Due to a bug that is thrown whenever a
+    // LongStringActor string reaches DebuggerServer.LONG_STRING_LENGTH we need
+    // to trim the value. When the bug is fixed we should stop trimming the
+    // string here.
+    let maxLength = DebuggerServer.LONG_STRING_LENGTH - 1;
+    if (value.length > maxLength) {
+      value = value.substr(0, maxLength);
+    }
+
     // Indexed db entry
     return {
       name: item.name,
-      value: new LongStringActor(this.conn, JSON.stringify(item.value))
+      value: new LongStringActor(this.conn, value)
     };
   },
 
   form(form, detail) {
     if (detail === "actorid") {
       return this.actorID;
     }
 
@@ -1702,38 +1734,41 @@ StorageActors.createActor({
     this.storageActor.update(action, "indexedDB", {
       [host]: [ JSON.stringify(path) ]
     });
   },
 
   maybeSetupChildProcess() {
     if (!DebuggerServer.isInChildProcess) {
       this.backToChild = (func, rv) => rv;
+      this.clearDBStore = indexedDBHelpers.clearDBStore;
+      this.gatherFilesOrFolders = indexedDBHelpers.gatherFilesOrFolders;
       this.getDBMetaData = indexedDBHelpers.getDBMetaData;
-      this.openWithPrincipal = indexedDBHelpers.openWithPrincipal;
       this.getDBNamesForHost = indexedDBHelpers.getDBNamesForHost;
+      this.getNameFromDatabaseFile = indexedDBHelpers.getNameFromDatabaseFile;
+      this.getObjectStoreData = indexedDBHelpers.getObjectStoreData;
       this.getSanitizedHost = indexedDBHelpers.getSanitizedHost;
-      this.getNameFromDatabaseFile = indexedDBHelpers.getNameFromDatabaseFile;
       this.getValuesForHost = indexedDBHelpers.getValuesForHost;
-      this.getObjectStoreData = indexedDBHelpers.getObjectStoreData;
+      this.openWithPrincipal = indexedDBHelpers.openWithPrincipal;
       this.removeDB = indexedDBHelpers.removeDB;
       this.removeDBRecord = indexedDBHelpers.removeDBRecord;
-      this.clearDBStore = indexedDBHelpers.clearDBStore;
+      this.splitNameAndStorage = indexedDBHelpers.splitNameAndStorage;
       return;
     }
 
     const { sendAsyncMessage, addMessageListener } =
       this.conn.parentMessageManager;
 
     this.conn.setupInParent({
       module: "devtools/server/actors/storage",
       setupParent: "setupParentProcessForIndexedDB"
     });
 
     this.getDBMetaData = callParentProcessAsync.bind(null, "getDBMetaData");
+    this.splitNameAndStorage = callParentProcessAsync.bind(null, "splitNameAndStorage");
     this.getDBNamesForHost = callParentProcessAsync.bind(null, "getDBNamesForHost");
     this.getValuesForHost = callParentProcessAsync.bind(null, "getValuesForHost");
     this.removeDB = callParentProcessAsync.bind(null, "removeDB");
     this.removeDBRecord = callParentProcessAsync.bind(null, "removeDBRecord");
     this.clearDBStore = callParentProcessAsync.bind(null, "clearDBStore");
 
     addMessageListener("debug:storage-indexedDB-request-child", msg => {
       switch (msg.json.method) {
@@ -1819,51 +1854,66 @@ var indexedDBHelpers = {
     });
   },
 
   /**
    * Fetches and stores all the metadata information for the given database
    * `name` for the given `host` with its `principal`. The stored metadata
    * information is of `DatabaseMetadata` type.
    */
-  getDBMetaData: Task.async(function* (host, principal, name) {
-    let request = this.openWithPrincipal(principal, name);
+  getDBMetaData: Task.async(function* (host, principal, name, storage) {
+    let request = this.openWithPrincipal(principal, name, storage);
     let success = promise.defer();
 
     request.onsuccess = event => {
       let db = event.target.result;
-
-      let dbData = new DatabaseMetadata(host, db);
+      let dbData = new DatabaseMetadata(host, db, storage);
       db.close();
 
       success.resolve(this.backToChild("getDBMetaData", dbData));
     };
     request.onerror = ({target}) => {
       console.error(
         `Error opening indexeddb database ${name} for host ${host}`, target.error);
       success.resolve(this.backToChild("getDBMetaData", null));
     };
     return success.promise;
   }),
 
+  splitNameAndStorage: function (name) {
+    let lastOpenBracketIndex = name.lastIndexOf("(");
+    let lastCloseBracketIndex = name.lastIndexOf(")");
+    let delta = lastCloseBracketIndex - lastOpenBracketIndex - 1;
+
+    let storage = name.substr(lastOpenBracketIndex + 1, delta);
+
+    name = name.substr(0, lastOpenBracketIndex - 1);
+
+    return { storage, name };
+  },
+
   /**
    * Opens an indexed db connection for the given `principal` and
    * database `name`.
    */
-  openWithPrincipal(principal, name) {
-    return indexedDBForStorage.openForPrincipal(principal, name);
+  openWithPrincipal: function (principal, name, storage) {
+    return indexedDBForStorage.openForPrincipal(principal, name,
+                                                { storage: storage });
   },
 
-  removeDB: Task.async(function* (host, principal, name) {
+  removeDB: Task.async(function* (host, principal, dbName) {
     let result = new promise(resolve => {
-      let request = indexedDBForStorage.deleteForPrincipal(principal, name);
+      let {name, storage} = this.splitNameAndStorage(dbName);
+      let request =
+        indexedDBForStorage.deleteForPrincipal(principal, name,
+                                               { storage: storage });
 
       request.onsuccess = () => {
         resolve({});
-        this.onItemUpdated("deleted", host, [name]);
+        this.onItemUpdated("deleted", host, [dbName]);
       };
 
       request.onblocked = () => {
         console.warn(`Deleting indexedDB database ${name} for host ${host} is blocked`);
         resolve({ blocked: true });
       };
 
       request.onerror = () => {
@@ -1879,20 +1929,21 @@ var indexedDBHelpers = {
       setTimeout(() => resolve({ blocked: true }), 3000);
     });
 
     return this.backToChild("removeDB", yield result);
   }),
 
   removeDBRecord: Task.async(function* (host, principal, dbName, storeName, id) {
     let db;
+    let {name, storage} = this.splitNameAndStorage(dbName);
 
     try {
       db = yield new promise((resolve, reject) => {
-        let request = this.openWithPrincipal(principal, dbName);
+        let request = this.openWithPrincipal(principal, name, storage);
         request.onsuccess = ev => resolve(ev.target.result);
         request.onerror = ev => reject(ev.target.error);
       });
 
       let transaction = db.transaction(storeName, "readwrite");
       let store = transaction.objectStore(storeName);
 
       yield new promise((resolve, reject) => {
@@ -1911,20 +1962,21 @@ var indexedDBHelpers = {
       db.close();
     }
 
     return this.backToChild("removeDBRecord", null);
   }),
 
   clearDBStore: Task.async(function* (host, principal, dbName, storeName) {
     let db;
+    let {name, storage} = this.splitNameAndStorage(dbName);
 
     try {
       db = yield new promise((resolve, reject) => {
-        let request = this.openWithPrincipal(principal, dbName);
+        let request = this.openWithPrincipal(principal, name, storage);
         request.onsuccess = ev => resolve(ev.target.result);
         request.onerror = ev => reject(ev.target.error);
       });
 
       let transaction = db.transaction(storeName, "readwrite");
       let store = transaction.objectStore(storeName);
 
       yield new promise((resolve, reject) => {
@@ -1946,77 +1998,141 @@ var indexedDBHelpers = {
     return this.backToChild("clearDBStore", null);
   }),
 
   /**
    * Fetches all the databases and their metadata for the given `host`.
    */
   getDBNamesForHost: Task.async(function* (host) {
     let sanitizedHost = this.getSanitizedHost(host);
-    let directory = OS.Path.join(OS.Constants.Path.profileDir, "storage",
-                                 "default", sanitizedHost, "idb");
+    let profileDir = OS.Constants.Path.profileDir;
+    let files = [];
+    let names = [];
+    let storagePath = OS.Path.join(profileDir, "storage");
 
-    let exists = yield OS.File.exists(directory);
-    if (!exists && host.startsWith("about:")) {
-      // try for moz-safe-about directory
-      sanitizedHost = this.getSanitizedHost("moz-safe-" + host);
-      directory = OS.Path.join(OS.Constants.Path.profileDir, "storage",
-                               "permanent", sanitizedHost, "idb");
-      exists = yield OS.File.exists(directory);
-    }
-    if (!exists) {
-      return this.backToChild("getDBNamesForHost", {names: []});
+    // We expect sqlite DB paths to look something like this:
+    // - PathToProfileDir/storage/default/http+++www.example.com/
+    //   idb/1556056096MeysDaabta.sqlite
+    // - PathToProfileDir/storage/permanent/http+++www.example.com/
+    //   idb/1556056096MeysDaabta.sqlite
+    // - PathToProfileDir/storage/temporary/http+++www.example.com/
+    //   idb/1556056096MeysDaabta.sqlite
+    //
+    // The subdirectory inside the storage folder is determined by the storage
+    // type:
+    // - default:   { storage: "default" } or not specified.
+    // - permanent: { storage: "persistent" }.
+    // - temporary: { storage: "temporary" }.
+    let sqliteFiles = yield this.gatherFilesOrFolders(storagePath, path => {
+      if (path.endsWith(".sqlite")) {
+        let { components } = OS.Path.split(path);
+        let isIDB = components[components.length - 2] === "idb";
+
+        return isIDB;
+      }
+      return false;
+    });
+
+    for (let file of sqliteFiles) {
+      let splitPath = OS.Path.split(file).components;
+      let idbIndex = splitPath.indexOf("idb");
+      let name = splitPath[idbIndex - 1];
+      let storage = splitPath[idbIndex - 2];
+      let relative = file.substr(profileDir.length + 1);
+
+      if (name.startsWith(sanitizedHost)) {
+        files.push({
+          file: relative,
+          storage: storage === "permanent" ? "persistent" : storage
+        });
+      }
     }
 
-    let names = [];
-    let dirIterator = new OS.File.DirectoryIterator(directory);
-    try {
-      yield dirIterator.forEach(file => {
-        // Skip directories.
-        if (file.isDir) {
-          return null;
-        }
-
-        // Skip any non-sqlite files.
-        if (!file.name.endsWith(".sqlite")) {
-          return null;
+    if (files.length > 0) {
+      for (let {file, storage} of files) {
+        let name = yield this.getNameFromDatabaseFile(file);
+        if (name) {
+          names.push({
+            name,
+            storage
+          });
         }
+      }
+    }
 
-        return this.getNameFromDatabaseFile(file.path).then(name => {
-          if (name) {
-            names.push(name);
+    return this.backToChild("getDBNamesForHost", {names});
+  }),
+
+  /**
+   * Gather together all of the files in path and pass each path through a
+   * validation function.
+   *
+   * @param {String}
+   *        Path in which to begin searching.
+   * @param {Function}
+   *        Validation function, which checks each file path. If this function
+   *        Returns true the file path is kept.
+   *
+   * @returns {Array}
+   *          An array of file paths.
+   */
+  gatherFilesOrFolders: Task.async(function* (path, validationFunc) {
+    let files = [];
+    let iterator;
+    let paths = [path];
+
+    while (paths.length > 0) {
+      try {
+        iterator = new OS.File.DirectoryIterator(paths.pop());
+
+        for (let child in iterator) {
+          child = yield child;
+
+          path = child.path;
+
+          if (child.isDir) {
+            paths.push(path);
+          } else if (validationFunc(path)) {
+            files.push(path);
           }
-          return null;
-        });
-      });
-    } finally {
-      dirIterator.close();
+        }
+      } catch (ex) {
+        // Ignore StopIteration to prevent exiting the loop.
+        if (ex != StopIteration) {
+          throw ex;
+        }
+      }
     }
-    return this.backToChild("getDBNamesForHost", {names: names});
+    iterator.close();
+
+    return files;
   }),
 
   /**
    * Removes any illegal characters from the host name to make it a valid file
    * name.
    */
   getSanitizedHost(host) {
+    if (host.startsWith("about:")) {
+      host = "moz-safe-" + host;
+    }
     return host.replace(ILLEGAL_CHAR_REGEX, "+");
   },
 
   /**
    * Retrieves the proper indexed db database name from the provided .sqlite
    * file location.
    */
   getNameFromDatabaseFile: Task.async(function* (path) {
     let connection = null;
     let retryCount = 0;
 
     // Content pages might be having an open transaction for the same indexed db
     // which this sqlite file belongs to. In that case, sqlite.openConnection
-    // will throw. Thus we retey for some time to see if lock is removed.
+    // will throw. Thus we retry for some time to see if lock is removed.
     while (!connection && retryCount++ < 25) {
       try {
         connection = yield Sqlite.openConnection({ path: path });
       } catch (ex) {
         // Continuously retrying is overkill. Waiting for 100ms before next try
         yield sleep(100);
       }
     }
@@ -2067,48 +2183,58 @@ var indexedDBHelpers = {
 
         for (let objectStore2 of objectStores2) {
           objectStores.push(objectStore2[1].toObject());
         }
       }
       return this.backToChild("getValuesForHost", {objectStores: objectStores});
     }
     // Get either all entries from the object store, or a particular id
-    let result = yield this.getObjectStoreData(host, principal, db2,
-      objectStore, id, options.index, options.size);
+    let storage = hostVsStores.get(host).get(db2).storage;
+    let result = yield this.getObjectStoreData(host, principal, db2, storage, {
+      objectStore: objectStore,
+      id: id,
+      index: options.index,
+      offset: 0,
+      size: options.size
+    });
     return this.backToChild("getValuesForHost", {result: result});
   }),
 
   /**
    * Returns all or requested entries from a particular objectStore from the db
    * in the given host.
    *
    * @param {string} host
    *        The given host.
    * @param {nsIPrincipal} principal
    *        The principal of the given document.
    * @param {string} dbName
    *        The name of the indexed db from the above host.
-   * @param {string} objectStore
-   *        The name of the object store from the above db.
-   * @param {string} id
-   *        id of the requested entry from the above object store.
-   *        null if all entries from the above object store are requested.
-   * @param {string} index
-   *        name of the IDBIndex to be iterated on while fetching entries.
-   *        null or "name" if no index is to be iterated.
-   * @param {number} offset
-   *        ofsset of the entries to be fetched.
-   * @param {number} size
-   *        The intended size of the entries to be fetched.
+   * @param {String} storage
+   *        Storage type, either "temporary", "default" or "persistent".
+   * @param {Object} requestOptions
+   *        An object in the following format:
+   *        {
+   *          objectStore: The name of the object store from the above db,
+   *          id:          Id of the requested entry from the above object
+   *                       store. null if all entries from the above object
+   *                       store are requested,
+   *          index:       Name of the IDBIndex to be iterated on while fetching
+   *                       entries. null or "name" if no index is to be
+   *                       iterated,
+   *          offset:      offset of the entries to be fetched,
+   *          size:        The intended size of the entries to be fetched
+   *        }
    */
-  getObjectStoreData(host, principal, dbName, objectStore, id, index,
-                     offset, size) {
-    let request = this.openWithPrincipal(principal, dbName);
+  getObjectStoreData(host, principal, dbName, storage, requestOptions) {
+    let {name} = this.splitNameAndStorage(dbName);
+    let request = this.openWithPrincipal(principal, name, storage);
     let success = promise.defer();
+    let {objectStore, id, index, offset, size} = requestOptions;
     let data = [];
     let db;
 
     if (!size || size > MAX_STORE_OBJECT_COUNT) {
       size = MAX_STORE_OBJECT_COUNT;
     }
 
     request.onsuccess = event => {
@@ -2200,31 +2326,35 @@ var indexedDBHelpers = {
     return md;
   },
 
   handleChildRequest(msg) {
     let args = msg.data.args;
 
     switch (msg.json.method) {
       case "getDBMetaData": {
-        let [host, principal, name] = args;
-        return indexedDBHelpers.getDBMetaData(host, principal, name);
+        let [host, principal, name, storage] = args;
+        return indexedDBHelpers.getDBMetaData(host, principal, name, storage);
+      }
+      case "splitNameAndStorage": {
+        let [name] = args;
+        return indexedDBHelpers.splitNameAndStorage(name);
       }
       case "getDBNamesForHost": {
         let [host] = args;
         return indexedDBHelpers.getDBNamesForHost(host);
       }
       case "getValuesForHost": {
         let [host, name, options, hostVsStores, principal] = args;
         return indexedDBHelpers.getValuesForHost(host, name, options,
                                                  hostVsStores, principal);
       }
       case "removeDB": {
-        let [host, principal, name] = args;
-        return indexedDBHelpers.removeDB(host, principal, name);
+        let [host, principal, dbName] = args;
+        return indexedDBHelpers.removeDB(host, principal, dbName);
       }
       case "removeDBRecord": {
         let [host, principal, db, store, id] = args;
         return indexedDBHelpers.removeDBRecord(host, principal, db, store, id);
       }
       case "clearDBStore": {
         let [host, principal, db, store] = args;
         return indexedDBHelpers.clearDBStore(host, principal, db, store);
--- a/devtools/server/tests/browser/browser_storage_listings.js
+++ b/devtools/server/tests/browser/browser_storage_listings.js
@@ -116,59 +116,59 @@ const storeMap = {
       }
     ]
   }
 };
 
 const IDBValues = {
   listStoresResponse: {
     "http://test1.example.org": [
-      ["idb1", "obj1"], ["idb1", "obj2"], ["idb2", "obj3"]
+      ["idb1 (default)", "obj1"], ["idb1 (default)", "obj2"], ["idb2 (default)", "obj3"]
     ],
     "http://sectest1.example.org": [
     ],
     "https://sectest1.example.org": [
-      ["idb-s1", "obj-s1"], ["idb-s2", "obj-s2"]
+      ["idb-s1 (default)", "obj-s1"], ["idb-s2 (default)", "obj-s2"]
     ]
   },
-  dbDetails : {
+  dbDetails: {
     "http://test1.example.org": [
       {
-        db: "idb1",
+        db: "idb1 (default)",
         origin: "http://test1.example.org",
         version: 1,
         objectStores: 2
       },
       {
-        db: "idb2",
+        db: "idb2 (default)",
         origin: "http://test1.example.org",
         version: 1,
         objectStores: 1
       },
     ],
     "http://sectest1.example.org": [
     ],
     "https://sectest1.example.org": [
       {
-        db: "idb-s1",
+        db: "idb-s1 (default)",
         origin: "https://sectest1.example.org",
         version: 1,
         objectStores: 1
       },
       {
-        db: "idb-s2",
+        db: "idb-s2 (default)",
         origin: "https://sectest1.example.org",
         version: 1,
         objectStores: 1
       },
     ]
   },
   objectStoreDetails: {
     "http://test1.example.org": {
-      idb1: [
+      "idb1 (default)": [
         {
           objectStore: "obj1",
           keyPath: "id",
           autoIncrement: false,
           indexes: [
             {
               name: "name",
               keyPath: "name",
@@ -185,17 +185,17 @@ const IDBValues = {
         },
         {
           objectStore: "obj2",
           keyPath: "id2",
           autoIncrement: false,
           indexes: []
         }
       ],
-      idb2: [
+      "idb2 (default)": [
         {
           objectStore: "obj3",
           keyPath: "id3",
           autoIncrement: false,
           indexes: [
             {
               name: "name2",
               keyPath: "name2",
@@ -203,25 +203,25 @@ const IDBValues = {
               multiEntry: false,
             }
           ]
         },
       ]
     },
     "http://sectest1.example.org" : {},
     "https://sectest1.example.org": {
-      "idb-s1": [
+      "idb-s1 (default)": [
         {
           objectStore: "obj-s1",
           keyPath: "id",
           autoIncrement: false,
           indexes: []
         },
       ],
-      "idb-s2": [
+      "idb-s2 (default)": [
         {
           objectStore: "obj-s2",
           keyPath: "id3",
           autoIncrement: true,
           indexes: [
             {
               name: "name2",
               keyPath: "name2",
@@ -231,17 +231,17 @@ const IDBValues = {
           ]
         },
       ]
     }
 
   },
   entries: {
     "http://test1.example.org": {
-      "idb1#obj1": [
+      "idb1 (default)#obj1": [
         {
           name: 1,
           value: {
             id: 1,
             name: "foo",
             email: "foo@bar.com",
           }
         },
@@ -257,32 +257,32 @@ const IDBValues = {
           name: 3,
           value: {
             id: 3,
             name: "foo2",
             email: "foo3@bar.com",
           }
         }
       ],
-      "idb1#obj2": [
+      "idb1 (default)#obj2": [
         {
           name: 1,
           value: {
             id2: 1,
             name: "foo",
             email: "foo@bar.com",
             extra: "baz"
           }
         }
       ],
-      "idb2#obj3": []
+      "idb2 (default)#obj3": []
     },
     "http://sectest1.example.org" : {},
     "https://sectest1.example.org": {
-      "idb-s1#obj-s1": [
+      "idb-s1 (default)#obj-s1": [
         {
           name: 6,
           value: {
             id: 6,
             name: "foo",
             email: "foo@bar.com",
           }
         },
@@ -290,17 +290,17 @@ const IDBValues = {
           name: 7,
           value: {
             id: 7,
             name: "foo2",
             email: "foo2@bar.com",
           }
         }
       ],
-      "idb-s2#obj-s2": [
+      "idb-s2 (default)#obj-s2": [
         {
           name: 13,
           value: {
             id2: 13,
             name2: "foo",
             email: "foo@bar.com",
           }
         }
--- a/devtools/shared/specs/storage.js
+++ b/devtools/shared/specs/storage.js
@@ -56,17 +56,17 @@ types.addDictType("cookieobject", {
 types.addDictType("cookiestoreobject", {
   total: "number",
   offset: "number",
   data: "array:nullable:cookieobject"
 });
 
 // Common methods for edit/remove
 const editRemoveMethods = {
-  getEditableFields: {
+  getFields: {
     request: {},
     response: {
       value: RetVal("json")
     }
   },
   editItem: {
     request: {
       data: Arg(0, "json"),