summaryrefslogtreecommitdiffstats
path: root/devtools/client
diff options
context:
space:
mode:
authorjanekptacijarabaci <janekptacijarabaci@seznam.cz>2018-03-02 13:36:16 +0100
committerjanekptacijarabaci <janekptacijarabaci@seznam.cz>2018-03-02 13:36:16 +0100
commit390894c822f1b163f16744646372a28c0d93a89e (patch)
tree29b6368ffd292bafcc098a0215cb83d0a7a925ec /devtools/client
parente272829137195b46612b7664c9416364089f7baa (diff)
downloadUXP-390894c822f1b163f16744646372a28c0d93a89e.tar
UXP-390894c822f1b163f16744646372a28c0d93a89e.tar.gz
UXP-390894c822f1b163f16744646372a28c0d93a89e.tar.lz
UXP-390894c822f1b163f16744646372a28c0d93a89e.tar.xz
UXP-390894c822f1b163f16744646372a28c0d93a89e.zip
Bug 1146194: Multiple cookies with the same name not shown
Issue #31
Diffstat (limited to 'devtools/client')
-rw-r--r--devtools/client/locales/en-US/storage.properties1
-rw-r--r--devtools/client/shared/widgets/TableWidget.js34
-rw-r--r--devtools/client/storage/test/browser.ini4
-rw-r--r--devtools/client/storage/test/browser_storage_basic.js23
-rw-r--r--devtools/client/storage/test/browser_storage_cookies_delete_all.js44
-rw-r--r--devtools/client/storage/test/browser_storage_cookies_domain.js12
-rw-r--r--devtools/client/storage/test/browser_storage_cookies_edit.js21
-rw-r--r--devtools/client/storage/test/browser_storage_cookies_edit_keyboard.js5
-rw-r--r--devtools/client/storage/test/browser_storage_cookies_tab_navigation.js3
-rw-r--r--devtools/client/storage/test/browser_storage_delete.js8
-rw-r--r--devtools/client/storage/test/browser_storage_delete_tree.js10
-rw-r--r--devtools/client/storage/test/browser_storage_dynamic_updates_cookies.js188
-rw-r--r--devtools/client/storage/test/browser_storage_dynamic_updates_localStorage.js70
-rw-r--r--devtools/client/storage/test/browser_storage_dynamic_updates_sessionStorage.js83
-rw-r--r--devtools/client/storage/test/browser_storage_sidebar.js8
-rw-r--r--devtools/client/storage/test/browser_storage_values.js14
-rw-r--r--devtools/client/storage/test/head.js47
-rw-r--r--devtools/client/storage/test/storage-updates.html4
-rw-r--r--devtools/client/storage/ui.js32
19 files changed, 553 insertions, 58 deletions
diff --git a/devtools/client/locales/en-US/storage.properties b/devtools/client/locales/en-US/storage.properties
index 1eeb88ff9..fd3b3ec52 100644
--- a/devtools/client/locales/en-US/storage.properties
+++ b/devtools/client/locales/en-US/storage.properties
@@ -35,6 +35,7 @@ tree.labels.Cache=Cache Storage
# LOCALIZATION NOTE (table.headers.*.*):
# These strings are the header names of the columns in the Storage Table for
# each type of storage available through the Storage Tree to the side.
+table.headers.cookies.uniqueKey=Unique key
table.headers.cookies.name=Name
table.headers.cookies.path=Path
table.headers.cookies.host=Domain
diff --git a/devtools/client/shared/widgets/TableWidget.js b/devtools/client/shared/widgets/TableWidget.js
index 5dacd1b67..96c020230 100644
--- a/devtools/client/shared/widgets/TableWidget.js
+++ b/devtools/client/shared/widgets/TableWidget.js
@@ -615,8 +615,13 @@ TableWidget.prototype = {
/**
* Populates the header context menu with the names of the columns along with
* displaying which columns are hidden or visible.
+ *
+ * @param {Array} privateColumns=[]
+ * An array of column names that should never appear in the table. This
+ * allows us to e.g. have an invisible compound primary key for a
+ * table's rows.
*/
- populateMenuPopup: function () {
+ populateMenuPopup: function (privateColumns = []) {
if (!this.menupopup) {
return;
}
@@ -626,6 +631,10 @@ TableWidget.prototype = {
}
for (let column of this.columns.values()) {
+ if (privateColumns.includes(column.id)) {
+ continue;
+ }
+
let menuitem = this.document.createElementNS(XUL_NS, "menuitem");
menuitem.setAttribute("label", column.header.getAttribute("value"));
menuitem.setAttribute("data-id", column.id);
@@ -663,16 +672,21 @@ TableWidget.prototype = {
* Creates the columns in the table. Without calling this method, data cannot
* be inserted into the table unless `initialColumns` was supplied.
*
- * @param {object} columns
+ * @param {Object} columns
* A key value pair representing the columns of the table. Where the
* key represents the id of the column and the value is the displayed
* label in the header of the column.
- * @param {string} sortOn
+ * @param {String} sortOn
* The id of the column on which the table will be initially sorted on.
- * @param {array} hiddenColumns
+ * @param {Array} hiddenColumns
* Ids of all the columns that are hidden by default.
+ * @param {Array} privateColumns=[]
+ * An array of column names that should never appear in the table. This
+ * allows us to e.g. have an invisible compound primary key for a
+ * table's rows.
*/
- setColumns: function (columns, sortOn = this.sortedOn, hiddenColumns = []) {
+ setColumns: function (columns, sortOn = this.sortedOn, hiddenColumns = [],
+ privateColumns = []) {
for (let column of this.columns.values()) {
column.destroy();
}
@@ -702,13 +716,14 @@ TableWidget.prototype = {
}
this.columns.set(id, new Column(this, id, columns[id]));
- if (hiddenColumns.indexOf(id) > -1) {
+ if (hiddenColumns.includes(id) || privateColumns.includes(id)) {
+ // Hide the column.
this.columns.get(id).toggleColumn();
}
}
this.sortedOn = sortOn;
this.sortBy(this.sortedOn);
- this.populateMenuPopup();
+ this.populateMenuPopup(privateColumns);
},
/**
@@ -778,6 +793,11 @@ TableWidget.prototype = {
return;
}
+ if (this.editBookmark && !this.items.has(this.editBookmark)) {
+ // Key has been updated... update bookmark.
+ this.editBookmark = item[this.uniqueId];
+ }
+
let index = this.columns.get(this.sortedOn).push(item);
for (let [key, column] of this.columns) {
if (key != this.sortedOn) {
diff --git a/devtools/client/storage/test/browser.ini b/devtools/client/storage/test/browser.ini
index dd7f48bd7..0ac28a92d 100644
--- a/devtools/client/storage/test/browser.ini
+++ b/devtools/client/storage/test/browser.ini
@@ -29,7 +29,9 @@ support-files =
[browser_storage_delete.js]
[browser_storage_delete_all.js]
[browser_storage_delete_tree.js]
-[browser_storage_dynamic_updates.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]
diff --git a/devtools/client/storage/test/browser_storage_basic.js b/devtools/client/storage/test/browser_storage_basic.js
index 343d46170..10eb8d0ca 100644
--- a/devtools/client/storage/test/browser_storage_basic.js
+++ b/devtools/client/storage/test/browser_storage_basic.js
@@ -2,6 +2,8 @@
* 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 */
+
// Basic test to assert that the storage tree and table corresponding to each
// item in the storage tree is correctly displayed
@@ -21,10 +23,23 @@
"use strict";
const testCases = [
- [["cookies", "test1.example.org"],
- ["c1", "cs2", "c3", "uc1"]],
- [["cookies", "sectest1.example.org"],
- ["uc1", "cs2", "sc1"]],
+ [
+ ["cookies", "test1.example.org"],
+ [
+ getCookieId("c1", "test1.example.org", "/browser"),
+ getCookieId("cs2", ".example.org", "/"),
+ getCookieId("c3", "test1.example.org", "/"),
+ getCookieId("uc1", ".example.org", "/")
+ ]
+ ],
+ [
+ ["cookies", "sectest1.example.org"],
+ [
+ getCookieId("uc1", ".example.org", "/"),
+ getCookieId("cs2", ".example.org", "/"),
+ getCookieId("sc1", "sectest1.example.org", "/browser/devtools/client/storage/test/")
+ ]
+ ],
[["localStorage", "http://test1.example.org"],
["ls1", "ls2"]],
[["localStorage", "http://sectest1.example.org"],
diff --git a/devtools/client/storage/test/browser_storage_cookies_delete_all.js b/devtools/client/storage/test/browser_storage_cookies_delete_all.js
index 6e6008e66..ba64014fd 100644
--- a/devtools/client/storage/test/browser_storage_cookies_delete_all.js
+++ b/devtools/client/storage/test/browser_storage_cookies_delete_all.js
@@ -21,8 +21,8 @@ function* performDelete(store, rowName, deleteAll) {
yield selectTreeItem(store);
let eventWait = gUI.once("store-objects-updated");
+ let cells = getRowCells(rowName, true);
- let cells = getRowCells(rowName);
yield waitForContextMenu(contextMenu, cells.name, () => {
info(`Opened context menu in ${storeName}, row '${rowName}'`);
if (deleteAll) {
@@ -43,24 +43,54 @@ add_task(function* () {
info("test state before delete");
yield checkState([
- [["cookies", "test1.example.org"], ["c1", "c3", "cs2", "uc1"]],
- [["cookies", "sectest1.example.org"], ["cs2", "sc1", "uc1"]],
+ [
+ ["cookies", "test1.example.org"], [
+ getCookieId("c1", "test1.example.org", "/browser"),
+ getCookieId("c3", "test1.example.org", "/"),
+ getCookieId("cs2", ".example.org", "/"),
+ getCookieId("uc1", ".example.org", "/")
+ ]
+ ],
+ [
+ ["cookies", "sectest1.example.org"], [
+ getCookieId("cs2", ".example.org", "/"),
+ getCookieId("sc1", "sectest1.example.org",
+ "/browser/devtools/client/storage/test/"),
+ getCookieId("uc1", ".example.org", "/")
+ ]
+ ],
]);
info("delete all from domain");
// delete only cookies that match the host exactly
- yield performDelete(["cookies", "test1.example.org"], "c1", false);
+ let id = getCookieId("c1", "test1.example.org", "/browser");
+ yield performDelete(["cookies", "test1.example.org"], id, 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"]],
+ [
+ ["cookies", "test1.example.org"],
+ [
+ getCookieId("cs2", ".example.org", "/"),
+ getCookieId("uc1", ".example.org", "/")
+ ]
+ ],
+ [
+ ["cookies", "sectest1.example.org"],
+ [
+ getCookieId("cs2", ".example.org", "/"),
+ getCookieId("uc1", ".example.org", "/"),
+ getCookieId("sc1", "sectest1.example.org",
+ "/browser/devtools/client/storage/test/"),
+ ]
+ ],
]);
info("delete all");
// delete all cookies for host, including domain cookies
- yield performDelete(["cookies", "sectest1.example.org"], "uc1", true);
+ id = getCookieId("uc1", ".example.org", "/");
+ yield performDelete(["cookies", "sectest1.example.org"], id, true);
info("test state after delete all");
yield checkState([
diff --git a/devtools/client/storage/test/browser_storage_cookies_domain.js b/devtools/client/storage/test/browser_storage_cookies_domain.js
index dc93d6e67..7b194b73e 100644
--- a/devtools/client/storage/test/browser_storage_cookies_domain.js
+++ b/devtools/client/storage/test/browser_storage_cookies_domain.js
@@ -13,8 +13,16 @@ add_task(function* () {
yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-cookies.html");
yield checkState([
- [["cookies", "test1.example.org"],
- ["test1", "test2", "test3", "test4", "test5"]],
+ [
+ ["cookies", "test1.example.org"],
+ [
+ getCookieId("test1", ".test1.example.org", "/browser"),
+ getCookieId("test2", "test1.example.org", "/browser"),
+ getCookieId("test3", ".test1.example.org", "/browser"),
+ getCookieId("test4", "test1.example.org", "/browser"),
+ getCookieId("test5", ".test1.example.org", "/browser")
+ ]
+ ],
]);
yield finishTests();
diff --git a/devtools/client/storage/test/browser_storage_cookies_edit.js b/devtools/client/storage/test/browser_storage_cookies_edit.js
index 5818e4864..14944b398 100644
--- a/devtools/client/storage/test/browser_storage_cookies_edit.js
+++ b/devtools/client/storage/test/browser_storage_cookies_edit.js
@@ -10,13 +10,20 @@ add_task(function* () {
yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-cookies.html");
showAllColumns(true);
- yield editCell("test3", "name", "newTest3");
- yield editCell("newTest3", "path", "/");
- yield editCell("newTest3", "host", "test1.example.org");
- yield editCell("newTest3", "expires", "Tue, 14 Feb 2040 17:41:14 GMT");
- yield editCell("newTest3", "value", "newValue3");
- yield editCell("newTest3", "isSecure", "true");
- yield editCell("newTest3", "isHttpOnly", "true");
+ let id = getCookieId("test3", ".test1.example.org", "/browser");
+ yield editCell(id, "name", "newTest3");
+
+ id = getCookieId("newTest3", ".test1.example.org", "/browser");
+ yield editCell(id, "host", "test1.example.org");
+
+ id = getCookieId("newTest3", "test1.example.org", "/browser");
+ yield editCell(id, "path", "/");
+
+ id = getCookieId("newTest3", "test1.example.org", "/");
+ yield editCell(id, "expires", "Tue, 14 Feb 2040 17:41:14 GMT");
+ yield editCell(id, "value", "newValue3");
+ yield editCell(id, "isSecure", "true");
+ yield editCell(id, "isHttpOnly", "true");
yield finishTests();
});
diff --git a/devtools/client/storage/test/browser_storage_cookies_edit_keyboard.js b/devtools/client/storage/test/browser_storage_cookies_edit_keyboard.js
index 1208c4376..4bbb63fbe 100644
--- a/devtools/client/storage/test/browser_storage_cookies_edit_keyboard.js
+++ b/devtools/client/storage/test/browser_storage_cookies_edit_keyboard.js
@@ -10,10 +10,11 @@ add_task(function* () {
yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-cookies.html");
showAllColumns(true);
- yield startCellEdit("test4", "name");
+ let id = getCookieId("test4", "test1.example.org", "/browser");
+ yield startCellEdit(id, "name");
yield typeWithTerminator("test6", "VK_TAB");
- yield typeWithTerminator("/", "VK_TAB");
yield typeWithTerminator(".example.org", "VK_TAB");
+ yield typeWithTerminator("/", "VK_TAB");
yield typeWithTerminator("Tue, 25 Dec 2040 12:00:00 GMT", "VK_TAB");
yield typeWithTerminator("test6value", "VK_TAB");
yield typeWithTerminator("false", "VK_TAB");
diff --git a/devtools/client/storage/test/browser_storage_cookies_tab_navigation.js b/devtools/client/storage/test/browser_storage_cookies_tab_navigation.js
index 783a0c844..5da359b8d 100644
--- a/devtools/client/storage/test/browser_storage_cookies_tab_navigation.js
+++ b/devtools/client/storage/test/browser_storage_cookies_tab_navigation.js
@@ -10,7 +10,8 @@ add_task(function* () {
yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-cookies.html");
showAllColumns(true);
- yield startCellEdit("test1", "name");
+ let id = getCookieId("test1", ".test1.example.org", "/browser");
+ yield startCellEdit(id, "name");
PressKeyXTimes("VK_TAB", 18);
is(getCurrentEditorValue(), "value3",
diff --git a/devtools/client/storage/test/browser_storage_delete.js b/devtools/client/storage/test/browser_storage_delete.js
index c0e2b0ad7..d5cb59a10 100644
--- a/devtools/client/storage/test/browser_storage_delete.js
+++ b/devtools/client/storage/test/browser_storage_delete.js
@@ -13,8 +13,10 @@ const TEST_CASES = [
"ls1", "name"],
[["sessionStorage", "http://test1.example.org"],
"ss1", "name"],
- [["cookies", "test1.example.org"],
- "c1", "name"],
+ [
+ ["cookies", "test1.example.org"],
+ getCookieId("c1", "test1.example.org", "/browser"), "name"
+ ],
[["indexedDB", "http://test1.example.org", "idb1", "obj1"],
1, "name"],
[["Cache", "http://test1.example.org", "plop"],
@@ -41,7 +43,7 @@ add_task(function* () {
yield waitForContextMenu(contextMenu, row[cellToClick], () => {
info(`Opened context menu in ${treeItemName}, row '${rowName}'`);
menuDeleteItem.click();
- let truncatedRowName = String(rowName).substr(0, 16);
+ let truncatedRowName = String(rowName).replace(SEPARATOR_GUID, "-").substr(0, 16);
ok(menuDeleteItem.getAttribute("label").includes(truncatedRowName),
`Context menu item label contains '${rowName}' (maybe truncated)`);
});
diff --git a/devtools/client/storage/test/browser_storage_delete_tree.js b/devtools/client/storage/test/browser_storage_delete_tree.js
index 867a1c8b6..3e866a2f5 100644
--- a/devtools/client/storage/test/browser_storage_delete_tree.js
+++ b/devtools/client/storage/test/browser_storage_delete_tree.js
@@ -17,7 +17,15 @@ add_task(function* () {
info("test state before delete");
yield checkState([
- [["cookies", "test1.example.org"], ["c1", "c3", "cs2", "uc1"]],
+ [
+ ["cookies", "test1.example.org"],
+ [
+ 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]],
diff --git a/devtools/client/storage/test/browser_storage_dynamic_updates_cookies.js b/devtools/client/storage/test/browser_storage_dynamic_updates_cookies.js
new file mode 100644
index 000000000..6cf52f2d3
--- /dev/null
+++ b/devtools/client/storage/test/browser_storage_dynamic_updates_cookies.js
@@ -0,0 +1,188 @@
+/* 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/. */
+
+"use strict";
+
+// Test dynamic updates in the storage inspector for cookies.
+
+add_task(function* () {
+ yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-updates.html");
+
+ gUI.tree.expandAll();
+
+ ok(gUI.sidebar.hidden, "Sidebar is initially hidden");
+ let c1id = getCookieId("c1", "test1.example.org", "/browser");
+ yield selectTableItem(c1id);
+
+ // test that value is something initially
+ let initialValue = [[
+ {name: "c1", value: "1.2.3.4.5.6.7"},
+ {name: "c1.Path", value: "/browser"}
+ ], [
+ {name: "c1", value: "Array"},
+ {name: "c1.0", value: "1"},
+ {name: "c1.6", value: "7"}
+ ]];
+
+ // test that value is something initially
+ let finalValue = [[
+ {name: "c1", value: '{"foo": 4,"bar":6}'},
+ {name: "c1.Path", value: "/browser"}
+ ], [
+ {name: "c1", value: "Object"},
+ {name: "c1.foo", value: "4"},
+ {name: "c1.bar", value: "6"}
+ ]];
+
+ // Check that sidebar shows correct initial value
+ yield findVariableViewProperties(initialValue[0], false);
+
+ yield findVariableViewProperties(initialValue[1], true);
+ // Check if table shows correct initial value
+
+ yield checkState([
+ [
+ ["cookies", "test1.example.org"],
+ [
+ getCookieId("c1", "test1.example.org", "/browser"),
+ getCookieId("c2", "test1.example.org", "/browser")
+ ]
+ ],
+ ]);
+ checkCell(c1id, "value", "1.2.3.4.5.6.7");
+
+ gWindow.addCookie("c1", '{"foo": 4,"bar":6}', "/browser");
+ yield gUI.once("sidebar-updated");
+
+ yield findVariableViewProperties(finalValue[0], false);
+ yield findVariableViewProperties(finalValue[1], true);
+
+ yield checkState([
+ [
+ ["cookies", "test1.example.org"],
+ [
+ getCookieId("c1", "test1.example.org", "/browser"),
+ getCookieId("c2", "test1.example.org", "/browser")
+ ]
+ ],
+ ]);
+ checkCell(c1id, "value", '{"foo": 4,"bar":6}');
+
+ // Add a new entry
+ gWindow.addCookie("c3", "booyeah");
+
+ // Wait once for update and another time for value fetching
+ yield gUI.once("store-objects-updated");
+ yield gUI.once("store-objects-updated");
+
+ yield checkState([
+ [
+ ["cookies", "test1.example.org"],
+ [
+ getCookieId("c1", "test1.example.org", "/browser"),
+ getCookieId("c2", "test1.example.org", "/browser"),
+ getCookieId("c3", "test1.example.org",
+ "/browser/devtools/client/storage/test/")
+ ]
+ ],
+ ]);
+ let c3id = getCookieId("c3", "test1.example.org",
+ "/browser/devtools/client/storage/test/");
+ checkCell(c3id, "value", "booyeah");
+
+ // Add another
+ gWindow.addCookie("c4", "booyeah");
+
+ // Wait once for update and another time for value fetching
+ yield gUI.once("store-objects-updated");
+ yield gUI.once("store-objects-updated");
+
+ yield checkState([
+ [
+ ["cookies", "test1.example.org"],
+ [
+ getCookieId("c1", "test1.example.org", "/browser"),
+ getCookieId("c2", "test1.example.org", "/browser"),
+ getCookieId("c3", "test1.example.org",
+ "/browser/devtools/client/storage/test/"),
+ getCookieId("c4", "test1.example.org",
+ "/browser/devtools/client/storage/test/")
+ ]
+ ],
+ ]);
+ let c4id = getCookieId("c4", "test1.example.org",
+ "/browser/devtools/client/storage/test/");
+ checkCell(c4id, "value", "booyeah");
+
+ // Removing cookies
+ gWindow.removeCookie("c1", "/browser");
+
+ yield gUI.once("sidebar-updated");
+
+ yield checkState([
+ [
+ ["cookies", "test1.example.org"],
+ [
+ getCookieId("c2", "test1.example.org", "/browser"),
+ getCookieId("c3", "test1.example.org",
+ "/browser/devtools/client/storage/test/"),
+ getCookieId("c4", "test1.example.org",
+ "/browser/devtools/client/storage/test/")
+ ]
+ ],
+ ]);
+
+ ok(!gUI.sidebar.hidden, "Sidebar still visible for next row");
+
+ // Check if next element's value is visible in sidebar
+ yield findVariableViewProperties([{name: "c2", value: "foobar"}]);
+
+ // Keep deleting till no rows
+ gWindow.removeCookie("c3");
+
+ yield gUI.once("store-objects-updated");
+
+ yield checkState([
+ [
+ ["cookies", "test1.example.org"],
+ [
+ getCookieId("c2", "test1.example.org", "/browser"),
+ getCookieId("c4", "test1.example.org",
+ "/browser/devtools/client/storage/test/")
+ ]
+ ],
+ ]);
+
+ // Check if next element's value is visible in sidebar
+ yield findVariableViewProperties([{name: "c2", value: "foobar"}]);
+
+ gWindow.removeCookie("c2", "/browser");
+
+ yield gUI.once("sidebar-updated");
+
+ yield checkState([
+ [
+ ["cookies", "test1.example.org"],
+ [
+ getCookieId("c4", "test1.example.org",
+ "/browser/devtools/client/storage/test/")
+ ]
+ ],
+ ]);
+
+ // Check if next element's value is visible in sidebar
+ yield findVariableViewProperties([{name: "c4", value: "booyeah"}]);
+
+ gWindow.removeCookie("c4");
+
+ yield gUI.once("store-objects-updated");
+
+ yield checkState([
+ [["cookies", "test1.example.org"], [ ]],
+ ]);
+
+ ok(gUI.sidebar.hidden, "Sidebar is hidden when no rows");
+
+ yield finishTests();
+});
diff --git a/devtools/client/storage/test/browser_storage_dynamic_updates_localStorage.js b/devtools/client/storage/test/browser_storage_dynamic_updates_localStorage.js
new file mode 100644
index 000000000..35912ce3a
--- /dev/null
+++ b/devtools/client/storage/test/browser_storage_dynamic_updates_localStorage.js
@@ -0,0 +1,70 @@
+/* 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/. */
+
+"use strict";
+
+// Test dynamic updates in the storage inspector for localStorage.
+
+add_task(function* () {
+ yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-updates.html");
+
+ gUI.tree.expandAll();
+
+ ok(gUI.sidebar.hidden, "Sidebar is initially hidden");
+
+ yield checkState([
+ [
+ ["localStorage", "http://test1.example.org"],
+ ["ls1", "ls2", "ls3", "ls4", "ls5", "ls6", "ls7"]
+ ],
+ ]);
+
+ gWindow.localStorage.removeItem("ls4");
+
+ yield gUI.once("store-objects-updated");
+
+ yield checkState([
+ [
+ ["localStorage", "http://test1.example.org"],
+ ["ls1", "ls2", "ls3", "ls5", "ls6", "ls7"]
+ ],
+ ]);
+
+ gWindow.localStorage.setItem("ls4", "again");
+
+ yield gUI.once("store-objects-updated");
+ yield gUI.once("store-objects-updated");
+
+ yield checkState([
+ [
+ ["localStorage", "http://test1.example.org"],
+ ["ls1", "ls2", "ls3", "ls4", "ls5", "ls6", "ls7"]
+ ],
+ ]);
+ // Updating a row
+ gWindow.localStorage.setItem("ls2", "ls2-changed");
+
+ yield gUI.once("store-objects-updated");
+ yield gUI.once("store-objects-updated");
+
+ checkCell("ls2", "value", "ls2-changed");
+
+ // Clearing items. Bug 1233497 makes it so that we can no longer yield
+ // CPOWs from Tasks. We work around this by calling clear via a ContentTask
+ // instead.
+ yield ContentTask.spawn(gBrowser.selectedBrowser, null, function* () {
+ return Task.spawn(content.wrappedJSObject.clear);
+ });
+
+ yield gUI.once("store-objects-cleared");
+
+ yield checkState([
+ [
+ ["localStorage", "http://test1.example.org"],
+ [ ]
+ ],
+ ]);
+
+ yield finishTests();
+});
diff --git a/devtools/client/storage/test/browser_storage_dynamic_updates_sessionStorage.js b/devtools/client/storage/test/browser_storage_dynamic_updates_sessionStorage.js
new file mode 100644
index 000000000..8c2f2537e
--- /dev/null
+++ b/devtools/client/storage/test/browser_storage_dynamic_updates_sessionStorage.js
@@ -0,0 +1,83 @@
+/* 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/. */
+
+"use strict";
+
+// Test dynamic updates in the storage inspector for sessionStorage.
+
+add_task(function* () {
+ yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-updates.html");
+
+ gUI.tree.expandAll();
+
+ ok(gUI.sidebar.hidden, "Sidebar is initially hidden");
+ yield checkState([
+ [
+ ["sessionStorage", "http://test1.example.org"],
+ ["ss1", "ss2", "ss3"]
+ ],
+ ]);
+
+ gWindow.sessionStorage.setItem("ss4", "new-item");
+
+ yield gUI.once("store-objects-updated");
+ yield gUI.once("store-objects-updated");
+
+ yield checkState([
+ [
+ ["sessionStorage", "http://test1.example.org"],
+ ["ss1", "ss2", "ss3", "ss4"]
+ ],
+ ]);
+
+ // deleting item
+
+ gWindow.sessionStorage.removeItem("ss3");
+
+ yield gUI.once("store-objects-updated");
+
+ gWindow.sessionStorage.removeItem("ss1");
+
+ yield gUI.once("store-objects-updated");
+
+ yield checkState([
+ [
+ ["sessionStorage", "http://test1.example.org"],
+ ["ss2", "ss4"]
+ ],
+ ]);
+
+ yield selectTableItem("ss2");
+
+ ok(!gUI.sidebar.hidden, "sidebar is visible");
+
+ // Checking for correct value in sidebar before update
+ yield findVariableViewProperties([{name: "ss2", value: "foobar"}]);
+
+ gWindow.sessionStorage.setItem("ss2", "changed=ss2");
+
+ yield gUI.once("sidebar-updated");
+
+ checkCell("ss2", "value", "changed=ss2");
+
+ yield findVariableViewProperties([{name: "ss2", value: "changed=ss2"}]);
+
+ // Clearing items. Bug 1233497 makes it so that we can no longer yield
+ // CPOWs from Tasks. We work around this by calling clear via a ContentTask
+ // instead.
+ yield ContentTask.spawn(gBrowser.selectedBrowser, null, function* () {
+ return Task.spawn(content.wrappedJSObject.clear);
+ });
+
+ yield gUI.once("store-objects-cleared");
+
+ yield checkState([
+ [
+ ["sessionStorage", "http://test1.example.org"],
+ [ ]
+ ],
+ ]);
+
+ yield finishTests();
+});
diff --git a/devtools/client/storage/test/browser_storage_sidebar.js b/devtools/client/storage/test/browser_storage_sidebar.js
index 9b60026a0..d1a71c667 100644
--- a/devtools/client/storage/test/browser_storage_sidebar.js
+++ b/devtools/client/storage/test/browser_storage_sidebar.js
@@ -20,22 +20,22 @@ const testCases = [
sidebarHidden: true
},
{
- location: "cs2",
+ location: getCookieId("cs2", ".example.org", "/"),
sidebarHidden: false
},
{
sendEscape: true
},
{
- location: "cs2",
+ location: getCookieId("cs2", ".example.org", "/"),
sidebarHidden: false
},
{
- location: "uc1",
+ location: getCookieId("uc1", ".example.org", "/"),
sidebarHidden: false
},
{
- location: "uc1",
+ location: getCookieId("uc1", ".example.org", "/"),
sidebarHidden: false
},
diff --git a/devtools/client/storage/test/browser_storage_values.js b/devtools/client/storage/test/browser_storage_values.js
index 920ce350e..122a867bb 100644
--- a/devtools/client/storage/test/browser_storage_values.js
+++ b/devtools/client/storage/test/browser_storage_values.js
@@ -17,7 +17,7 @@
const LONG_WORD = "a".repeat(1000);
const testCases = [
- ["cs2", [
+ [getCookieId("cs2", ".example.org", "/"), [
{name: "cs2", value: "sessionCookie"},
{name: "cs2.Path", value: "/"},
{name: "cs2.HostOnly", value: "false"},
@@ -26,7 +26,7 @@ const testCases = [
{name: "cs2.Expires", value: "Session"},
{name: "cs2.Secure", value: "false"},
]],
- ["c1", [
+ [getCookieId("c1", "test1.example.org", "/browser"), [
{name: "c1", value: JSON.stringify(["foo", "Bar", {foo: "Bar"}])},
{name: "c1.Path", value: "/browser"},
{name: "c1.HostOnly", value: "true"},
@@ -42,9 +42,13 @@ const testCases = [
{name: "c1.2", value: "Object"},
{name: "c1.2.foo", value: "Bar"},
], true],
- ["c_encoded", [
- {name: "c_encoded", value: encodeURIComponent(JSON.stringify({foo: {foo1: "bar"}}))}
- ]],
+ [
+ getCookieId("c_encoded", "test1.example.org",
+ "/browser/devtools/client/storage/test/"),
+ [
+ {name: "c_encoded", value: encodeURIComponent(JSON.stringify({foo: {foo1: "bar"}}))}
+ ]
+ ],
[null, [
{name: "c_encoded", value: "Object"},
{name: "c_encoded.foo", value: "Object"},
diff --git a/devtools/client/storage/test/head.js b/devtools/client/storage/test/head.js
index 9662393cf..894056c9e 100644
--- a/devtools/client/storage/test/head.js
+++ b/devtools/client/storage/test/head.js
@@ -24,6 +24,11 @@ const MAIN_DOMAIN = "http://test1.example.org/" + PATH;
const ALT_DOMAIN = "http://sectest1.example.org/" + PATH;
const ALT_DOMAIN_SECURED = "https://sectest1.example.org:443/" + PATH;
+// GUID to be used as a separator in compound keys. This must match the same
+// constant in devtools/server/actors/storage.js,
+// devtools/client/storage/ui.js and devtools/server/tests/browser/head.js
+const SEPARATOR_GUID = "{9d414cc5-8319-0a04-0586-c0a6ae01670a}";
+
var gToolbox, gPanelWindow, gWindow, gUI;
// Services.prefs.setBoolPref(DUMPEMIT_PREF, true);
@@ -505,10 +510,16 @@ function* selectTreeItem(ids) {
* The id of the row in the table widget
*/
function* selectTableItem(id) {
- let selector = ".table-widget-cell[data-id='" + id + "']";
+ let table = gUI.table;
+ let selector = ".table-widget-column#" + table.uniqueId +
+ " .table-widget-cell[value='" + id + "']";
let target = gPanelWindow.document.querySelector(selector);
ok(target, "table item found with ids " + id);
+ if (!target) {
+ showAvailableIds();
+ }
+
yield click(target);
yield gUI.once("sidebar-updated");
}
@@ -586,22 +597,39 @@ function getRowCells(id, includeHidden = false) {
if (!item) {
ok(false, "Row id '" + id + "' exists");
+
+ showAvailableIds();
}
- let index = table.columns.get(table.uniqueId).visibleCellNodes.indexOf(item);
+ let index = table.columns.get(table.uniqueId).cellNodes.indexOf(item);
let cells = {};
for (let [name, column] of [...table.columns]) {
if (!includeHidden && column.column.parentNode.hidden) {
continue;
}
- cells[name] = column.visibleCellNodes[index];
+ cells[name] = column.cellNodes[index];
}
return cells;
}
/**
+ * Show available ids.
+ */
+function showAvailableIds() {
+ let doc = gPanelWindow.document;
+ let table = gUI.table;
+
+ info("Available ids:");
+ let cells = doc.querySelectorAll(".table-widget-column#" + table.uniqueId +
+ " .table-widget-cell");
+ for (let cell of cells) {
+ info(" - " + cell.getAttribute("value"));
+ }
+}
+
+/**
* Get a cell value.
*
* @param {String} id
@@ -798,9 +826,18 @@ function* checkState(state) {
is(items.size, names.length,
`There is correct number of rows in ${storeName}`);
+
+ if (names.length === 0) {
+ showAvailableIds();
+ }
+
for (let name of names) {
ok(items.has(name),
`There is item with name '${name}' in ${storeName}`);
+
+ if (!items.has(name)) {
+ showAvailableIds();
+ }
}
}
}
@@ -838,3 +875,7 @@ var focusSearchBoxUsingShortcut = Task.async(function* (panelWin, callback) {
callback();
}
});
+
+function getCookieId(name, domain, path) {
+ return `${name}${SEPARATOR_GUID}${domain}${SEPARATOR_GUID}${path}`;
+}
diff --git a/devtools/client/storage/test/storage-updates.html b/devtools/client/storage/test/storage-updates.html
index a009814b2..341992f61 100644
--- a/devtools/client/storage/test/storage-updates.html
+++ b/devtools/client/storage/test/storage-updates.html
@@ -38,8 +38,10 @@ window.removeCookie = function(name, path) {
* can be tested.
*/
window.clear = function*() {
- sessionStorage.clear();
+ localStorage.clear();
+ dump("removed localStorage from " + document.location + "\n");
+ sessionStorage.clear();
dump("removed sessionStorage from " + document.location + "\n");
};
diff --git a/devtools/client/storage/ui.js b/devtools/client/storage/ui.js
index 6af493e44..c4dd57c6e 100644
--- a/devtools/client/storage/ui.js
+++ b/devtools/client/storage/ui.js
@@ -12,6 +12,12 @@ const {KeyShortcuts} = require("devtools/client/shared/key-shortcuts");
const JSOL = require("devtools/client/shared/vendor/jsol");
const {KeyCodes} = require("devtools/client/shared/keycodes");
+// GUID to be used as a separator in compound keys. This must match the same
+// constant in devtools/server/actors/storage.js,
+// devtools/client/storage/test/head.js and
+// devtools/server/tests/browser/head.js
+const SEPARATOR_GUID = "{9d414cc5-8319-0a04-0586-c0a6ae01670a}";
+
loader.lazyRequireGetter(this, "TreeWidget",
"devtools/client/shared/widgets/TreeWidget", true);
loader.lazyRequireGetter(this, "TableWidget",
@@ -36,13 +42,6 @@ const GENERIC_VARIABLES_VIEW_SETTINGS = {
preventDescriptorModifiers: true
};
-// Columns which are hidden by default in the storage table
-const HIDDEN_COLUMNS = [
- "creationTime",
- "isDomain",
- "isSecure"
-];
-
const REASON = {
NEW_ROW: "new-row",
NEXT_50_ITEMS: "next-50-items",
@@ -786,6 +785,8 @@ StorageUI.prototype = {
let uniqueKey = null;
let columns = {};
let editableFields = [];
+ let hiddenFields = [];
+ let privateFields = [];
let fields = yield this.getCurrentActor().getFields(subtype);
fields.forEach(f => {
@@ -797,6 +798,14 @@ StorageUI.prototype = {
editableFields.push(f.name);
}
+ if (f.hidden) {
+ hiddenFields.push(f.name);
+ }
+
+ if (f.private) {
+ privateFields.push(f.name);
+ }
+
columns[f.name] = f.name;
let columnName;
try {
@@ -812,7 +821,7 @@ StorageUI.prototype = {
}
});
- this.table.setColumns(columns, null, HIDDEN_COLUMNS);
+ this.table.setColumns(columns, null, hiddenFields, privateFields);
this.hideSidebar();
yield this.makeFieldsEditable(editableFields);
@@ -927,10 +936,13 @@ StorageUI.prototype = {
let rowId = this.table.contextMenuRowId;
let data = this.table.items.get(rowId);
- let name = addEllipsis(data[this.table.uniqueId]);
+ let name = data[this.table.uniqueId];
+
+ let separatorRegex = new RegExp(SEPARATOR_GUID, "g");
+ let label = addEllipsis((name + "").replace(separatorRegex, "-"));
this._tablePopupDelete.setAttribute("label",
- L10N.getFormatStr("storage.popupMenu.deleteLabel", name));
+ L10N.getFormatStr("storage.popupMenu.deleteLabel", label));
if (type === "cookies") {
let host = addEllipsis(data.host);