blob: 6a22561f7c98ea8e5d72fd9b5e85c4cc7fa1e473 [file] [log] [blame]
/*
* Copyright (C) 2008 Nokia Inc. All rights reserved.
* Copyright (C) 2013 Samsung Electronics. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
Resources.DOMStorageItemsView = class extends Resources.StorageItemsView {
/**
* @param {!Resources.DOMStorage} domStorage
*/
constructor(domStorage) {
super(Common.UIString('DOM Storage'), 'domStoragePanel');
this._domStorage = domStorage;
this.element.classList.add('storage-view', 'table');
const columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([
{id: 'key', title: Common.UIString('Key'), sortable: false, editable: true, longText: true, weight: 50},
{id: 'value', title: Common.UIString('Value'), sortable: false, editable: true, longText: true, weight: 50}
]);
this._dataGrid = new DataGrid.DataGrid(
columns, this._editingCallback.bind(this), this._deleteCallback.bind(this), this.refreshItems.bind(this));
this._dataGrid.addEventListener(
DataGrid.DataGrid.Events.SelectedNode,
event => this._previewEntry(/** @type {!DataGrid.DataGridNode} */ (event.data)));
this._dataGrid.addEventListener(DataGrid.DataGrid.Events.DeselectedNode, event => this._previewEntry(null));
this._dataGrid.setStriped(true);
this._dataGrid.setName('DOMStorageItemsView');
this._splitWidget = new UI.SplitWidget(false, false);
this._splitWidget.show(this.element);
this._splitWidget.setSecondIsSidebar(true);
this._previewPanel = new UI.VBox();
const resizer = this._previewPanel.element.createChild('div', 'preview-panel-resizer');
const dataGridWidget = this._dataGrid.asWidget();
dataGridWidget.setMinimumSize(0, 50);
this._splitWidget.setMainWidget(dataGridWidget);
this._splitWidget.setSidebarWidget(this._previewPanel);
this._splitWidget.installResizer(resizer);
/** @type {?UI.Widget} */
this._preview = null;
/** @type {?string} */
this._previewValue = null;
this._showPreview(null, null);
this._eventListeners = [];
this.setStorage(domStorage);
}
/**
* @param {!Resources.DOMStorage} domStorage
*/
setStorage(domStorage) {
Common.EventTarget.removeEventListeners(this._eventListeners);
this._domStorage = domStorage;
this._eventListeners = [
this._domStorage.addEventListener(
Resources.DOMStorage.Events.DOMStorageItemsCleared, this._domStorageItemsCleared, this),
this._domStorage.addEventListener(
Resources.DOMStorage.Events.DOMStorageItemRemoved, this._domStorageItemRemoved, this),
this._domStorage.addEventListener(
Resources.DOMStorage.Events.DOMStorageItemAdded, this._domStorageItemAdded, this),
this._domStorage.addEventListener(
Resources.DOMStorage.Events.DOMStorageItemUpdated, this._domStorageItemUpdated, this),
];
this.refreshItems();
}
_domStorageItemsCleared() {
if (!this.isShowing() || !this._dataGrid) {
return;
}
this._dataGrid.rootNode().removeChildren();
this._dataGrid.addCreationNode(false);
this.setCanDeleteSelected(false);
}
/**
* @param {!Common.Event} event
*/
_domStorageItemRemoved(event) {
if (!this.isShowing() || !this._dataGrid) {
return;
}
const storageData = event.data;
const rootNode = this._dataGrid.rootNode();
const children = rootNode.children;
for (let i = 0; i < children.length; ++i) {
const childNode = children[i];
if (childNode.data.key === storageData.key) {
rootNode.removeChild(childNode);
this.setCanDeleteSelected(children.length > 1);
return;
}
}
}
/**
* @param {!Common.Event} event
*/
_domStorageItemAdded(event) {
if (!this.isShowing() || !this._dataGrid) {
return;
}
const storageData = event.data;
const rootNode = this._dataGrid.rootNode();
const children = rootNode.children;
for (let i = 0; i < children.length; ++i) {
if (children[i].data.key === storageData.key) {
return;
}
}
const childNode = new DataGrid.DataGridNode({key: storageData.key, value: storageData.value}, false);
rootNode.insertChild(childNode, children.length - 1);
}
/**
* @param {!Common.Event} event
*/
_domStorageItemUpdated(event) {
if (!this.isShowing() || !this._dataGrid) {
return;
}
const storageData = event.data;
const childNode = this._dataGrid.rootNode().children.find(child => child.data.key === storageData.key);
if (!childNode || childNode.data.value === storageData.value) {
return;
}
childNode.data.value = storageData.value;
childNode.refresh();
if (!childNode.selected) {
return;
}
this._previewEntry(childNode);
this.setCanDeleteSelected(true);
}
/**
* @param {!Array<!Array<string>>} items
*/
_showDOMStorageItems(items) {
const rootNode = this._dataGrid.rootNode();
let selectedKey = null;
for (const node of rootNode.children) {
if (!node.selected) {
continue;
}
selectedKey = node.data.key;
break;
}
rootNode.removeChildren();
let selectedNode = null;
const filteredItems = item => `${item[0]} ${item[1]}`;
for (const item of this.filter(items, filteredItems)) {
const key = item[0];
const value = item[1];
const node = new DataGrid.DataGridNode({key: key, value: value}, false);
node.selectable = true;
rootNode.appendChild(node);
if (!selectedNode || key === selectedKey) {
selectedNode = node;
}
}
if (selectedNode) {
selectedNode.selected = true;
}
this._dataGrid.addCreationNode(false);
this.setCanDeleteSelected(!!selectedNode);
}
/**
* @override
*/
deleteSelectedItem() {
if (!this._dataGrid || !this._dataGrid.selectedNode) {
return;
}
this._deleteCallback(this._dataGrid.selectedNode);
}
/**
* @override
*/
refreshItems() {
this._domStorage.getItems().then(items => items && this._showDOMStorageItems(items));
}
/**
* @override
*/
deleteAllItems() {
this._domStorage.clear();
// explicitly clear the view because the event won't be fired when it has no items
this._domStorageItemsCleared();
}
_editingCallback(editingNode, columnIdentifier, oldText, newText) {
const domStorage = this._domStorage;
if (columnIdentifier === 'key') {
if (typeof oldText === 'string') {
domStorage.removeItem(oldText);
}
domStorage.setItem(newText, editingNode.data.value || '');
this._removeDupes(editingNode);
} else {
domStorage.setItem(editingNode.data.key || '', newText);
}
}
/**
* @param {!DataGrid.DataGridNode} masterNode
*/
_removeDupes(masterNode) {
const rootNode = this._dataGrid.rootNode();
const children = rootNode.children;
for (let i = children.length - 1; i >= 0; --i) {
const childNode = children[i];
if ((childNode.data.key === masterNode.data.key) && (masterNode !== childNode)) {
rootNode.removeChild(childNode);
}
}
}
_deleteCallback(node) {
if (!node || node.isCreationNode) {
return;
}
if (this._domStorage) {
this._domStorage.removeItem(node.data.key);
}
}
/**
* @param {?UI.Widget} preview
* @param {?string} value
*/
_showPreview(preview, value) {
if (this._preview && this._previewValue === value) {
return;
}
if (this._preview) {
this._preview.detach();
}
if (!preview) {
preview = new UI.EmptyWidget(Common.UIString('Select a value to preview'));
}
this._previewValue = value;
this._preview = preview;
preview.show(this._previewPanel.contentElement);
}
/**
* @param {?DataGrid.DataGridNode} entry
*/
async _previewEntry(entry) {
const value = entry && entry.data && entry.data.value;
if (!value) {
this._showPreview(null, value);
return;
}
const protocol = this._domStorage.isLocalStorage ? 'localstorage' : 'sessionstorage';
const url = `${protocol}://${entry.key}`;
const provider =
Common.StaticContentProvider.fromString(url, Common.resourceTypes.XHR, /** @type {string} */ (value));
const preview = await SourceFrame.PreviewFactory.createPreview(provider, 'text/plain');
// Selection could've changed while the preview was loaded
if (!entry.selected) {
return;
}
this._showPreview(preview, value);
}
};