Backed out changeset a4c47419ac3f (bug 1231434) for eslint failures (no space after generator star, backquotes instead of doublequotes used). r=backout
authorSebastian Hengst <archaeopteryx@coole-files.de>
Sun, 10 Apr 2016 20:13:07 +0200
changeset 316173 9332103718ecc5d23f4523f2faedd929e0fb46ee
parent 316172 a4c47419ac3f7c90a75d9ed85363d2eee79ee5a7
child 316311 29d5a4175c8b74f45482276a53985cf2568b4be2
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)
reviewersbackout
bugs1231434
milestone48.0a1
backs outa4c47419ac3f7c90a75d9ed85363d2eee79ee5a7
Backed out changeset a4c47419ac3f (bug 1231434) for eslint failures (no space after generator star, backquotes instead of doublequotes used). r=backout
devtools/client/locales/en-US/storage.dtd
devtools/client/locales/en-US/storage.properties
devtools/client/shared/widgets/TableWidget.js
devtools/client/shared/widgets/TreeWidget.js
devtools/client/storage/storage.xul
devtools/client/storage/test/browser.ini
devtools/client/storage/test/browser_storage_cookies_delete_all.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/head.js
devtools/client/storage/ui.js
devtools/server/actors/storage.js
--- a/devtools/client/locales/en-US/storage.dtd
+++ b/devtools/client/locales/en-US/storage.dtd
@@ -1,11 +1,8 @@
 <!-- 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/. -->
 
 <!-- LOCALIZATION NOTE : This file contains the Storage Inspector strings. -->
 
 <!-- LOCALIZATION NOTE : Placeholder for the searchbox that allows you to filter the table items. -->
 <!ENTITY searchBox.placeholder         "Filter items">
-
-<!-- LOCALIZATION NOTE : Label of popup menu action to delete all storage items. -->
-<!ENTITY storage.popupMenu.deleteAllLabel "Delete All">
--- a/devtools/client/locales/en-US/storage.properties
+++ b/devtools/client/locales/en-US/storage.properties
@@ -114,12 +114,8 @@ storage.data.label=Data
 
 # LOCALIZATION NOTE (storage.parsedValue.label):
 # This is the heading displayed over the item parsed value in the sidebar
 storage.parsedValue.label=Parsed Value
 
 # LOCALIZATION NOTE (storage.popupMenu.deleteLabel):
 # Label of popup menu action to delete storage item.
 storage.popupMenu.deleteLabel=Delete ā€œ%Sā€
