mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-08-15 08:53:07 +09:00
moebius#339: Make it possible to add cookies, local and session storage entries
Issue #31 https://github.com/MoonchildProductions/moebius/pull/339
This commit is contained in:
parent
e688e88257
commit
6d865bfda3
13 changed files with 309 additions and 43 deletions
|
|
@ -87,7 +87,11 @@ storage.parsedValue.label=Parsed Value
|
|||
# Label of popup menu action to delete storage item.
|
||||
storage.popupMenu.deleteLabel=Delete “%S”
|
||||
|
||||
# LOCALIZATION NOTE (storage.popupMenu.deleteAllLabel):
|
||||
# LOCALIZATION NOTE (storage.popupMenu.addItemLabel):
|
||||
# Label of popup menu action to add an item.
|
||||
storage.popupMenu.addItemLabel=Add Item
|
||||
|
||||
# LOCALIZATION NOTE (storage.popupMenu.deleteAllFromLabel):
|
||||
# Label of popup menu action to delete all storage items.
|
||||
storage.popupMenu.deleteAllFromLabel=Delete All From “%S”
|
||||
|
||||
|
|
|
|||
|
|
@ -123,6 +123,8 @@ function TableWidget(node, options = {}) {
|
|||
TableWidget.prototype = {
|
||||
|
||||
items: null,
|
||||
editBookmark: null,
|
||||
scrollIntoViewOnUpdate: null,
|
||||
|
||||
/**
|
||||
* Getter for the headers context menu popup id.
|
||||
|
|
@ -1159,7 +1161,9 @@ Column.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Called when a row is updated.
|
||||
* Called when a row is updated e.g. a cell is changed. This means that
|
||||
* for a new row this method will be called once for each column. If a single
|
||||
* cell is changed this method will be called just once.
|
||||
*
|
||||
* @param {string} event
|
||||
* The event name of the event. i.e. EVENTS.ROW_UPDATED
|
||||
|
|
@ -1168,7 +1172,23 @@ Column.prototype = {
|
|||
*/
|
||||
onRowUpdated: function (event, id) {
|
||||
this._updateItems();
|
||||
|
||||
if (this.highlightUpdated && this.items[id] != null) {
|
||||
if (this.table.scrollIntoViewOnUpdate) {
|
||||
let cell = this.cells[this.items[id]];
|
||||
|
||||
// When a new row is created this method is called once for each column
|
||||
// as each cell is updated. We can only scroll to cells if they are
|
||||
// visible. We check for visibility and once we find the first visible
|
||||
// cell in a row we scroll it into view and reset the
|
||||
// scrollIntoViewOnUpdate flag.
|
||||
if (cell.label.clientHeight > 0) {
|
||||
cell.scrollIntoView();
|
||||
|
||||
this.table.scrollIntoViewOnUpdate = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.table.editBookmark) {
|
||||
// A rows position in the table can change as the result of an edit. In
|
||||
// order to ensure that the correct row is highlighted after an edit we
|
||||
|
|
@ -1180,6 +1200,7 @@ Column.prototype = {
|
|||
|
||||
this.cells[this.items[id]].flash();
|
||||
}
|
||||
|
||||
this.updateZebra();
|
||||
},
|
||||
|
||||
|
|
@ -1594,6 +1615,10 @@ Cell.prototype = {
|
|||
this.label.focus();
|
||||
},
|
||||
|
||||
scrollIntoView: function () {
|
||||
this.label.scrollIntoView(false);
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
this.label.remove();
|
||||
this.label = null;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
<menuitem id="storage-tree-popup-delete"/>
|
||||
</menupopup>
|
||||
<menupopup id="storage-table-popup">
|
||||
<menuitem id="storage-table-popup-add"/>
|
||||
<menuitem id="storage-table-popup-delete"/>
|
||||
<menuitem id="storage-table-popup-delete-all-from"/>
|
||||
<menuitem id="storage-table-popup-delete-all"
|
||||
|
|
@ -45,6 +46,9 @@
|
|||
<splitter class="devtools-side-splitter"/>
|
||||
<vbox flex="1">
|
||||
<hbox id="storage-toolbar" class="devtools-toolbar">
|
||||
<button id="add-button"
|
||||
class="devtools-button add-button"></button>
|
||||
<spacer flex="1"/>
|
||||
<textbox id="storage-searchbox"
|
||||
class="devtools-filterinput"
|
||||
type="search"
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ support-files =
|
|||
[browser_storage_basic.js]
|
||||
[browser_storage_cache_delete.js]
|
||||
[browser_storage_cache_error.js]
|
||||
[browser_storage_cookies_add.js]
|
||||
[browser_storage_cookies_delete_all.js]
|
||||
[browser_storage_cookies_domain.js]
|
||||
[browser_storage_cookies_edit.js]
|
||||
|
|
@ -38,11 +39,13 @@ support-files =
|
|||
[browser_storage_indexeddb_delete.js]
|
||||
[browser_storage_indexeddb_delete_blocked.js]
|
||||
[browser_storage_indexeddb_duplicate_names.js]
|
||||
[browser_storage_localstorage_add.js]
|
||||
[browser_storage_localstorage_edit.js]
|
||||
[browser_storage_localstorage_error.js]
|
||||
[browser_storage_overflow.js]
|
||||
[browser_storage_search.js]
|
||||
[browser_storage_search_keyboard_trap.js]
|
||||
[browser_storage_sessionstorage_add.js]
|
||||
[browser_storage_sessionstorage_edit.js]
|
||||
[browser_storage_sidebar.js]
|
||||
[browser_storage_sidebar_update.js]
|
||||
|
|
|
|||
20
devtools/client/storage/test/browser_storage_cookies_add.js
Normal file
20
devtools/client/storage/test/browser_storage_cookies_add.js
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* 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/. */
|
||||
|
||||
// Basic test to check the adding of cookies.
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(function* () {
|
||||
yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-cookies.html");
|
||||
showAllColumns(true);
|
||||
|
||||
yield performAdd(["cookies", "http://test1.example.org"]);
|
||||
yield performAdd(["cookies", "http://test1.example.org"]);
|
||||
yield performAdd(["cookies", "http://test1.example.org"]);
|
||||
yield performAdd(["cookies", "http://test1.example.org"]);
|
||||
yield performAdd(["cookies", "http://test1.example.org"]);
|
||||
|
||||
yield finishTests();
|
||||
});
|
||||
|
|
@ -18,8 +18,8 @@ add_task(function* () {
|
|||
|
||||
info("do the delete");
|
||||
yield selectTreeItem(["indexedDB", "http://test1.example.org"]);
|
||||
let actor = gUI.getCurrentActor();
|
||||
let result = yield actor.removeDatabase("http://test1.example.org", "idb (default)");
|
||||
let front = gUI.getCurrentFront();
|
||||
let result = yield front.removeDatabase("http://test1.example.org", "idb (default)");
|
||||
|
||||
ok(result.blocked, "removeDatabase attempt is blocked");
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ add_task(function* () {
|
|||
info("try to delete database from nonexistent host");
|
||||
let errorThrown = false;
|
||||
try {
|
||||
result = yield actor.removeDatabase("http://test2.example.org", "idb (default)");
|
||||
result = yield front.removeDatabase("http://test2.example.org", "idb (default)");
|
||||
} catch (ex) {
|
||||
errorThrown = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
/* 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/. */
|
||||
|
||||
// Basic test to check the adding of localStorage entries.
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(function* () {
|
||||
yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-localstorage.html");
|
||||
showAllColumns(true);
|
||||
|
||||
yield performAdd(["localStorage", "http://test1.example.org"]);
|
||||
yield performAdd(["localStorage", "http://test1.example.org"]);
|
||||
yield performAdd(["localStorage", "http://test1.example.org"]);
|
||||
yield performAdd(["localStorage", "http://test1.example.org"]);
|
||||
yield performAdd(["localStorage", "http://test1.example.org"]);
|
||||
|
||||
yield finishTests();
|
||||
});
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
/* 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/. */
|
||||
|
||||
// Basic test to check the adding of sessionStorage entries.
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(function* () {
|
||||
yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-sessionstorage.html");
|
||||
showAllColumns(true);
|
||||
|
||||
yield performAdd(["sessionStorage", "http://test1.example.org"]);
|
||||
yield performAdd(["sessionStorage", "http://test1.example.org"]);
|
||||
yield performAdd(["sessionStorage", "http://test1.example.org"]);
|
||||
yield performAdd(["sessionStorage", "http://test1.example.org"]);
|
||||
yield performAdd(["sessionStorage", "http://test1.example.org"]);
|
||||
|
||||
yield finishTests();
|
||||
});
|
||||
|
|
@ -897,3 +897,39 @@ function setPermission(url, permission) {
|
|||
.addFromPrincipal(principal, permission,
|
||||
nsIPermissionManager.ALLOW_ACTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an item.
|
||||
* @param {Array} store
|
||||
* An array containing the path to the store to which we wish to add an
|
||||
* item.
|
||||
*/
|
||||
function* performAdd(store) {
|
||||
let storeName = store.join(" > ");
|
||||
let toolbar = gPanelWindow.document.getElementById("storage-toolbar");
|
||||
let type = store[0];
|
||||
|
||||
yield selectTreeItem(store);
|
||||
|
||||
let menuAdd = toolbar.querySelector(
|
||||
"#add-button");
|
||||
|
||||
if (menuAdd.hidden) {
|
||||
is(menuAdd.hidden, false,
|
||||
`performAdd called for ${storeName} but it is not supported`);
|
||||
return;
|
||||
}
|
||||
|
||||
let eventEdit = gUI.table.once("row-edit");
|
||||
let eventWait = gUI.once("store-objects-updated");
|
||||
|
||||
menuAdd.click();
|
||||
|
||||
let rowId = yield eventEdit;
|
||||
yield eventWait;
|
||||
|
||||
let key = type === "cookies" ? "uniqueKey" : "name";
|
||||
let value = getCellValue(rowId, key);
|
||||
|
||||
is(rowId, value, `Row '${rowId}' was successfully added.`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,12 +160,20 @@ function StorageUI(front, target, panelWin, toolbox) {
|
|||
this._tablePopup = this._panelDoc.getElementById("storage-table-popup");
|
||||
this._tablePopup.addEventListener("popupshowing", this.onTablePopupShowing);
|
||||
|
||||
this.onAddItem = this.onAddItem.bind(this);
|
||||
this.onRemoveItem = this.onRemoveItem.bind(this);
|
||||
this.onRemoveAllFrom = this.onRemoveAllFrom.bind(this);
|
||||
this.onRemoveAll = this.onRemoveAll.bind(this);
|
||||
this.onRemoveAllSessionCookies = this.onRemoveAllSessionCookies.bind(this);
|
||||
this.onRemoveTreeItem = this.onRemoveTreeItem.bind(this);
|
||||
|
||||
this._addButton = this._panelDoc.getElementById("add-button");
|
||||
this._addButton.addEventListener("command", this.onAddItem);
|
||||
|
||||
this._tablePopupAddItem = this._panelDoc.getElementById(
|
||||
"storage-table-popup-add");
|
||||
this._tablePopupAddItem.addEventListener("command", this.onAddItem);
|
||||
|
||||
this._tablePopupDelete = this._panelDoc.getElementById(
|
||||
"storage-table-popup-delete");
|
||||
this._tablePopupDelete.addEventListener("command", this.onRemoveItem);
|
||||
|
|
@ -221,6 +229,8 @@ StorageUI.prototype = {
|
|||
this.searchBox = null;
|
||||
|
||||
this._treePopup.removeEventListener("popupshowing", this.onTreePopupShowing);
|
||||
this._addButton.removeEventListener("command", this.onAddItem);
|
||||
this._tablePopupAddItem.removeEventListener("command", this.onAddItem);
|
||||
this._treePopupDeleteAll.removeEventListener("command", this.onRemoveAll);
|
||||
this._treePopupDeleteAllSessionCookies.removeEventListener("command",
|
||||
this.onRemoveAllSessionCookies);
|
||||
|
|
@ -243,7 +253,7 @@ StorageUI.prototype = {
|
|||
this.table.clearSelection();
|
||||
},
|
||||
|
||||
getCurrentActor: function () {
|
||||
getCurrentFront: function () {
|
||||
let type = this.table.datatype;
|
||||
|
||||
return this.storageTypes[type];
|
||||
|
|
@ -264,9 +274,9 @@ StorageUI.prototype = {
|
|||
},
|
||||
|
||||
editItem: function (eventType, data) {
|
||||
let actor = this.getCurrentActor();
|
||||
let front = this.getCurrentFront();
|
||||
|
||||
actor.editItem(data);
|
||||
front.editItem(data);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -520,7 +530,7 @@ StorageUI.prototype = {
|
|||
// The indexedDB type could have sub-type data to fetch.
|
||||
// If having names specified, then it means
|
||||
// we are fetching details of specific database or of object store.
|
||||
if (type == "indexedDB" && names) {
|
||||
if (type === "indexedDB" && names) {
|
||||
let [ dbName, objectStoreName ] = JSON.parse(names[0]);
|
||||
if (dbName) {
|
||||
subType = "database";
|
||||
|
|
@ -529,6 +539,15 @@ StorageUI.prototype = {
|
|||
subType = "object store";
|
||||
}
|
||||
}
|
||||
|
||||
this.actorSupportsAddItem = yield this._target.actorHasMethod(type, "addItem");
|
||||
this.actorSupportsRemoveItem =
|
||||
yield this._target.actorHasMethod(type, "removeItem");
|
||||
this.actorSupportsRemoveAll =
|
||||
yield this._target.actorHasMethod(type, "removeAll");
|
||||
this.actorSupportsRemoveAllSessionCookies =
|
||||
yield this._target.actorHasMethod(type, "removeAllSessionCookies");
|
||||
|
||||
yield this.resetColumns(type, host, subType);
|
||||
}
|
||||
|
||||
|
|
@ -536,12 +555,34 @@ StorageUI.prototype = {
|
|||
if (data.length) {
|
||||
this.populateTable(data, reason);
|
||||
}
|
||||
yield this.updateToolbar();
|
||||
this.emit("store-objects-updated");
|
||||
} catch (ex) {
|
||||
console.error(ex);
|
||||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
* Updates the toolbar hiding and showing buttons as appropriate.
|
||||
*/
|
||||
updateToolbar: Task.async(function* () {
|
||||
let item = this.tree.selectedItem;
|
||||
let howManyNodesIn = item ? item.length : 0;
|
||||
|
||||
// The first node is just a title e.g. "Cookies" so we need to be at least
|
||||
// 2 nodes in to show the add button.
|
||||
let canAdd = this.actorSupportsAddItem && howManyNodesIn > 1;
|
||||
|
||||
if (canAdd) {
|
||||
this._addButton.hidden = false;
|
||||
this._addButton.setAttribute("tooltiptext",
|
||||
L10N.getFormatStr("storage.popupMenu.addItemLabel"));
|
||||
} else {
|
||||
this._addButton.hidden = true;
|
||||
this._addButton.removeAttribute("tooltiptext");
|
||||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
* Populates the storage tree which displays the list of storages present for
|
||||
* the page.
|
||||
|
|
@ -777,11 +818,19 @@ StorageUI.prototype = {
|
|||
* the storage tree
|
||||
*/
|
||||
onHostSelect: function (event, item) {
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
this.table.clear();
|
||||
this.hideSidebar();
|
||||
this.searchBox.value = "";
|
||||
|
||||
let [type, host] = item;
|
||||
this.table.host = host;
|
||||
this.table.datatype = type;
|
||||
|
||||
this.updateToolbar();
|
||||
|
||||
let names = null;
|
||||
if (!host) {
|
||||
return;
|
||||
|
|
@ -814,7 +863,7 @@ StorageUI.prototype = {
|
|||
let editableFields = [];
|
||||
let hiddenFields = [];
|
||||
let privateFields = [];
|
||||
let fields = yield this.getCurrentActor().getFields(subtype);
|
||||
let fields = yield this.getCurrentFront().getFields(subtype);
|
||||
|
||||
fields.forEach(f => {
|
||||
if (!uniqueKey) {
|
||||
|
|
@ -949,33 +998,47 @@ StorageUI.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Fires before a cell context menu with the "Delete" action is shown.
|
||||
* If the currently selected storage object doesn't support removing items, prevent
|
||||
* showing the menu.
|
||||
* Fires before a cell context menu with the "Add" or "Delete" action is
|
||||
* shown. If the currently selected storage object doesn't support adding or
|
||||
* removing items, prevent showing the menu.
|
||||
*/
|
||||
onTablePopupShowing: function (event) {
|
||||
let selectedItem = this.tree.selectedItem;
|
||||
let type = selectedItem[0];
|
||||
let actor = this.getCurrentActor();
|
||||
|
||||
// IndexedDB only supports removing items from object stores (level 4 of the tree)
|
||||
if (!actor.removeItem || (type === "indexedDB" && selectedItem.length !== 4)) {
|
||||
if ((!this.actorSupportsAddItem && !this.actorSupportsRemoveItem &&
|
||||
type !== "cookies") ||
|
||||
(type === "indexedDB" && selectedItem.length !== 4)) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
let rowId = this.table.contextMenuRowId;
|
||||
let data = this.table.items.get(rowId);
|
||||
let name = data[this.table.uniqueId];
|
||||
|
||||
let separatorRegex = new RegExp(SEPARATOR_GUID, "g");
|
||||
let label = addEllipsis((name + "").replace(separatorRegex, "-"));
|
||||
if (this.actorSupportsRemoveItem) {
|
||||
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", label));
|
||||
this._tablePopupDelete.hidden = false;
|
||||
this._tablePopupDelete.setAttribute("label",
|
||||
L10N.getFormatStr("storage.popupMenu.deleteLabel", label));
|
||||
} else {
|
||||
this._tablePopupDelete.hidden = true;
|
||||
}
|
||||
|
||||
if (this.actorSupportsAddItem) {
|
||||
this._tablePopupAddItem.hidden = false;
|
||||
this._tablePopupAddItem.setAttribute("label",
|
||||
L10N.getFormatStr("storage.popupMenu.addItemLabel"));
|
||||
} else {
|
||||
this._tablePopupAddItem.hidden = true;
|
||||
}
|
||||
|
||||
let showDeleteAllSessionCookies = false;
|
||||
if (selectedItem && actor.removeAllSessionCookies) {
|
||||
if (this.actorSupportsRemoveAllSessionCookies) {
|
||||
if (type === "cookies" && selectedItem.length === 2) {
|
||||
showDeleteAllSessionCookies = true;
|
||||
}
|
||||
|
|
@ -1000,13 +1063,12 @@ StorageUI.prototype = {
|
|||
|
||||
if (selectedItem) {
|
||||
let type = selectedItem[0];
|
||||
let actor = this.storageTypes[type];
|
||||
|
||||
// The delete all (aka clear) action is displayed for IndexedDB object stores
|
||||
// (level 4 of tree), for Cache objects (level 3) and for the whole host (level 2)
|
||||
// for other storage types (cookies, localStorage, ...).
|
||||
let showDeleteAll = false;
|
||||
if (actor.removeAll) {
|
||||
if (this.actorSupportsRemoveAll) {
|
||||
let level;
|
||||
if (type == "indexedDB") {
|
||||
level = 4;
|
||||
|
|
@ -1026,7 +1088,7 @@ StorageUI.prototype = {
|
|||
// The delete all session cookies action is displayed for cookie object stores
|
||||
// (level 2 of tree)
|
||||
let showDeleteAllSessionCookies = false;
|
||||
if (actor.removeAllSessionCookies) {
|
||||
if (this.actorSupportsRemoveAllSessionCookies) {
|
||||
if (type === "cookies" && selectedItem.length === 2) {
|
||||
showDeleteAllSessionCookies = true;
|
||||
}
|
||||
|
|
@ -1054,45 +1116,55 @@ StorageUI.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles adding an item from the storage
|
||||
*/
|
||||
onAddItem: function () {
|
||||
if (!this.tree.selectedItem) {
|
||||
return;
|
||||
}
|
||||
let front = this.getCurrentFront();
|
||||
let [, host] = this.tree.selectedItem;
|
||||
|
||||
// Prepare to scroll into view.
|
||||
this.table.scrollIntoViewOnUpdate = true;
|
||||
this.table.editBookmark = createGUID();
|
||||
front.addItem(this.table.editBookmark, host);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles removing an item from the storage
|
||||
*/
|
||||
onRemoveItem: function () {
|
||||
let [, host, ...path] = this.tree.selectedItem;
|
||||
let actor = this.getCurrentActor();
|
||||
let front = this.getCurrentFront();
|
||||
let rowId = this.table.contextMenuRowId;
|
||||
let data = this.table.items.get(rowId);
|
||||
let name = data[this.table.uniqueId];
|
||||
if (path.length > 0) {
|
||||
name = JSON.stringify([...path, name]);
|
||||
}
|
||||
actor.removeItem(host, name);
|
||||
front.removeItem(host, name);
|
||||
},
|
||||
|
||||
/**
|
||||
* 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 the correct value only after the
|
||||
// table data from server are successfully fetched (and that's async).
|
||||
let [type, host, ...path] = this.tree.selectedItem;
|
||||
let actor = this.storageTypes[type];
|
||||
let [, host, ...path] = this.tree.selectedItem;
|
||||
let front = this.getCurrentFront();
|
||||
let name = path.length > 0 ? JSON.stringify(path) : undefined;
|
||||
actor.removeAll(host, name);
|
||||
front.removeAll(host, name);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles removing all session cookies from the storage
|
||||
*/
|
||||
onRemoveAllSessionCookies: function () {
|
||||
// Cannot use this.currentActor() if the handler is called from the
|
||||
// tree context menu: it returns the correct value only after the
|
||||
// table data from server is successfully fetched (and that's async).
|
||||
let [, host, ...path] = this.tree.selectedItem;
|
||||
let actor = this.getCurrentActor();
|
||||
let front = this.getCurrentFront();
|
||||
let name = path.length > 0 ? JSON.stringify(path) : undefined;
|
||||
actor.removeAllSessionCookies(host, name);
|
||||
front.removeAllSessionCookies(host, name);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -1101,11 +1173,11 @@ StorageUI.prototype = {
|
|||
*/
|
||||
onRemoveAllFrom: function () {
|
||||
let [, host] = this.tree.selectedItem;
|
||||
let actor = this.getCurrentActor();
|
||||
let front = this.getCurrentFront();
|
||||
let rowId = this.table.contextMenuRowId;
|
||||
let data = this.table.items.get(rowId);
|
||||
|
||||
actor.removeAll(host, data.host);
|
||||
front.removeAll(host, data.host);
|
||||
},
|
||||
|
||||
onRemoveTreeItem: function () {
|
||||
|
|
@ -1119,9 +1191,9 @@ StorageUI.prototype = {
|
|||
},
|
||||
|
||||
removeDatabase: function (host, dbName) {
|
||||
let actor = this.storageTypes.indexedDB;
|
||||
let front = this.getCurrentFront();
|
||||
|
||||
actor.removeDatabase(host, dbName).then(result => {
|
||||
front.removeDatabase(host, dbName).then(result => {
|
||||
if (result.blocked) {
|
||||
let notificationBox = this._toolbox.getNotificationBox();
|
||||
notificationBox.appendNotification(
|
||||
|
|
@ -1141,8 +1213,17 @@ StorageUI.prototype = {
|
|||
},
|
||||
|
||||
removeCache: function (host, cacheName) {
|
||||
let actor = this.storageTypes.Cache;
|
||||
let front = this.getCurrentFront();
|
||||
|
||||
actor.removeItem(host, JSON.stringify([ cacheName ]));
|
||||
front.removeItem(host, JSON.stringify([ cacheName ]));
|
||||
},
|
||||
};
|
||||
|
||||
// Helper Functions
|
||||
|
||||
function createGUID() {
|
||||
return "{cccccccc-cccc-4ccc-yccc-cccccccccccc}".replace(/[cy]/g, c => {
|
||||
let r = Math.random() * 16 | 0, v = c == "c" ? r : (r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,20 @@
|
|||
min-width: 250px;
|
||||
}
|
||||
|
||||
#storage-toolbar .add-button::before {
|
||||
margin: 0;
|
||||
background-image: url("chrome://devtools/skin/images/add.svg");
|
||||
-moz-user-focus: normal;
|
||||
}
|
||||
|
||||
#storage-toolbar .devtools-button {
|
||||
min-width: unset;
|
||||
}
|
||||
|
||||
#storage-toolbar .devtools-button hbox {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Responsive sidebar */
|
||||
@media (max-width: 700px) {
|
||||
#storage-tree,
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ const {isWindowIncluded} = require("devtools/shared/layout/utils");
|
|||
const specs = require("devtools/shared/specs/storage");
|
||||
const { Task } = require("devtools/shared/task");
|
||||
|
||||
const DEFAULT_VALUE = "value";
|
||||
|
||||
// GUID to be used as a separator in compound keys. This must match the same
|
||||
// constant in devtools/client/storage/ui.js,
|
||||
// devtools/client/storage/test/head.js and
|
||||
|
|
@ -616,6 +618,14 @@ StorageActors.createActor({
|
|||
this.editCookie(data);
|
||||
}),
|
||||
|
||||
addItem: Task.async(function* (guid) {
|
||||
let doc = this.storageActor.document;
|
||||
let time = new Date().getTime();
|
||||
let expiry = new Date(time + 3600 * 24 * 1000).toGMTString();
|
||||
|
||||
doc.cookie = `${guid}=${DEFAULT_VALUE};expires=${expiry}`;
|
||||
}),
|
||||
|
||||
removeItem: Task.async(function* (host, name) {
|
||||
let doc = this.storageActor.document;
|
||||
this.removeCookie(host, name, doc.nodePrincipal
|
||||
|
|
@ -954,6 +964,12 @@ var cookieHelpers = {
|
|||
let rowdata = msg.data.args[0];
|
||||
return cookieHelpers.editCookie(rowdata);
|
||||
}
|
||||
case "createNewCookie": {
|
||||
let host = msg.data.args[0];
|
||||
let guid = msg.data.args[1];
|
||||
let originAttributes = msg.data.args[2];
|
||||
return cookieHelpers.createNewCookie(host, guid, originAttributes);
|
||||
}
|
||||
case "removeCookie": {
|
||||
let host = msg.data.args[0];
|
||||
let name = msg.data.args[1];
|
||||
|
|
@ -1094,6 +1110,14 @@ function getObjectForLocalOrSessionStorage(type) {
|
|||
];
|
||||
}),
|
||||
|
||||
addItem: Task.async(function* (guid, host) {
|
||||
let storage = this.hostVsStores.get(host);
|
||||
if (!storage) {
|
||||
return;
|
||||
}
|
||||
storage.setItem(guid, DEFAULT_VALUE);
|
||||
}),
|
||||
|
||||
/**
|
||||
* Edit localStorage or sessionStorage fields.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -90,6 +90,13 @@ createStorageSpec({
|
|||
methods: Object.assign({},
|
||||
editRemoveMethods,
|
||||
{
|
||||
addItem: {
|
||||
request: {
|
||||
guid: Arg(0, "string"),
|
||||
},
|
||||
response: {}
|
||||
}
|
||||
}, {
|
||||
removeAll: {
|
||||
request: {
|
||||
host: Arg(0, "string"),
|
||||
|
|
@ -119,6 +126,14 @@ types.addDictType("storageobject", {
|
|||
const storageMethods = Object.assign({},
|
||||
editRemoveMethods,
|
||||
{
|
||||
addItem: {
|
||||
request: {
|
||||
guid: Arg(0, "string"),
|
||||
host: Arg(1, "nullable:string")
|
||||
},
|
||||
response: {}
|
||||
}
|
||||
}, {
|
||||
removeAll: {
|
||||
request: {
|
||||
host: Arg(0, "string")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue