Modified: trunk/Source/WebInspectorUI/UserInterface/Views/CookieStorageContentView.js (237745 => 237746)
--- trunk/Source/WebInspectorUI/UserInterface/Views/CookieStorageContentView.js 2018-11-02 19:03:44 UTC (rev 237745)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/CookieStorageContentView.js 2018-11-02 19:39:01 UTC (rev 237746)
@@ -31,10 +31,12 @@
this.element.classList.add("cookie-storage");
+ this._cookies = [];
+ this._sortComparator = null;
+ this._table = null;
+
this._refreshButtonNavigationItem = new WI.ButtonNavigationItem("cookie-storage-refresh", WI.UIString("Refresh"), "Images/ReloadFull.svg", 13, 13);
this._refreshButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._refreshButtonClicked, this);
-
- this.update();
}
// Public
@@ -44,16 +46,6 @@
return [this._refreshButtonNavigationItem];
}
- update()
- {
- PageAgent.getCookies().then((payload) => {
- this._cookies = this._filterCookies(payload.cookies);
- this._rebuildTable();
- }).catch((error) => {
- console.error("Could not fetch cookies: ", error);
- });
- }
-
saveToCookie(cookie)
{
cookie.type = WI.ContentViewCookieType.CookieStorage;
@@ -62,97 +54,196 @@
get scrollableElements()
{
- if (!this._dataGrid)
+ if (!this._table)
return [];
- return [this._dataGrid.scrollContainer];
+ return [this._table.scrollContainer];
}
- // Private
+ // Table dataSource
- _rebuildTable()
+ tableNumberOfRows(table)
{
- // FIXME <https://webkit.org/b/151400>: If there are no cookies, add placeholder explanatory text.
- if (!this._dataGrid) {
- var columns = {name: {}, value: {}, domain: {}, path: {}, expires: {}, size: {}, http: {}, secure: {}, sameSite: {}};
+ return this._cookies.length;
+ }
- columns.name.title = WI.UIString("Name");
- columns.name.sortable = true;
- columns.name.width = "24%";
- columns.name.locked = true;
+ tableSortChanged(table)
+ {
+ this._generateSortComparator();
- columns.value.title = WI.UIString("Value");
- columns.value.sortable = true;
- columns.value.width = "34%";
- columns.value.locked = true;
+ if (!this._sortComparator)
+ return;
- columns.domain.title = WI.UIString("Domain");
- columns.domain.sortable = true;
- columns.domain.width = "6%";
+ this._updateSort();
+ this._table.reloadData();
+ }
- columns.path.title = WI.UIString("Path");
- columns.path.sortable = true;
- columns.path.width = "6%";
+ // Table delegate
- columns.expires.title = WI.UIString("Expires");
- columns.expires.sortable = true;
- columns.expires.width = "6%";
+ tableCellContextMenuClicked(table, cell, column, rowIndex, event)
+ {
+ let contextMenu = WI.ContextMenu.createFromEvent(event);
- columns.size.title = WI.UIString("Size");
- columns.size.aligned = "right";
- columns.size.sortable = true;
- columns.size.width = "6%";
+ contextMenu.appendSeparator();
+ contextMenu.appendItem(WI.UIString("Delete"), () => {
+ if (table.isRowSelected(rowIndex))
+ table.removeSelectedRows();
+ else
+ table.removeRow(rowIndex);
+ });
+ contextMenu.appendSeparator();
+ }
- columns.http.title = WI.UIString("HTTP");
- columns.http.aligned = "centered";
- columns.http.sortable = true;
- columns.http.width = "6%";
+ tableDidRemoveRows(table, rowIndexes)
+ {
+ if (!rowIndexes.length)
+ return;
- columns.secure.title = WI.UIString("Secure");
- columns.secure.aligned = "centered";
- columns.secure.sortable = true;
- columns.secure.width = "6%";
+ for (let i = rowIndexes.length - 1; i >= 0; --i) {
+ let rowIndex = rowIndexes[i];
+ let cookie = this._cookies[rowIndex];
+ console.assert(cookie, "Missing cookie for row " + rowIndex);
+ if (!cookie)
+ continue;
- columns.sameSite.title = WI.UIString("Same-Site");
- columns.sameSite.sortable = true;
- columns.sameSite.width = "6%";
+ this._cookies.splice(rowIndex, 1);
- this._dataGrid = new WI.DataGrid(columns, null, this._deleteCallback.bind(this));
- this._dataGrid.columnChooserEnabled = true;
- this._dataGrid.addEventListener(WI.DataGrid.Event.SortChanged, this._sortDataGrid, this);
- this._dataGrid.sortColumnIdentifier = "name";
- this._dataGrid.createSettings("cookie-storage-content-view");
+ // FIXME: <https://bugs.webkit.org/b/189533> add a WI.Cookie.url property
+ // once we switch over to using model objects instead of raw payload data.
+ let cookieURL = (cookie.secure ? "https://" : "http://") + cookie.domain + cookie.path;
+ PageAgent.deleteCookie(cookie.name, cookieURL);
+ }
+ }
- this.addSubview(this._dataGrid);
- this._dataGrid.updateLayout();
+ tablePopulateCell(table, cell, column, rowIndex)
+ {
+ let cookie = this._cookies[rowIndex];
+
+ const checkmark = "\u2713";
+
+ switch (column.identifier) {
+ case "name":
+ cell.textContent = cookie.name;
+ break;
+ case "value":
+ cell.textContent = cookie.value;
+ break;
+ case "domain":
+ cell.textContent = cookie.domain || emDash;
+ break;
+ case "path":
+ cell.textContent = cookie.path || emDash;
+ break;
+ case "expires":
+ cell.textContent = cookie.expires ? new Date(cookie.expires).toLocaleString() : WI.UIString("Session");
+ break;
+ case "size":
+ cell.textContent = Number.bytesToString(cookie.size);
+ break;
+ case "secure":
+ cell.textContent = cookie.secure ? checkmark : zeroWidthSpace;
+ break;
+ case "httpOnly":
+ cell.textContent = cookie.httpOnly ? checkmark : zeroWidthSpace;
+ break;
+ case "sameSite":
+ cell.textContent = cookie.sameSite === WI.Cookie.SameSiteType.None ? emDash : WI.Cookie.displayNameForSameSiteType(cookie.sameSite);
+ break;
}
- console.assert(this._dataGrid);
- this._dataGrid.removeChildren();
+ return cell;
+ }
- for (let cookie of this._cookies) {
- const checkmark = "\u2713";
- var data = {
- name: cookie.name,
- value: cookie.value,
- domain: cookie.domain || "",
- path: cookie.path || "",
- expires: "",
- size: Number.bytesToString(cookie.size),
- http: cookie.httpOnly ? checkmark : "",
- secure: cookie.secure ? checkmark : "",
- sameSite: cookie.sameSite && cookie.sameSite !== WI.Cookie.SameSiteType.None ? WI.Cookie.displayNameForSameSiteType(cookie.sameSite) : "",
- };
+ // Protected
- if (cookie.type !== WI.CookieType.Request)
- data["expires"] = cookie.session ? WI.UIString("Session") : new Date(cookie.expires).toLocaleString();
+ initialLayout()
+ {
+ super.initialLayout();
- var node = new WI.DataGridNode(data);
- node.cookie = cookie;
+ this._table = new WI.Table("cookies-table", this, this, 20);
+ this._table.allowsMultipleSelection = true;
- this._dataGrid.appendChild(node);
- }
+ this._nameColumn = new WI.TableColumn("name", WI.UIString("Name"), {
+ minWidth: 70,
+ maxWidth: 300,
+ initialWidth: 200,
+ resizeType: WI.TableColumn.ResizeType.Locked,
+ });
+
+ this._valueColumn = new WI.TableColumn("value", WI.UIString("Value"), {
+ minWidth: 100,
+ maxWidth: 600,
+ initialWidth: 200,
+ hideable: false,
+ });
+
+ this._domainColumn = new WI.TableColumn("domain", WI.unlocalizedString("Domain"), {
+ minWidth: 100,
+ maxWidth: 200,
+ initialWidth: 120,
+ });
+
+ this._pathColumn = new WI.TableColumn("path", WI.unlocalizedString("Path"), {
+ minWidth: 50,
+ maxWidth: 300,
+ initialWidth: 100,
+ });
+
+ this._expiresColumn = new WI.TableColumn("expires", WI.unlocalizedString("Expires"), {
+ minWidth: 100,
+ maxWidth: 200,
+ initialWidth: 150,
+ });
+
+ this._sizeColumn = new WI.TableColumn("size", WI.unlocalizedString("Size"), {
+ minWidth: 50,
+ maxWidth: 80,
+ initialWidth: 65,
+ align: "right",
+ });
+
+ this._secureColumn = new WI.TableColumn("secure", WI.unlocalizedString("Secure"), {
+ minWidth: 70,
+ maxWidth: 70,
+ align: "center",
+ });
+
+ this._httpOnlyColumn = new WI.TableColumn("httpOnly", WI.unlocalizedString("HttpOnly"), {
+ minWidth: 80,
+ maxWidth: 80,
+ align: "center",
+ });
+
+ this._sameSiteColumn = new WI.TableColumn("sameSite", WI.unlocalizedString("SameSite"), {
+ minWidth: 40,
+ maxWidth: 80,
+ initialWidth: 70,
+ align: "center",
+ });
+
+ this._table.addColumn(this._nameColumn);
+ this._table.addColumn(this._valueColumn);
+ this._table.addColumn(this._domainColumn);
+ this._table.addColumn(this._pathColumn);
+ this._table.addColumn(this._expiresColumn);
+ this._table.addColumn(this._sizeColumn);
+ this._table.addColumn(this._secureColumn);
+ this._table.addColumn(this._httpOnlyColumn);
+ this._table.addColumn(this._sameSiteColumn);
+
+ if (!this._table.sortColumnIdentifier) {
+ this._table.sortOrder = WI.Table.SortOrder.Ascending;
+ this._table.sortColumnIdentifier = "name";
+ }
+
+ this.addSubview(this._table);
+
+ this._table.element.addEventListener("keydown", this._handleTableKeyDown.bind(this));
+
+ this._reloadCookies();
}
+ // Private
+
_filterCookies(cookies)
{
let resourceMatchesStorageDomain = (resource) => {
@@ -176,62 +267,78 @@
return cookiesForDomain;
}
- _sortDataGrid()
+ _generateSortComparator()
{
- function localeCompare(field, nodeA, nodeB)
- {
- return (nodeA.data[field] + "").extendedLocaleCompare(nodeB.data[field] + "");
+ let sortColumnIdentifier = this._table.sortColumnIdentifier;
+ if (!sortColumnIdentifier) {
+ this._sortComparator = null;
+ return;
}
- function numberCompare(field, nodeA, nodeB)
- {
- return nodeA.cookie[field] - nodeB.cookie[field];
- }
+ let comparator = null;
- function expiresCompare(nodeA, nodeB)
- {
- if (nodeA.cookie.session !== nodeB.cookie.session)
- return nodeA.cookie.session ? -1 : 1;
+ switch (sortColumnIdentifier) {
+ case "name":
+ case "value":
+ case "domain":
+ case "path":
+ case "sameSite":
+ comparator = (a, b) => (a[sortColumnIdentifier] || "").extendedLocaleCompare(b[sortColumnIdentifier] || "");
+ break;
- if (nodeA.cookie.session)
- return 0;
+ case "size":
+ case "httpOnly":
+ case "secure":
+ comparator = (a, b) => a[sortColumnIdentifier] - b[sortColumnIdentifier];
+ break;
- return nodeA.cookie.expires - nodeB.cookie.expires;
- }
+ case "expires":
+ comparator = (a, b) => {
+ if (!a.expires)
+ return 1;
+ if (!b.expires)
+ return -1;
+ return a.expires - b.expires;
+ };
+ break;
- var comparator;
- switch (this._dataGrid.sortColumnIdentifier) {
- case "value": comparator = localeCompare.bind(this, "value"); break;
- case "domain": comparator = localeCompare.bind(this, "domain"); break;
- case "path": comparator = localeCompare.bind(this, "path"); break;
- case "expires": comparator = expiresCompare; break;
- case "size": comparator = numberCompare.bind(this, "size"); break;
- case "http": comparator = localeCompare.bind(this, "http"); break;
- case "secure": comparator = localeCompare.bind(this, "secure"); break;
- case "sameSite": comparator = localeCompare.bind(this, "sameSite"); break;
- case "name":
- default: comparator = localeCompare.bind(this, "name"); break;
+ default:
+ console.assert("Unexpected sort column", sortColumnIdentifier);
+ return;
}
- console.assert(comparator);
- this._dataGrid.sortNodes(comparator);
+ let reverseFactor = this._table.sortOrder === WI.Table.SortOrder.Ascending ? 1 : -1;
+ this._sortComparator = (a, b) => reverseFactor * comparator(a, b);
}
- _deleteCallback(node)
+ _refreshButtonClicked(event)
{
- if (!node || !node.cookie)
+ this._reloadCookies();
+ }
+
+ _reloadCookies()
+ {
+ PageAgent.getCookies().then((payload) => {
+ this._cookies = this._filterCookies(payload.cookies);
+ this._updateSort();
+ this._table.reloadData();
+ }).catch((error) => {
+ console.error("Could not fetch cookies: ", error);
+ });
+ }
+
+ _updateSort()
+ {
+ if (!this._sortComparator)
return;
- var cookie = node.cookie;
- var cookieURL = (cookie.secure ? "https://" : "http://") + cookie.domain + cookie.path;
- PageAgent.deleteCookie(cookie.name, cookieURL);
-
- this.update();
+ this._cookies.sort(this._sortComparator);
}
- _refreshButtonClicked(event)
+ _handleTableKeyDown(event)
{
- this.update();
+ if (event.keyCode === WI.KeyboardShortcut.Key.Backspace.keyCode || event.keyCode === WI.KeyboardShortcut.Key.Delete.keyCode)
+ this._table.removeSelectedRows();
}
};
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/Table.js (237745 => 237746)
--- trunk/Source/WebInspectorUI/UserInterface/Views/Table.js 2018-11-02 19:03:44 UTC (rev 237745)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/Table.js 2018-11-02 19:39:01 UTC (rev 237746)
@@ -235,6 +235,11 @@
this._notifySelectionDidChange();
}
+ isRowSelected(rowIndex)
+ {
+ return this._selectedRows.has(rowIndex);
+ }
+
resize()
{
this._cachedWidth = NaN;
@@ -321,7 +326,7 @@
console.assert(!extendSelection || this._allowsMultipleSelection, "Cannot extend selection with multiple selection disabled.");
console.assert(rowIndex >= 0 && rowIndex < this.numberOfRows);
- if (this._isRowSelected(rowIndex)) {
+ if (this.isRowSelected(rowIndex)) {
if (!extendSelection)
this._deselectAllAndSelect(rowIndex);
return;
@@ -346,7 +351,7 @@
{
console.assert(rowIndex >= 0 && rowIndex < this.numberOfRows);
- if (!this._isRowSelected(rowIndex))
+ if (!this.isRowSelected(rowIndex))
return;
let oldSelectedRow = this._cachedRows.get(rowIndex);
@@ -390,7 +395,7 @@
{
console.assert(rowIndex >= 0 && rowIndex < this.numberOfRows);
- if (this._isRowSelected(rowIndex))
+ if (this.isRowSelected(rowIndex))
this.deselectRow(rowIndex);
this._removeRows(new WI.IndexSet([rowIndex]));
@@ -797,7 +802,7 @@
let row = document.createElement("li");
row.__index = rowIndex;
row.__widthGeneration = 0;
- if (this._isRowSelected(rowIndex))
+ if (this.isRowSelected(rowIndex))
row.classList.add("selected");
this._cachedRows.set(rowIndex, row);
@@ -1321,7 +1326,7 @@
let column = this._visibleColumns[columnIndex];
let rowIndex = row.__index;
- if (this._isRowSelected(rowIndex)) {
+ if (this.isRowSelected(rowIndex)) {
if (event.metaKey)
this.deselectRow(rowIndex)
else
@@ -1452,7 +1457,7 @@
this._cachedRows.set(newIndex, row);
}
- if (this._isRowSelected(index)) {
+ if (this.isRowSelected(index)) {
this._selectedRows.delete(index);
this._selectedRows.add(newIndex);
if (this._selectedRowIndex === index)
@@ -1493,11 +1498,6 @@
}
}
- _isRowSelected(rowIndex)
- {
- return this._selectedRows.has(rowIndex);
- }
-
_notifySelectionDidChange()
{
if (this._suppressNextSelectionDidChange) {