Bug 1320362 - Move indexedDb storage type in the storage inspector into a new column r=jdescottes
authorMichael Ratcliffe <mratcliffe@mozilla.com>
Tue, 29 Nov 2016 10:57:18 +0000
changeset 324844 65c73bad7dc1e2f74873928bc2e954dade385c41
parent 324843 549da59b304f7f5a7aca4a27c4de7fcb53c93176
child 324845 ff48df015e576a28208bb3c09d553f909fcbb3d1
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersjdescottes
bugs1320362
milestone53.0a1
Bug 1320362 - Move indexedDb storage type in the storage inspector into a new column r=jdescottes Ideally we would have used the GUID to join fields to build the compound key but because we show the uniqueId in the tree that would lead to an ugly user experience. As an alternative we simply use e.g. db1 (default) as the uniqueId. This works as a unique key, is informative for the user and means minimal changes to tests. MozReview-Commit-ID: I0XxTIoV33p
devtools/client/locales/en-US/storage.properties
devtools/client/shared/widgets/TableWidget.js
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
@@ -48,18 +48,20 @@ table.headers.localStorage.name=Key
 table.headers.localStorage.value=Value
 
 table.headers.sessionStorage.name=Key
 table.headers.sessionStorage.value=Value
 
 table.headers.Cache.url=URL
 table.headers.Cache.status=Status
 
+table.headers.indexedDB.uniqueKey=Unique key
 table.headers.indexedDB.name=Key
 table.headers.indexedDB.db=Database Name
+table.headers.indexedDB.storage=Storage
 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.keyPath2=Key Path
 table.headers.indexedDB.autoIncrement=Auto Increment
 table.headers.indexedDB.indexes=Indexes
