Bug 1237915 - Fix devtools storage interface to use the correct user context id when opening indexdb connections. r=mratcliffe
authorTim Huang <tihuang@mozilla.com>
Fri, 01 Apr 2016 18:05:00 +0200
changeset 315684 fba631fb424cb3aba5e300f3d16ce8b2a05e0b89
parent 315683 45b2a2adec04c7349f887f77dbaaefca986659fc
child 315685 978884d01e8ef968262e54138bf43acdbbc603b6
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
bugs1237915
milestone48.0a1
Bug 1237915 - Fix devtools storage interface to use the correct user context id when opening indexdb connections. r=mratcliffe MozReview-Commit-ID: LRGx44VWjQG
devtools/server/actors/storage.js
--- a/devtools/server/actors/storage.js
+++ b/devtools/server/actors/storage.js
@@ -342,20 +342,28 @@ StorageActors.defaults = function(typeNa
       let sortOn = options.sortOn || "name";
 
       let toReturn = {
         offset: offset,
         total: 0,
         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 (names) {
         for (let name of names) {
           let values =
-            yield this.getValuesForHost(host, name, options, this.hostVsStores);
+            yield this.getValuesForHost(host, name, options, this.hostVsStores, principal);
 
           let {result, objectStores} = values;
 
           if (result && typeof result.objectsSize !== "undefined") {
             for (let {key, count} of result.objectsSize) {
               this.objectsSize[key] = count;
             }
           }
@@ -375,17 +383,17 @@ StorageActors.defaults = function(typeNa
           toReturn.data = [];
         } else {
           toReturn.data = toReturn.data.sort((a, b) => {
             return a[sortOn] - b[sortOn];
           }).slice(offset, offset + size).map(a => this.toStoreObject(a));
         }
       } else {
         let obj = yield this.getValuesForHost(host, undefined, undefined,
-                                              this.hostVsStores);
+                                              this.hostVsStores, principal);
         if (obj.dbs) {
           obj = obj.dbs;
         }
 
         toReturn.total = obj.length;
         if (offset > toReturn.total) {
           // In this case, toReturn.data is an empty array.
           toReturn.offset = offset = toReturn.total;
@@ -1546,19 +1554,21 @@ 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);
+    let principal = win.document.nodePrincipal;
 
     for (let name of names) {
-      let metadata = yield this.getDBMetaData(host, name);
+      let metadata = yield this.getDBMetaData(host, principal, name);
 
       metadata = indexedDBHelpers.patchMetadataMapsAndProtos(metadata);
       storeMap.set(name, metadata);
     }
 
     this.hostVsStores.set(host, storeMap);
   }),
 
@@ -1612,17 +1622,17 @@ StorageActors.createActor({
   },
 
   maybeSetupChildProcess: function() {
     if (!DebuggerServer.isInChildProcess) {
       this.backToChild = function(...args) {
         return args[1];
       };
       this.getDBMetaData = indexedDBHelpers.getDBMetaData;
-      this.openWithOrigin = indexedDBHelpers.openWithOrigin;
+      this.openWithPrincipal = indexedDBHelpers.openWithPrincipal;
       this.getDBNamesForHost = indexedDBHelpers.getDBNamesForHost;
       this.getSanitizedHost = indexedDBHelpers.getSanitizedHost;
       this.getNameFromDatabaseFile = indexedDBHelpers.getNameFromDatabaseFile;
       this.getValuesForHost = indexedDBHelpers.getValuesForHost;
       this.getObjectStoreData = indexedDBHelpers.getObjectStoreData;
       this.patchMetadataMapsAndProtos =
         indexedDBHelpers.patchMetadataMapsAndProtos;
       return;
@@ -1681,21 +1691,21 @@ var indexedDBHelpers = {
     mm.broadcastAsyncMessage("storage:storage-indexedDB-request-child", {
       method: "backToChild",
       args: args
     });
   },
 
   /**
    * Fetches and stores all the metadata information for the given database
-   * `name` for the given `host`. The stored metadata information is of
-   * `DatabaseMetadata` type.
+   * `name` for the given `host` with its `principal`. The stored metadata
+   * information is of `DatabaseMetadata` type.
    */
-  getDBMetaData: Task.async(function*(host, name) {
-    let request = this.openWithOrigin(host, name);
+  getDBMetaData: Task.async(function*(host, principal, name) {
+    let request = this.openWithPrincipal(principal, name);
     let success = promise.defer();
 
     request.onsuccess = event => {
       let db = event.target.result;
 
       let dbData = new DatabaseMetadata(host, db);
       db.close();
 
@@ -1707,29 +1717,19 @@ var indexedDBHelpers = {
                     host);
       this.backToChild("getDBMetaData", null);
       success.resolve(null);
     };
     return success.promise;
   }),
 
   /**
-   * Opens an indexed db connection for the given `host` and database `name`.
+   * Opens an indexed db connection for the given `principal` and database `name`.
    */
-  openWithOrigin: function(host, name) {
-    let principal;
-
-    if (/^(about:|chrome:)/.test(host)) {
-      principal = Services.scriptSecurityManager.getSystemPrincipal();
-    } else {
-      let uri = Services.io.newURI(host, null, null);
-      principal = Services.scriptSecurityManager
-                          .createCodebasePrincipal(uri, {});
-    }
-
+  openWithPrincipal: function(principal, name) {
     return require("indexedDB").openForPrincipal(principal, name);
   },
 
     /**
    * Fetches all the databases and their metadata for the given `host`.
    */
   getDBNamesForHost: Task.async(function*(host) {
     let sanitizedHost = this.getSanitizedHost(host);
@@ -1815,17 +1815,17 @@ var indexedDBHelpers = {
     let name = rows[0].getResultByName("name");
 
     yield connection.close();
 
     return name;
   }),
 
   getValuesForHost:
-  Task.async(function*(host, name = "null", options, hostVsStores) {
+  Task.async(function*(host, name = "null", options, hostVsStores, principal) {
     name = JSON.parse(name);
     if (!name || !name.length) {
       // This means that details about the db in this particular host are
       // requested.
       let dbs = [];
       if (hostVsStores.has(host)) {
         for (let [, db] of hostVsStores.get(host)) {
           db = indexedDBHelpers.patchMetadataMapsAndProtos(db);
@@ -1849,45 +1849,47 @@ 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, db2, objectStore, id,
+    let result = yield this.getObjectStoreData(host, principal, db2, objectStore, id,
                                                options.index, 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.
    */
   getObjectStoreData:
-  function(host, dbName, objectStore, id, index, offset, size) {
-    let request = this.openWithOrigin(host, dbName);
+  function(host, principal, dbName, objectStore, id, index, offset, size) {
+    let request = this.openWithPrincipal(principal, dbName);
     let success = promise.defer();
     let data = [];
     let db;
 
     if (!size || size > MAX_STORE_OBJECT_COUNT) {
       size = MAX_STORE_OBJECT_COUNT;
     }
 
@@ -1981,30 +1983,34 @@ var indexedDBHelpers = {
   },
 
   handleChildRequest: function(msg) {
     let host;
     let name;
     let args = msg.data.args;
 
     switch (msg.json.method) {
-      case "getDBMetaData":
+      case "getDBMetaData": {
         host = args[0];
-        name = args[1];
-        return indexedDBHelpers.getDBMetaData(host, name);
+        let principal = args[1];
+        name = args[2];
+        return indexedDBHelpers.getDBMetaData(host, principal, name);
+      }
       case "getDBNamesForHost":
         host = args[0];
         return indexedDBHelpers.getDBNamesForHost(host);
-      case "getValuesForHost":
+      case "getValuesForHost": {
         host = args[0];
         name = args[1];
         let options = args[2];
         let hostVsStores = args[3];
+        let principal = args[4];
         return indexedDBHelpers.getValuesForHost(host, name, options,
-                                                 hostVsStores);
+                                                 hostVsStores, principal);
+      }
       default:
         console.error("ERR_DIRECTOR_PARENT_UNKNOWN_METHOD", msg.json.method);
         throw new Error("ERR_DIRECTOR_PARENT_UNKNOWN_METHOD");
     }
   }
 };
 
 /**
@@ -2170,16 +2176,28 @@ var StorageActor = exports.StorageActor 
                    .currentInnerWindowID;
       if (id == innerID) {
         return win;
       }
     }
     return null;
   },
 
+  getWindowFromHost: function(host) {
+    for (let win of this.childWindowPool.values()) {
+      let origin = win.document
+                      .nodePrincipal
+                      .originNoSuffix;
+      if (origin === host) {
+        return win;
+      }
+    }
+    return null;
+  },
+
   /**
    * Event handler for any docshell update. This lets us figure out whenever
    * any new window is added, or an existing window is removed.
    */
   observe: function(subject, topic) {
     if (subject.location &&
         (!subject.location.href || subject.location.href == "about:blank")) {
       return null;