Bug 1262766 - Storage Inspector breaks down when Cache Storage throws a DOM security error. r=mratcliffe
authorJarda Snajdr <jsnajdr@gmail.com>
Mon, 11 Apr 2016 01:23:00 -0400
changeset 316339 54a802cb5d4336b3ac8cba27c331e2c338e2b432
parent 316338 1d5b01d01df634f2113a6ebfd597feb8b70f001f
child 316340 d93a1bc945137dfcc94866f1e30da1f55cfb8d9d
push id9480
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 17:12:58 +0000
treeherdermozilla-aurora@0d6a91c76a9e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmratcliffe
bugs1262766
milestone48.0a1
Bug 1262766 - Storage Inspector breaks down when Cache Storage throws a DOM security error. r=mratcliffe
devtools/client/storage/test/browser.ini
devtools/client/storage/test/browser_storage_cache_error.js
devtools/client/storage/test/storage-cache-error.html
devtools/server/actors/storage.js
--- a/devtools/client/storage/test/browser.ini
+++ b/devtools/client/storage/test/browser.ini
@@ -1,25 +1,27 @@
 [DEFAULT]
 tags = devtools
 subsuite = devtools
 support-files =
+  storage-cache-error.html
   storage-complex-values.html
   storage-cookies.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
   head.js
 
 [browser_storage_basic.js]
+[browser_storage_cache_error.js]
 [browser_storage_cookies_delete_all.js]
 [browser_storage_cookies_edit.js]
 [browser_storage_cookies_edit_keyboard.js]
 [browser_storage_cookies_tab_navigation.js]
 [browser_storage_dynamic_updates.js]
 [browser_storage_localstorage_edit.js]
 [browser_storage_delete.js]
 [browser_storage_delete_all.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/storage/test/browser_storage_cache_error.js
@@ -0,0 +1,21 @@
+/* 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 */
+
+"use strict";
+
+// Test handling errors in CacheStorage
+
+add_task(function* () {
+  yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-cache-error.html");
+
+  const cacheItemId = ["Cache", "javascript:parent.frameContent"];
+
+  gUI.tree.selectedItem = cacheItemId;
+  ok(gUI.tree.isSelected(cacheItemId),
+    `The item ${cacheItemId.join(" > ")} is present in the tree`);
+
+  yield finishTests();
+});
new file mode 100644
--- /dev/null
+++ b/devtools/client/storage/test/storage-cache-error.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Storage inspector test for handling errors in CacheStorage</title>
+</head>
+<body>
+<script type="application/javascript;version=1.7">
+"use strict";
+
+// Create an iframe with a javascript: source URL. Such iframes are
+// considered untrusted by the CacheStorage.
+let frameEl = document.createElement("iframe");
+document.body.appendChild(frameEl);
+
+window.frameContent = 'Hello World';
+frameEl.contentWindow.location.href = "javascript:parent.frameContent";
+</script>
+</body>
+</html>
--- a/devtools/server/actors/storage.js
+++ b/devtools/server/actors/storage.js
@@ -347,17 +347,19 @@ StorageActors.defaults = function(typeNa
         data: []
       };
 
       let principal = null;
       if (this.typeName === "indexedDB") {
         // We only acquire principal when the type of the storage is indexedDB
         // because the principal only matters the indexedDB.
         let win = this.storageActor.getWindowFromHost(host);
-        principal = win.document.nodePrincipal;
+        if (win) {
+          principal = win.document.nodePrincipal;
+        }
       }
 
       if (names) {
         for (let name of names) {
           let values =
             yield this.getValuesForHost(host, name, options, this.hostVsStores, principal);
 
           let {result, objectStores} = values;
@@ -1340,18 +1342,22 @@ StorageActors.createActor({
       return location.href;
     }
     return location.protocol + "//" + location.host;
   },
 
   populateStoresForHost: Task.async(function*(host) {
     let storeMap = new Map();
     let caches = yield this.getCachesForHost(host);
-    for (let name of (yield caches.keys())) {
-      storeMap.set(name, (yield caches.open(name)));
+    try {
+      for (let name of (yield caches.keys())) {
+        storeMap.set(name, (yield caches.open(name)));
+      }
+    } catch (ex) {
+      console.error(`Failed to enumerate CacheStorage for host ${host}:`, ex);
     }
     this.hostVsStores.set(host, storeMap);
   }),
 
   /**
    * This method is overriden and left blank as for Cache Storage, this
    * operation cannot be performed synchronously. Thus, the preListStores
    * method exists to do the same task asynchronously.
@@ -1601,23 +1607,25 @@ StorageActors.createActor({
       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);
-    let principal = win.document.nodePrincipal;
+    if (win) {
+      let principal = win.document.nodePrincipal;
 
-    for (let name of names) {
-      let metadata = yield this.getDBMetaData(host, principal, name);
+      for (let name of names) {
+        let metadata = yield this.getDBMetaData(host, principal, name);
 
-      metadata = indexedDBHelpers.patchMetadataMapsAndProtos(metadata);
-      storeMap.set(name, metadata);
+        metadata = indexedDBHelpers.patchMetadataMapsAndProtos(metadata);
+        storeMap.set(name, metadata);
+      }
     }
 
     this.hostVsStores.set(host, storeMap);
   }),
 
   /**
    * Returns the over-the-wire implementation of the indexed db entity.
    */