--- a/devtools/client/shared/widgets/TableWidget.js
+++ b/devtools/client/shared/widgets/TableWidget.js
@@ -714,16 +714,20 @@ TableWidget.prototype = {
       if (this.firstColumn && id == this.firstColumn) {
         continue;
       }
 
       this.columns.set(id, new Column(this, id, columns[id]));
       if (hiddenColumns.includes(id) || privateColumns.includes(id)) {
         // Hide the column.
         this.columns.get(id).toggleColumn();
+
+        if (privateColumns.includes(id)) {
+          this.columns.get(id).private = true;
+        }
       }
     }
     this.sortedOn = sortOn;
     this.sortBy(this.sortedOn);
     this.populateMenuPopup(privateColumns);
   },
 
   /**
@@ -973,16 +977,19 @@ module.exports.TableWidget = TableWidget
  * @param {TableWidget} table
  *        The table object to which the column belongs.
  * @param {string} id
  *        Id of the column.
  * @param {String} header
  *        The displayed string on the column's header.
  */
 function Column(table, id, header) {
+  // By default cells are visible in the UI.
+  this._private = false;
+
   this.tbody = table.tbody;
   this.document = table.document;
   this.window = table.window;
   this.id = id;
   this.uniqueId = table.uniqueId;
   this.wrapTextInElements = table.wrapTextInElements;
   this.table = table;
   this.cells = [];
@@ -1056,16 +1063,33 @@ Column.prototype = {
    * 1 - ascending order
    * 2 - descending order
    */
   get sorted() {
     return this._sortState || 0;
   },
 
   /**
+   * Get the private state of the column (visibility in the UI).
+   */
+  get private() {
+    return this._private;
+  },
+
+  /**
+   * Set the private state of the column (visibility in the UI).
+   *
+   * @param  {Boolean} state
+   *         Private (true or false)
+   */
+  set private(state) {
+    this._private = state;
+  },
+
+  /**
    * Sets the sorted value
    */
   set sorted(value) {
     if (!value) {
       this.header.removeAttribute("sorted");
     } else {
       this.header.setAttribute("sorted",
         value == 1 ? "ascending" : "descending");
--- a/devtools/client/storage/ui.js
+++ b/devtools/client/storage/ui.js
@@ -568,17 +568,17 @@ StorageUI.prototype = {
         if (!this.tree.selectedItem) {
           this.tree.selectedItem = [type, host];
         }
       }
     }
   },
 
   /**
-   * Populates the selected entry from teh table in the sidebar for a more
+   * Populates the selected entry from the table in the sidebar for a more
    * detailed view.
    */
   displayObjectSidebar: Task.async(function* () {
     let item = this.table.selectedRow;
     if (!item) {
       // Make sure that sidebar is hidden and return
       this.sidebar.hidden = true;
       return;
@@ -610,27 +610,37 @@ StorageUI.prototype = {
       let itemProps = Object.keys(item);
       if (itemProps.length > 3) {
         // Display any other information other than the item name and value
         // which may be available.
         let rawObject = Object.create(null);
         let otherProps = itemProps.filter(
           e => !["name", "value", "valueActor"].includes(e));
         for (let prop of otherProps) {
+          let column = this.table.columns.get(prop);
+          if (column && column.private) {
+            continue;
+          }
+
           let cookieProp = COOKIE_KEY_MAP[prop] || prop;
           // The pseduo property of HostOnly refers to converse of isDomain property
           rawObject[cookieProp] = (prop === "isDomain") ? !item[prop] : item[prop];
         }
         itemVar.populate(rawObject, {sorted: true});
         itemVar.twisty = true;
         itemVar.expanded = true;
       }
     } else {
       // Case when displaying IndexedDB db/object store properties.
       for (let key in item) {
+        let column = this.table.columns.get(key);
+        if (column && column.private) {
+          continue;
+        }
+
         mainScope.addItem(key, {}, true).setGrip(item[key]);
         this.parseItemValue(key, item[key]);
       }
     }
 
     this.emit("sidebar-updated");
   }),
 
--- a/devtools/server/actors/storage.js
+++ b/devtools/server/actors/storage.js
@@ -1471,17 +1471,19 @@ function DatabaseMetadata(origin, db, st
 }
 DatabaseMetadata.prototype = {
   get objectStores() {
     return this._objectStores;
   },
 
   toObject() {
     return {
-      name: `${this._name} (${this.storage})`,
+      uniqueKey: `${this._name}${SEPARATOR_GUID}${this.storage}`,
+      name: this._name,
+      storage: this.storage,
       origin: this._origin,
       version: this._version,
       objectStores: this._objectStores.size
     };
   }
 };
 
 StorageActors.createActor({
@@ -1683,17 +1685,19 @@ StorageActors.createActor({
         keyPath: item.keyPath,
         autoIncrement: item.autoIncrement,
         indexes: item.indexes
       };
     }
     if ("objectStores" in item) {
       // DB meta data
       return {
+        uniqueKey: `${item.name} (${item.storage})`,
         db: item.name,
+        storage: item.storage,
         origin: item.origin,
         version: item.version,
         objectStores: item.objectStores
       };
     }
 
     let value = JSON.stringify(item.value);
 
@@ -1825,17 +1829,19 @@ StorageActors.createActor({
         return [
           { name: "name", editable: false },
           { name: "value", editable: false }
         ];
 
       // Detail of indexedDB for one origin
       default:
         return [
+          { name: "uniqueKey", editable: false, private: true },
           { name: "db", editable: false },
+          { name: "storage", editable: false },
           { name: "origin", editable: false },
           { name: "version", editable: false },
           { name: "objectStores", editable: false },
         ];
     }
   })
 });
 
--- a/devtools/server/tests/browser/browser_storage_listings.js
+++ b/devtools/server/tests/browser/browser_storage_listings.js
@@ -465,27 +465,27 @@ var testIndexedDB = Task.async(function*
 var testIndexedDBs = Task.async(function* (index, hosts, indexedDBActor) {
   let host = Object.keys(hosts)[index];
   let matchItems = data => {
     is(data.total, IDBValues.dbDetails[host].length,
        "Number of indexed db in host " + host + " matches");
     for (let item of data.data) {
       let found = false;
       for (let toMatch of IDBValues.dbDetails[host]) {
-        if (item.db == toMatch.db) {
+        if (item.uniqueKey == toMatch.db) {
           found = true;
-          ok(true, "Found indexed db " + item.db + " in response");
+          ok(true, "Found indexed db " + item.uniqueKey + " in response");
           is(item.origin, toMatch.origin, "The origin matches.");
           is(item.version, toMatch.version, "The version matches.");
           is(item.objectStores, toMatch.objectStores,
-             "The numebr of object stores matches.");
+             "The number of object stores matches.");
           break;
         }
       }
-      ok(found, "indexed db " + item.name + " should exist in response");
+      ok(found, "indexed db " + item.uniqueKey + " should exist in response");
     }
   };
 
   ok(!!IDBValues.dbDetails[host], "Host is present in the list : " + host);
   matchItems(yield indexedDBActor.getStoreObjects(host));
   if (index == Object.keys(hosts).length - 1) {
     return;
   }
--- a/devtools/shared/specs/storage.js
+++ b/devtools/shared/specs/storage.js
@@ -35,16 +35,17 @@ function createStorageSpec(options) {
   childSpecs[options.typeName] = protocol.generateActorSpec({
     typeName: options.typeName,
     methods
   });
 }
 
 // Cookies store object
 types.addDictType("cookieobject", {
+  uniqueKey: "string",
   name: "string",
   value: "longstring",
   path: "nullable:string",
   host: "string",
   isDomain: "boolean",
   isSecure: "boolean",
   isHttpOnly: "boolean",
   creationTime: "number",
@@ -171,21 +172,23 @@ createStorageSpec({
     },
   }
 });
 
 // Indexed DB store object
 // This is a union on idb object, db metadata object and object store metadata
 // object
 types.addDictType("idbobject", {
+  uniqueKey: "string",
   name: "nullable:string",
   db: "nullable:string",
   objectStore: "nullable:string",
   origin: "nullable:string",
   version: "nullable:number",
+  storage: "nullable:string",
   objectStores: "nullable:number",
   keyPath: "nullable:string",
   autoIncrement: "nullable:boolean",
   indexes: "nullable:string",
   value: "nullable:longstring"
 });
 
 // Array of Indexed DB store objects