-
-# LOCALIZATION NOTE (storage.popupMenu.deleteAllLabel):
-# Label of popup menu action to delete all storage items.
-storage.popupMenu.deleteAllFromLabel=Delete All From ā€œ%Sā€
--- a/devtools/client/shared/widgets/TableWidget.js
+++ b/devtools/client/shared/widgets/TableWidget.js
@@ -798,19 +798,16 @@ TableWidget.prototype = {
 
   /**
    * Removes the row associated with the `item` object.
    */
   remove: function(item) {
     if (typeof item == "string") {
       item = this.items.get(item);
     }
-    if (!item) {
-      return;
-    }
     let removed = this.items.delete(item[this.uniqueId]);
 
     if (!removed) {
       return;
     }
     for (let column of this.columns.values()) {
       column.remove(item);
       column.updateZebra();
--- a/devtools/client/shared/widgets/TreeWidget.js
+++ b/devtools/client/shared/widgets/TreeWidget.js
@@ -12,33 +12,30 @@ const EventEmitter = require("devtools/s
 /**
  * A tree widget with keyboard navigation and collapsable structure.
  *
  * @param {nsIDOMNode} node
  *        The container element for the tree widget.
  * @param {Object} options
  *        - emptyText {string}: text to display when no entries in the table.
  *        - defaultType {string}: The default type of the tree items. For ex.
- *          'js'
+ *        'js'
  *        - sorted {boolean}: Defaults to true. If true, tree items are kept in
- *          lexical order. If false, items will be kept in insertion order.
- *        - contextMenuId {string}: ID of context menu to be displayed on
- *          tree items.
+ *        lexical order. If false, items will be kept in insertion order.
  */
 function TreeWidget(node, options = {}) {
   EventEmitter.decorate(this);
 
   this.document = node.ownerDocument;
   this.window = this.document.defaultView;
   this._parent = node;
 
   this.emptyText = options.emptyText || "";
   this.defaultType = options.defaultType;
   this.sorted = options.sorted !== false;
-  this.contextMenuId = options.contextMenuId;
 
   this.setupRoot();
 
   this.placeholder = this.document.createElementNS(HTML_NS, "label");
   this.placeholder.className = "tree-widget-empty-text";
   this._parent.appendChild(this.placeholder);
 
   if (this.emptyText) {
@@ -51,41 +48,40 @@ function TreeWidget(node, options = {}) 
 TreeWidget.prototype = {
 
   _selectedLabel: null,
   _selectedItem: null,
 
   /**
    * Select any node in the tree.
    *
-   * @param {array} ids
+   * @param {array} id
    *        An array of ids leading upto the selected item
    */
-  set selectedItem(ids) {
+  set selectedItem(id) {
     if (this._selectedLabel) {
       this._selectedLabel.classList.remove("theme-selected");
     }
     let currentSelected = this._selectedLabel;
-    if (ids == -1) {
+    if (id == -1) {
       this._selectedLabel = this._selectedItem = null;
       return;
     }
-    if (!Array.isArray(ids)) {
+    if (!Array.isArray(id)) {
       return;
     }
-    this._selectedLabel = this.root.setSelectedItem(ids);
+    this._selectedLabel = this.root.setSelectedItem(id);
     if (!this._selectedLabel) {
       this._selectedItem = null;
     } else {
       if (currentSelected != this._selectedLabel) {
         this.ensureSelectedVisible();
       }
-      this._selectedItem = ids;
-      this.emit("select", this._selectedItem,
-        this.attachments.get(JSON.stringify(ids)));
+      this._selectedItem =
+      JSON.parse(this._selectedLabel.parentNode.getAttribute("data-id"));
     }
   },
 
   /**
    * Gets the selected item in the tree.
    *
    * @return {array}
    *        An array of ids leading upto the selected item
@@ -119,26 +115,19 @@ TreeWidget.prototype = {
     this.root = null;
   },
 
   /**
    * Sets up the root container of the TreeWidget.
    */
   setupRoot: function() {
     this.root = new TreeItem(this.document);
-    if (this.contextMenuId) {
-      this.root.children.addEventListener("contextmenu", (event) => {
-        let menu = this.document.getElementById(this.contextMenuId);
-        menu.openPopupAtScreen(event.screenX, event.screenY, true);
-      });
-    }
-
     this._parent.appendChild(this.root.children);
 
-    this.root.children.addEventListener("mousedown", e => this.onClick(e));
+    this.root.children.addEventListener("click", e => this.onClick(e));
     this.root.children.addEventListener("keypress", e => this.onKeypress(e));
   },
 
   /**
    * Sets the text to be shown when no node is present in the tree
    */
   setPlaceholderText: function(text) {
     this.placeholder.textContent = text;
@@ -321,34 +310,39 @@ TreeWidget.prototype = {
       if (target == this.root.children) {
         return;
       }
       target = target.parentNode;
     }
     if (!target) {
       return;
     }
-
     if (target.hasAttribute("expanded")) {
       target.removeAttribute("expanded");
     } else {
       target.setAttribute("expanded", "true");
     }
-
+    if (this._selectedLabel) {
+      this._selectedLabel.classList.remove("theme-selected");
+    }
     if (this._selectedLabel != target) {
       let ids = target.parentNode.getAttribute("data-id");
-      this.selectedItem = JSON.parse(ids);
+      this._selectedItem = JSON.parse(ids);
+      this.emit("select", this._selectedItem, this.attachments.get(ids));
+      this._selectedLabel = target;
     }
+    target.classList.add("theme-selected");
   },
 
   /**
    * Keypress handler for this tree. Used to select next and previous visible
    * items, as well as collapsing and expanding any item.
    */
   onKeypress: function(event) {
+    let currentSelected = this._selectedLabel;
     switch (event.keyCode) {
       case event.DOM_VK_UP:
         this.selectPreviousItem();
         break;
 
       case event.DOM_VK_DOWN:
         this.selectNextItem();
         break;
@@ -368,16 +362,21 @@ TreeWidget.prototype = {
         } else {
           this.selectPreviousItem();
         }
         break;
 
       default: return;
     }
     event.preventDefault();
+    if (this._selectedLabel != currentSelected) {
+      let ids = JSON.stringify(this._selectedItem);
+      this.emit("select", this._selectedItem, this.attachments.get(ids));
+      this.ensureSelectedVisible();
+    }
   },
 
   /**
    * Scrolls the viewport of the tree so that the selected item is always
    * visible.
    */
   ensureSelectedVisible: function() {
     let {top, bottom} = this._selectedLabel.getBoundingClientRect();
--- a/devtools/client/storage/storage.xul
+++ b/devtools/client/storage/storage.xul
@@ -18,25 +18,18 @@
 
   <script type="application/javascript;version=1.8"
           src="chrome://devtools/content/shared/theme-switching.js"/>
   <script type="text/javascript" src="chrome://global/content/globalOverlay.js"/>
 
   <commandset id="editMenuCommands"/>
 
   <popupset id="storagePopupSet">
-    <menupopup id="storage-tree-popup">
-      <menuitem id="storage-tree-popup-delete-all"
-                label="&storage.popupMenu.deleteAllLabel;"/>
-    </menupopup>
     <menupopup id="storage-table-popup">
       <menuitem id="storage-table-popup-delete"/>
-      <menuitem id="storage-table-popup-delete-all-from"/>
-      <menuitem id="storage-table-popup-delete-all"
-                label="&storage.popupMenu.deleteAllLabel;"/>
     </menupopup>
   </popupset>
 
   <box flex="1" class="devtools-responsive-container theme-body">
     <vbox id="storage-tree"/>
     <splitter class="devtools-side-splitter"/>
     <vbox flex="1">
       <hbox id="storage-toolbar" class="devtools-toolbar">
--- a/devtools/client/storage/test/browser.ini
+++ b/devtools/client/storage/test/browser.ini
@@ -10,23 +10,20 @@ support-files =
   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_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]
-[browser_storage_delete_tree.js]
 [browser_storage_overflow.js]
 [browser_storage_search.js]
 skip-if = os == "linux" && e10s # Bug 1240804 - unhandled promise rejections
 [browser_storage_sessionstorage_edit.js]
 [browser_storage_sidebar.js]
 [browser_storage_values.js]
deleted file mode 100644
--- a/devtools/client/storage/test/browser_storage_cookies_delete_all.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/* 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 deleting all cookies
-
-function* performDelete(store, rowName, deleteAll) {
-  let contextMenu = gPanelWindow.document.getElementById(
-    "storage-table-popup");
-  let menuDeleteAllItem = contextMenu.querySelector(
-    "#storage-table-popup-delete-all");
-  let menuDeleteAllFromItem = contextMenu.querySelector(
-    "#storage-table-popup-delete-all-from");
-
-  let storeName = store.join(" > ");
-
-  yield selectTreeItem(store);
-
-  let eventWait = gUI.once("store-objects-updated");
-
-  let cells = getRowCells(rowName);
-  yield waitForContextMenu(contextMenu, cells.name, () => {
-    info(`Opened context menu in ${storeName}, row '${rowName}'`);
-    if (deleteAll) {
-      menuDeleteAllItem.click();
-    } else {
-      menuDeleteAllFromItem.click();
-      let hostName = cells.host.value;
-      ok(menuDeleteAllFromItem.getAttribute("label").includes(hostName),
-        `Context menu item label contains '${hostName}'`);
-    }
-  });
-
-  yield eventWait;
-}
-
-add_task(function*() {
-  yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-listings.html");
-
-  info(`test state before delete`);
-  yield checkState([
-    [["cookies", "test1.example.org"], ["c1", "c3", "cs2", "uc1"]],
-    [["cookies", "sectest1.example.org"], ["cs2", "sc1", "uc1"]],
-  ]);
-
-  info(`delete all from domain`);
-  // delete only cookies that match the host exactly
-  yield performDelete(["cookies", "test1.example.org"], "c1", false);
-
-  info(`test state after delete all from domain`);
-  yield checkState([
-    // Domain cookies (.example.org) must not be deleted.
-    [["cookies", "test1.example.org"], ["cs2", "uc1"]],
-    [["cookies", "sectest1.example.org"], ["cs2", "sc1", "uc1"]],
-  ]);
-
-  info(`delete all`);
-  // delete all cookies for host, including domain cookies
-  yield performDelete(["cookies", "sectest1.example.org"], "uc1", true);
-
-  info(`test state after delete all`);
-  yield checkState([
-    // Domain cookies (.example.org) are deleted too, so deleting in sectest1
-    // also removes stuff from test1.
-    [["cookies", "test1.example.org"], []],
-    [["cookies", "sectest1.example.org"], []],
-  ]);
-
-  yield finishTests();
-});
--- a/devtools/client/storage/test/browser_storage_delete.js
+++ b/devtools/client/storage/test/browser_storage_delete.js
@@ -23,28 +23,27 @@ add_task(function* () {
   let contextMenu = gPanelWindow.document.getElementById("storage-table-popup");
   let menuDeleteItem = contextMenu.querySelector("#storage-table-popup-delete");
 
   for (let [ [store, host], rowName, cellToClick] of TEST_CASES) {
     info(`Selecting tree item ${store} > ${host}`);
     yield selectTreeItem([store, host]);
 
     let row = getRowCells(rowName);
+
     ok(gUI.table.items.has(rowName),
       `There is a row '${rowName}' in ${store} > ${host}`);
 
-    let eventWait = gUI.once("store-objects-updated");
-
     yield waitForContextMenu(contextMenu, row[cellToClick], () => {
       info(`Opened context menu in ${store} > ${host}, row '${rowName}'`);
       menuDeleteItem.click();
       ok(menuDeleteItem.getAttribute("label").includes(rowName),
         `Context menu item label contains '${rowName}'`);
     });
 
-    yield eventWait;
+    yield gUI.once("store-objects-updated");
 
     ok(!gUI.table.items.has(rowName),
       `There is no row '${rowName}' in ${store} > ${host} after deletion`);
   }
 
   yield finishTests();
 });
deleted file mode 100644
--- a/devtools/client/storage/test/browser_storage_delete_all.js
+++ /dev/null
@@ -1,79 +0,0 @@
-/* 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 deleting all storage items
-
-add_task(function*() {
-  yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-listings.html");
-
-  let contextMenu = gPanelWindow.document.getElementById("storage-table-popup");
-  let menuDeleteAllItem = contextMenu.querySelector(
-    "#storage-table-popup-delete-all");
-
-  info(`test state before delete`);
-  const beforeState = [
-    [["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"]],
-  ];
-
-  yield checkState(beforeState);
-
-  info(`do the delete`);
-  const deleteHosts = [
-    [["localStorage", "https://sectest1.example.org"], "iframe-s-ls1"],
-    [["sessionStorage", "https://sectest1.example.org"], "iframe-s-ss1"],
-  ];
-
-  for (let [store, rowName] of deleteHosts) {
-    let storeName = store.join(" > ");
-
-    yield selectTreeItem(store);
-
-    let eventWait = gUI.once("store-objects-cleared");
-
-    let cell = getRowCells(rowName).name;
-    yield waitForContextMenu(contextMenu, cell, () => {
-      info(`Opened context menu in ${storeName}, row '${rowName}'`);
-      menuDeleteAllItem.click();
-    });
-
-    yield eventWait;
-  }
-
-  info(`test state after delete`);
-  const afterState = [
-    // iframes from the same host, one secure, one unsecure, are independent
-    // from each other. Delete all in one doesn't touch the other one.
-    [["localStorage", "http://test1.example.org"],
-      ["ls1", "ls2"]],
-    [["localStorage", "http://sectest1.example.org"],
-      ["iframe-u-ls1"]],
-    [["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"],
-      []],
-  ];
-
-  yield checkState(afterState);
-
-  yield finishTests();
-});
deleted file mode 100644
--- a/devtools/client/storage/test/browser_storage_delete_tree.js
+++ /dev/null
@@ -1,60 +0,0 @@
-/* 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 deleting all storage items from the tree.
-
-add_task(function*() {
-  yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-listings.html");
-
-  let contextMenu = gPanelWindow.document.getElementById("storage-tree-popup");
-  let menuDeleteAllItem = contextMenu.querySelector(
-    "#storage-tree-popup-delete-all");
-
-  info(`test state before delete`);
-  yield checkState([
-    [["cookies", "test1.example.org"], ["c1", "c3", "cs2", "uc1"]],
-    [["localStorage", "http://test1.example.org"], ["ls1", "ls2"]],
-    [["sessionStorage", "http://test1.example.org"], ["ss1"]],
-  ]);
-
-  info(`do the delete`);
-  const deleteHosts = [
-    ["cookies", "test1.example.org"],
-    ["localStorage", "http://test1.example.org"],
-    ["sessionStorage", "http://test1.example.org"],
-  ];
-
-  for (let store of deleteHosts) {
-    let storeName = store.join(" > ");
-
-    yield selectTreeItem(store);
-
-    let eventName = "store-objects-" +
-      (store[0] == "cookies" ? "updated" : "cleared");
-    let eventWait = gUI.once(eventName);
-
-    let selector = `[data-id='${JSON.stringify(store)}'] > .tree-widget-item`;
-    let target = gPanelWindow.document.querySelector(selector);
-    ok(target, `tree item found in ${storeName}`);
-    yield waitForContextMenu(contextMenu, target, () => {
-      info(`Opened tree context menu in ${storeName}`);
-      menuDeleteAllItem.click();
-    });
-
-    yield eventWait;
-  }
-
-  info(`test state after delete`);
-  yield checkState([
-    [["cookies", "test1.example.org"], []],
-    [["localStorage", "http://test1.example.org"], []],
-    [["sessionStorage", "http://test1.example.org"], []],
-  ]);
-
-  yield finishTests();
-});
--- a/devtools/client/storage/test/head.js
+++ b/devtools/client/storage/test/head.js
@@ -504,23 +504,27 @@ function matchVariablesViewProperty(prop
 
 /**
  * Click selects a row in the table.
  *
  * @param {[String]} ids
  *        The array id of the item in the tree
  */
 function* selectTreeItem(ids) {
-  /* If this item is already selected, return */
-  if (gUI.tree.isSelected(ids)) {
-    return;
-  }
+  // Expand tree as some/all items could be collapsed leading to click on an
+  // incorrect tree item
+  gUI.tree.expandAll();
+
+  let selector = "[data-id='" + JSON.stringify(ids) + "'] > .tree-widget-item";
+  let target = gPanelWindow.document.querySelector(selector);
+  ok(target, "tree item found with ids " + JSON.stringify(ids));
 
   let updated = gUI.once("store-objects-updated");
-  gUI.tree.selectedItem = ids;
+
+  yield click(target);
   yield updated;
 }
 
 /**
  * Click selects a row in the table.
  *
  * @param {String} id
  *        The id of the row in the table widget
@@ -836,40 +840,13 @@ function waitForContextMenu(popup, butto
     onHidden && onHidden();
 
     deferred.resolve(popup);
   }
 
   popup.addEventListener("popupshown", onPopupShown);
 
   info("wait for the context menu to open");
-  button.scrollIntoView();
   let eventDetails = {type: "contextmenu", button: 2};
   EventUtils.synthesizeMouse(button, 2, 2, eventDetails,
                              button.ownerDocument.defaultView);
   return deferred.promise;
 }
-
-/**
- * Verify the storage inspector state: check that given type/host exists
- * in the tree, and that the table contains rows with specified names.
- *
- * @param {Array} state Array of state specifications. For example,
- *        [["cookies", "example.com"], ["c1", "c2"]] means to select the
- *        "example.com" host in cookies and then verify there are "c1" and "c2"
- *        cookies (and no other ones).
- */
-function* checkState(state) {
-  for (let [store, names] of state) {
-    let storeName = store.join(" > ");
-    info(`Selecting tree item ${storeName}`);
-    yield selectTreeItem(store);
-
-    let items = gUI.table.items;
-
-    is(items.size, names.length,
-      `There is correct number of rows in ${storeName}`);
-    for (let name of names) {
-      ok(items.has(name),
-        `There is item with name '${name}' in ${storeName}`);
-    }
-  }
-}
--- a/devtools/client/storage/ui.js
+++ b/devtools/client/storage/ui.js
@@ -65,20 +65,17 @@ var StorageUI = this.StorageUI = functio
   EventEmitter.decorate(this);
 
   this._target = target;
   this._window = panelWin;
   this._panelDoc = panelWin.document;
   this.front = front;
 
   let treeNode = this._panelDoc.getElementById("storage-tree");
-  this.tree = new TreeWidget(treeNode, {
-    defaultType: "dir",
-    contextMenuId: "storage-tree-popup"
-  });
+  this.tree = new TreeWidget(treeNode, {defaultType: "dir"});
   this.onHostSelect = this.onHostSelect.bind(this);
   this.tree.on("select", this.onHostSelect);
 
   let tableNode = this._panelDoc.getElementById("storage-table");
   this.table = new TableWidget(tableNode, {
     emptyText: L10N.getStr("table.emptyText"),
     highlightUpdated: true,
     cellContextMenuId: "storage-table-popup"
@@ -109,51 +106,32 @@ var StorageUI = this.StorageUI = functio
   this.onUpdate = this.onUpdate.bind(this);
   this.front.on("stores-update", this.onUpdate);
   this.onCleared = this.onCleared.bind(this);
   this.front.on("stores-cleared", this.onCleared);
 
   this.handleKeypress = this.handleKeypress.bind(this);
   this._panelDoc.addEventListener("keypress", this.handleKeypress);
 
-  this.onTreePopupShowing = this.onTreePopupShowing.bind(this);
-  this._treePopup = this._panelDoc.getElementById("storage-tree-popup");
-  this._treePopup.addEventListener("popupshowing", this.onTreePopupShowing);
-
-  this.onTablePopupShowing = this.onTablePopupShowing.bind(this);
+  this.onPopupShowing = this.onPopupShowing.bind(this);
   this._tablePopup = this._panelDoc.getElementById("storage-table-popup");
-  this._tablePopup.addEventListener("popupshowing", this.onTablePopupShowing);
+  this._tablePopup.addEventListener("popupshowing", this.onPopupShowing, false);
 
   this.onRemoveItem = this.onRemoveItem.bind(this);
-  this.onRemoveAllFrom = this.onRemoveAllFrom.bind(this);
-  this.onRemoveAll = this.onRemoveAll.bind(this);
-
   this._tablePopupDelete = this._panelDoc.getElementById(
     "storage-table-popup-delete");
-  this._tablePopupDelete.addEventListener("command", this.onRemoveItem);
-
-  this._tablePopupDeleteAllFrom = this._panelDoc.getElementById(
-    "storage-table-popup-delete-all-from");
-  this._tablePopupDeleteAllFrom.addEventListener("command",
-    this.onRemoveAllFrom);
-
-  this._tablePopupDeleteAll = this._panelDoc.getElementById(
-    "storage-table-popup-delete-all");
-  this._tablePopupDeleteAll.addEventListener("command", this.onRemoveAll);
-
-  this._treePopupDeleteAll = this._panelDoc.getElementById(
-    "storage-tree-popup-delete-all");
-  this._treePopupDeleteAll.addEventListener("command", this.onRemoveAll);
+  this._tablePopupDelete.addEventListener("command", this.onRemoveItem, false);
 };
 
 exports.StorageUI = StorageUI;
 
 StorageUI.prototype = {
 
   storageTypes: null,
+  shouldResetColumns: true,
   shouldLoadMoreItems: true,
 
   set animationsEnabled(value) {
     this._panelDoc.documentElement.classList.toggle("no-animate", !value);
   },
 
   destroy: function() {
     this.table.off(TableWidget.EVENTS.ROW_SELECTED, this.displayObjectSidebar);
@@ -162,26 +140,18 @@ StorageUI.prototype = {
     this.table.destroy();
 
     this.front.off("stores-update", this.onUpdate);
     this.front.off("stores-cleared", this.onCleared);
     this._panelDoc.removeEventListener("keypress", this.handleKeypress);
     this.searchBox.removeEventListener("input", this.filterItems);
     this.searchBox = null;
 
-    this._treePopup.removeEventListener("popupshowing",
-      this.onTreePopupShowing);
-    this._treePopupDeleteAll.removeEventListener("command", this.onRemoveAll);
-
-    this._tablePopup.removeEventListener("popupshowing",
-      this.onTablePopupShowing);
+    this._tablePopup.removeEventListener("popupshowing", this.onPopupShowing);
     this._tablePopupDelete.removeEventListener("command", this.onRemoveItem);
-    this._tablePopupDeleteAllFrom.removeEventListener("command",
-      this.onRemoveAllFrom);
-    this._tablePopupDeleteAll.removeEventListener("command", this.onRemoveAll);
   },
 
   /**
    * Empties and hides the object viewer sidebar
    */
   hideSidebar: function() {
     this.view.empty();
     this.sidebar.hidden = true;
@@ -416,20 +386,20 @@ StorageUI.prototype = {
       throw new Error("Invalid reason specified");
     }
 
     storageType.getStoreObjects(host, names, fetchOpts).then(({data}) => {
       if (!data.length) {
         this.emit("store-objects-updated");
         return;
       }
-      if (reason === REASON.POPULATE) {
+      if (this.shouldResetColumns) {
         this.resetColumns(data[0], type);
-        this.table.host = host;
       }
+      this.table.host = host;
       this.populateTable(data, reason);
       this.emit("store-objects-updated");
 
       this.makeFieldsEditable();
     }, Cu.reportError);
   },
 
   /**
@@ -462,23 +432,25 @@ StorageUI.prototype = {
       for (let host in storageTypes[type].hosts) {
         this.tree.add([type, {id: host, type: "url"}]);
         for (let name of storageTypes[type].hosts[host]) {
           try {
             let names = JSON.parse(name);
             this.tree.add([type, host, ...names]);
             if (!this.tree.selectedItem) {
               this.tree.selectedItem = [type, host, names[0], names[1]];
+              this.fetchStorageObjects(type, host, [name], REASON.POPULATE);
             }
           } catch (ex) {
             // Do Nothing
           }
         }
         if (!this.tree.selectedItem) {
           this.tree.selectedItem = [type, host];
+          this.fetchStorageObjects(type, host, null, REASON.POPULATE);
         }
       }
     }
   },
 
   /**
    * Populates the selected entry from teh table in the sidebar for a more
    * detailed view.
@@ -648,16 +620,17 @@ StorageUI.prototype = {
     let [type, host] = item;
     let names = null;
     if (!host) {
       return;
     }
     if (item.length > 2) {
       names = [JSON.stringify(item.slice(2))];
     }
+    this.shouldResetColumns = true;
     this.fetchStorageObjects(type, host, names, REASON.POPULATE);
     this.itemOffset = 0;
   },
 
   /**
    * Resets the column headers in the storage table with the pased object `data`
    *
    * @param {object} data
@@ -679,16 +652,17 @@ StorageUI.prototype = {
         columns[key] = L10N.getStr("table.headers." + type + "." + key);
       } catch (e) {
         console.error("Unable to localize table header type:" + type +
                       " key:" + key);
       }
     }
     this.table.setColumns(columns, null, HIDDEN_COLUMNS);
     this.table.datatype = type;
+    this.shouldResetColumns = false;
     this.hideSidebar();
   },
 
   /**
    * Populates or updates the rows in the storage table.
    *
    * @param {array[object]} data
    *        Array of objects to be populated in the storage table
@@ -778,96 +752,39 @@ StorageUI.prototype = {
     this.fetchStorageObjects(type, host, names, REASON.NEXT_50_ITEMS);
   },
 
   /**
    * Fires before a cell context menu with the "Delete" action is shown.
    * If the current storage actor doesn't support removing items, prevent
    * showing the menu.
    */
-  onTablePopupShowing: function(event) {
+  onPopupShowing: function(event) {
     if (!this.getCurrentActor().removeItem) {
       event.preventDefault();
       return;
     }
 
-    const maxLen = ITEM_NAME_MAX_LENGTH;
-    let [type] = this.tree.selectedItem;
     let rowId = this.table.contextMenuRowId;
     let data = this.table.items.get(rowId);
     let name = data[this.table.uniqueId];
 
+    const maxLen = ITEM_NAME_MAX_LENGTH;
     if (name.length > maxLen) {
       name = name.substr(0, maxLen) + L10N.ellipsis;
     }
 
     this._tablePopupDelete.setAttribute("label",
       L10N.getFormatStr("storage.popupMenu.deleteLabel", name));
-
-    if (type === "cookies") {
-      let host = data.host;
-      if (host.length > maxLen) {
-        host = host.substr(0, maxLen) + L10N.ellipsis;
-      }
-
-      this._tablePopupDeleteAllFrom.hidden = false;
-      this._tablePopupDeleteAllFrom.setAttribute("label",
-        L10N.getFormatStr("storage.popupMenu.deleteAllFromLabel", host));
-    } else {
-      this._tablePopupDeleteAllFrom.hidden = true;
-    }
-  },
-
-  onTreePopupShowing: function(event) {
-    let showMenu = false;
-    let selectedItem = this.tree.selectedItem;
-    // Never show menu on the 1st level item
-    if (selectedItem && selectedItem.length > 1) {
-      // this.currentActor() would return wrong value here
-      let actor = this.storageTypes[selectedItem[0]];
-      if (actor.removeAll) {
-        showMenu = true;
-      }
-    }
-
-    if (!showMenu) {
-      event.preventDefault();
-    }
   },
 
   /**
    * Handles removing an item from the storage
    */
   onRemoveItem: function() {
     let [, host] = this.tree.selectedItem;
     let actor = this.getCurrentActor();
     let rowId = this.table.contextMenuRowId;
     let data = this.table.items.get(rowId);
 
     actor.removeItem(host, data[this.table.uniqueId]);
   },
-
-  /**
-   * Handles removing all items from the storage
-   */
-  onRemoveAll: function() {
-    // Cannot use this.currentActor() if the handler is called from the
-    // tree context menu: it returns correct value only after the table
-    // data from server are successfully fetched (and that's async).
-    let [type, host] = this.tree.selectedItem;
-    let actor = this.storageTypes[type];
-
-    actor.removeAll(host);
-  },
-
-  /**
-   * Handles removing all cookies with exactly the same domain as the
-   * cookie in the selected row.
-   */
-  onRemoveAllFrom: function() {
-    let [, host] = this.tree.selectedItem;
-    let actor = this.getCurrentActor();
-    let rowId = this.table.contextMenuRowId;
-    let data = this.table.items.get(rowId);
-
-    actor.removeAll(host, data.host);
-  },
 };
--- a/devtools/server/actors/storage.js
+++ b/devtools/server/actors/storage.js
@@ -681,48 +681,31 @@ StorageActors.createActor({
     },
     response: {}
   }),
 
   removeItem: method(Task.async(function*(host, name) {
     this.removeCookie(host, name);
   }), {
     request: {
-      host: Arg(0, "string"),
-      name: Arg(1, "string"),
-    },
-    response: {}
-  }),
-
-  removeAll: method(Task.async(function*(host, domain) {
-    this.removeAllCookies(host, domain);
-  }), {
-    request: {
-      host: Arg(0, "string"),
-      domain: Arg(1, "nullable:string")
+      host: Arg(0),
+      name: Arg(1),
     },
     response: {}
   }),
 
   maybeSetupChildProcess: function() {
     cookieHelpers.onCookieChanged = this.onCookieChanged.bind(this);
 
     if (!DebuggerServer.isInChildProcess) {
-      this.getCookiesFromHost =
-        cookieHelpers.getCookiesFromHost.bind(cookieHelpers);
-      this.addCookieObservers =
-        cookieHelpers.addCookieObservers.bind(cookieHelpers);
-      this.removeCookieObservers =
-        cookieHelpers.removeCookieObservers.bind(cookieHelpers);
-      this.editCookie =
-        cookieHelpers.editCookie.bind(cookieHelpers);
-      this.removeCookie =
-        cookieHelpers.removeCookie.bind(cookieHelpers);
-      this.removeAllCookies =
-        cookieHelpers.removeAllCookies.bind(cookieHelpers);
+      this.getCookiesFromHost = cookieHelpers.getCookiesFromHost;
+      this.addCookieObservers = cookieHelpers.addCookieObservers;
+      this.removeCookieObservers = cookieHelpers.removeCookieObservers;
+      this.editCookie = cookieHelpers.editCookie;
+      this.removeCookie = cookieHelpers.removeCookie;
       return;
     }
 
     const { sendSyncMessage, addMessageListener } =
       this.conn.parentMessageManager;
 
     this.conn.setupInParent({
       module: "devtools/server/actors/storage",
@@ -734,18 +717,16 @@ StorageActors.createActor({
     this.addCookieObservers =
       callParentProcess.bind(null, "addCookieObservers");
     this.removeCookieObservers =
       callParentProcess.bind(null, "removeCookieObservers");
     this.editCookie =
       callParentProcess.bind(null, "editCookie");
     this.removeCookie =
       callParentProcess.bind(null, "removeCookie");
-    this.removeAllCookies =
-      callParentProcess.bind(null, "removeAllCookies");
 
     addMessageListener("storage:storage-cookie-request-child",
                        cookieHelpers.handleParentRequest);
 
     function callParentProcess(methodName, ...args) {
       let reply = sendSyncMessage("storage:storage-cookie-request-parent", {
         method: methodName,
         args: args
@@ -889,54 +870,42 @@ var cookieHelpers = {
       cookie.value,
       cookie.isSecure,
       cookie.isHttpOnly,
       cookie.isSession,
       cookie.isSession ? MAX_COOKIE_EXPIRY : cookie.expires
     );
   },
 
-  _removeCookies: function(host, opts = {}) {
+  removeCookie: function(host, name) {
     function hostMatches(cookieHost, matchHost) {
       if (cookieHost == null) {
         return matchHost == null;
       }
       if (cookieHost.startsWith(".")) {
         return matchHost.endsWith(cookieHost);
       }
       return cookieHost == host;
     }
 
     let enumerator = Services.cookies.getCookiesFromHost(host);
     while (enumerator.hasMoreElements()) {
       let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
-      if (hostMatches(cookie.host, host) &&
-          (!opts.name || cookie.name === opts.name) &&
-          (!opts.domain || cookie.host === opts.domain)) {
+      if (hostMatches(cookie.host, host) && cookie.name === name) {
         Services.cookies.remove(
           cookie.host,
           cookie.name,
           cookie.path,
           cookie.originAttributes,
           false
         );
       }
     }
   },
 
-  removeCookie: function(host, name) {
-    if (name !== undefined) {
-      this._removeCookies(host, { name });
-    }
-  },
-
-  removeAllCookies: function(host, domain) {
-    this._removeCookies(host, { domain });
-  },
-
   addCookieObservers: function() {
     Services.obs.addObserver(cookieHelpers, "cookie-changed", false);
     return null;
   },
 
   removeCookieObservers: function() {
     Services.obs.removeObserver(cookieHelpers, "cookie-changed", false);
     return null;
@@ -995,21 +964,16 @@ var cookieHelpers = {
         let rowdata = msg.data.args[0];
         return cookieHelpers.editCookie(rowdata);
       }
       case "removeCookie": {
         let host = msg.data.args[0];
         let name = msg.data.args[1];
         return cookieHelpers.removeCookie(host, name);
       }
-      case "removeAllCookies": {
-        let host = msg.data.args[0];
-        let domain = msg.data.args[1];
-        return cookieHelpers.removeAllCookies(host, domain);
-      }
       default:
         console.error("ERR_DIRECTOR_PARENT_UNKNOWN_METHOD", msg.json.method);
         throw new Error("ERR_DIRECTOR_PARENT_UNKNOWN_METHOD");
     }
   },
 };
 
 /**
@@ -1211,26 +1175,16 @@ function getObjectForLocalOrSessionStora
       storage.removeItem(name);
     }), {
       request: {
         host: Arg(0),
         name: Arg(1),
       },
       response: {}
     }),
-
-    removeAll: method(Task.async(function*(host) {
-      let storage = this.hostVsStores.get(host);
-      storage.clear();
-    }), {
-      request: {
-        host: Arg(0)
-      },
-      response: {}
-    }),
   };
 }
 
 /**
  * The Local Storage actor and front.
  */
 StorageActors.createActor({
   typeName: "localStorage",
@@ -2119,17 +2073,17 @@ var StorageActor = exports.StorageActor 
       type: "storesUpdate",
       data: Arg(0, "storeUpdateObject")
     },
     "stores-cleared": {
       type: "storesCleared",
       data: Arg(0, "json")
     },
     "stores-reloaded": {
-      type: "storesReloaded",
+      type: "storesRelaoded",
       data: Arg(0, "json")
     }
   },
 
   initialize: function(conn, tabActor) {
     protocol.Actor.prototype.initialize.call(this, null);
 
     this.conn = conn;
@@ -2351,23 +2305,21 @@ var StorageActor = exports.StorageActor 
     }
     if (!this.boundUpdate[action]) {
       this.boundUpdate[action] = {};
     }
     if (!this.boundUpdate[action][storeType]) {
       this.boundUpdate[action][storeType] = {};
     }
     for (let host in data) {
-      if (!this.boundUpdate[action][storeType][host]) {
-        this.boundUpdate[action][storeType][host] = [];
-      }
-      for (let name of data[host]) {
-        if (!this.boundUpdate[action][storeType][host].includes(name)) {
-          this.boundUpdate[action][storeType][host].push(name);
-        }
+      if (!this.boundUpdate[action][storeType][host] || action == "deleted") {
+        this.boundUpdate[action][storeType][host] = data[host];
+      } else {
+        this.boundUpdate[action][storeType][host] =
+        this.boundUpdate[action][storeType][host].concat(data[host]);
       }
     }
     if (action == "added") {
       // If the same store name was previously deleted or changed, but now is
       // added somehow, dont send the deleted or changed update.
       this.removeNamesFromUpdateList("deleted", storeType, data);
       this.removeNamesFromUpdateList("changed", storeType, data);
     } else if (action == "changed" && this.boundUpdate.added &&