diff options
author | Ben Murdoch <benm@google.com> | 2009-08-18 15:36:45 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2009-08-18 19:20:06 +0100 |
commit | d227fc870c7a697500a3c900c31baf05fb9a8524 (patch) | |
tree | a3fa109aa5bf52fef562ac49d97a2f723889cc71 /WebCore/inspector/front-end | |
parent | f2c627513266faa73f7669058d98c60769fb3524 (diff) | |
download | external_webkit-d227fc870c7a697500a3c900c31baf05fb9a8524.zip external_webkit-d227fc870c7a697500a3c900c31baf05fb9a8524.tar.gz external_webkit-d227fc870c7a697500a3c900c31baf05fb9a8524.tar.bz2 |
Merge WebKit r47420
Diffstat (limited to 'WebCore/inspector/front-end')
28 files changed, 1477 insertions, 896 deletions
diff --git a/WebCore/inspector/front-end/ConsoleView.js b/WebCore/inspector/front-end/ConsoleView.js index 6851eea..d4693b7 100644 --- a/WebCore/inspector/front-end/ConsoleView.js +++ b/WebCore/inspector/front-end/ConsoleView.js @@ -175,7 +175,7 @@ WebInspector.ConsoleView.prototype = { clearMessages: function(clearInspectorController) { if (clearInspectorController) - InspectorController.clearMessages(); + InspectorController.clearMessages(false); if (WebInspector.panels.resources) WebInspector.panels.resources.clearMessages(); @@ -212,10 +212,42 @@ WebInspector.ConsoleView.prototype = { return; var reportCompletions = this._reportCompletions.bind(this, bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix); - this._evalInInspectedWindow(expressionString, reportCompletions); + // Collect comma separated object properties for the completion. + + if (!expressionString) { + if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused) { + // Evaluate into properties in scope of the selected call frame. + reportCompletions(WebInspector.panels.scripts.variablesInSelectedCallFrame()); + return; + } else { + expressionString = "this"; + } + } + + function parsingCallback(result, isException) + { + if (!isException) + result = JSON.parse(result); + reportCompletions(result, isException); + } + + this._evalInInspectedWindow( + "(function() {" + + "var props = {};" + + "for (var prop in (" + expressionString + ")) props[prop] = true;" + + ((!dotNotation && !bracketNotation) ? + "for (var prop in window._inspectorCommandLineAPI)" + + "if (prop.charAt(0) !== '_') props[prop] = true;" + : "") + + "return JSON.stringify(props);" + + "})()", + parsingCallback); }, - _reportCompletions: function(bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix, result) { + _reportCompletions: function(bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix, result, isException) { + if (isException) + return; + if (bracketNotation) { if (prefix.length && prefix[0] === "'") var quoteUsed = "'"; @@ -224,16 +256,7 @@ WebInspector.ConsoleView.prototype = { } var results = []; - var properties = Object.properties(result); - if (!dotNotation && !bracketNotation && result._inspectorCommandLineAPI) { - var commandLineAPI = Object.properties(result._inspectorCommandLineAPI); - for (var i = 0; i < commandLineAPI.length; ++i) { - var property = commandLineAPI[i]; - if (property.charAt(0) !== "_") - properties.push(property); - } - } - properties.sort(); + var properties = Object.sortedProperties(result); for (var i = 0; i < properties.length; ++i) { var property = properties[i]; @@ -288,7 +311,7 @@ WebInspector.ConsoleView.prototype = { if (!link || !link.representedNode) return; - WebInspector.updateFocusedNode(link.representedNode); + WebInspector.updateFocusedNode(link.representedNode.id); event.stopPropagation(); event.preventDefault(); }, @@ -313,74 +336,6 @@ WebInspector.ConsoleView.prototype = { this.doEvalInWindow(expression, callback); }, - _ensureCommandLineAPIInstalled: function(inspectedWindow) - { - if (!inspectedWindow._inspectorCommandLineAPI) { - inspectedWindow.eval("window._inspectorCommandLineAPI = { \ - $: function() { return document.getElementById.apply(document, arguments) }, \ - $$: function() { return document.querySelectorAll.apply(document, arguments) }, \ - $x: function(xpath, context) { \ - var nodes = []; \ - try { \ - var doc = context || document; \ - var results = doc.evaluate(xpath, doc, null, XPathResult.ANY_TYPE, null); \ - var node; \ - while (node = results.iterateNext()) nodes.push(node); \ - } catch (e) {} \ - return nodes; \ - }, \ - dir: function() { return console.dir.apply(console, arguments) }, \ - dirxml: function() { return console.dirxml.apply(console, arguments) }, \ - keys: function(o) { var a = []; for (var k in o) a.push(k); return a; }, \ - values: function(o) { var a = []; for (var k in o) a.push(o[k]); return a; }, \ - profile: function() { return console.profile.apply(console, arguments) }, \ - profileEnd: function() { return console.profileEnd.apply(console, arguments) }, \ - _inspectedNodes: [], \ - get $0() { return _inspectorCommandLineAPI._inspectedNodes[0] }, \ - get $1() { return _inspectorCommandLineAPI._inspectedNodes[1] }, \ - get $2() { return _inspectorCommandLineAPI._inspectedNodes[2] }, \ - get $3() { return _inspectorCommandLineAPI._inspectedNodes[3] }, \ - get $4() { return _inspectorCommandLineAPI._inspectedNodes[4] } \ - };"); - - inspectedWindow._inspectorCommandLineAPI.clear = InspectorController.wrapCallback(this.clearMessages.bind(this)); - inspectedWindow._inspectorCommandLineAPI.inspect = InspectorController.wrapCallback(inspectObject.bind(this)); - - function inspectObject(o) - { - if (arguments.length === 0) - return; - - InspectorController.inspectedWindow().console.log(o); - if (Object.type(o, InspectorController.inspectedWindow()) === "node") { - WebInspector.showElementsPanel(); - WebInspector.panels.elements.treeOutline.revealAndSelectNode(o); - } else { - switch (Object.describe(o)) { - case "Database": - WebInspector.showDatabasesPanel(); - WebInspector.panels.databases.selectDatabase(o); - break; - case "Storage": - WebInspector.showDatabasesPanel(); - WebInspector.panels.databases.selectDOMStorage(o); - break; - } - } - } - } - }, - - addInspectedNode: function(node) - { - var inspectedWindow = InspectorController.inspectedWindow(); - this._ensureCommandLineAPIInstalled(inspectedWindow); - var inspectedNodes = inspectedWindow._inspectorCommandLineAPI._inspectedNodes; - inspectedNodes.unshift(node); - if (inspectedNodes.length >= 5) - inspectedNodes.pop(); - }, - doEvalInWindow: function(expression, callback) { if (!expression) { @@ -388,22 +343,15 @@ WebInspector.ConsoleView.prototype = { expression = "this"; } - // Surround the expression in with statements to inject our command line API so that - // the window object properties still take more precedent than our API functions. - expression = "with (window._inspectorCommandLineAPI) { with (window) { " + expression + " } }"; - var self = this; - function delayedEvaluation() + function evalCallback(result) { - var inspectedWindow = InspectorController.inspectedWindow(); - self._ensureCommandLineAPIInstalled(inspectedWindow); - try { - callback(inspectedWindow.eval(expression)); - } catch (e) { - callback(e, true); - } - } - setTimeout(delayedEvaluation, 0); + if (result.exception) + callback(result.exception, true); + else + callback(result.value, false); + }; + InspectorController.evaluate(expression, evalCallback); }, _enterKeyPressed: function(event) @@ -436,13 +384,10 @@ WebInspector.ConsoleView.prototype = { _format: function(output, forceObjectFormat) { - var inspectedWindow = InspectorController.inspectedWindow(); if (forceObjectFormat) var type = "object"; - else if (output instanceof inspectedWindow.NodeList) - var type = "array"; else - var type = Object.type(output, inspectedWindow); + var type = Object.proxyType(output); // We don't perform any special formatting on these types, so we just // pass them through the simple _formatvalue function. @@ -451,8 +396,6 @@ WebInspector.ConsoleView.prototype = { "null": 1, "boolean": 1, "number": 1, - "date": 1, - "function": 1, }; var formatter; @@ -479,6 +422,16 @@ WebInspector.ConsoleView.prototype = { elem.appendChild(document.createTextNode(val)); }, + _formatfunction: function(func, elem) + { + elem.appendChild(document.createTextNode(func.description)); + }, + + _formatdate: function(date, elem) + { + elem.appendChild(document.createTextNode(date.description)); + }, + _formatstring: function(str, elem) { elem.appendChild(document.createTextNode("\"" + str + "\"")); @@ -486,7 +439,7 @@ WebInspector.ConsoleView.prototype = { _formatregexp: function(re, elem) { - var formatted = String(re).replace(/([\\\/])/g, "\\$1").replace(/\\(\/[gim]*)$/, "$1").substring(1); + var formatted = String(re.description).replace(/([\\\/])/g, "\\$1").replace(/\\(\/[gim]*)$/, "$1").substring(1); elem.appendChild(document.createTextNode(formatted)); }, @@ -501,10 +454,10 @@ WebInspector.ConsoleView.prototype = { elem.appendChild(document.createTextNode("]")); }, - _formatnode: function(node, elem) + _formatnode: function(object, elem) { var treeOutline = new WebInspector.ElementsTreeOutline(); - treeOutline.rootDOMNode = node; + treeOutline.rootDOMNode = WebInspector.domAgent.nodeForId(object.nodeId); treeOutline.element.addStyleClass("outline-disclosure"); if (!treeOutline.children[0].hasChildren) treeOutline.element.addStyleClass("single-node"); @@ -513,7 +466,7 @@ WebInspector.ConsoleView.prototype = { _formatobject: function(obj, elem) { - elem.appendChild(new WebInspector.ObjectPropertiesSection(new WebInspector.ObjectProxy(obj), Object.describe(obj, true), null, null, true).element); + elem.appendChild(new WebInspector.ObjectPropertiesSection(obj, obj.description, null, true).element); }, _formaterror: function(obj, elem) diff --git a/WebCore/inspector/front-end/CookieItemsView.js b/WebCore/inspector/front-end/CookieItemsView.js new file mode 100644 index 0000000..2d69e7d --- /dev/null +++ b/WebCore/inspector/front-end/CookieItemsView.js @@ -0,0 +1,329 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009 Joseph Pecoraro + * + * 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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. + */ + +WebInspector.CookieItemsView = function() +{ + WebInspector.View.call(this); + + // Some Platforms have not yet implemented access to raw cookies + // Those platforms will return undefined instead of an Array + // For these platforms we: + // - resort to document.cookie + // - do not show the delete cookie status bar button + this._useFallback = typeof InspectorController.cookies() === "undefined"; + + this.element.addStyleClass("storage-view"); + this.element.addStyleClass("table"); + + this.deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item"); + this.deleteButton.visible = false; + this.deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false); + + this.refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item"); + this.refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false); +} + +WebInspector.CookieItemsView.prototype = { + get statusBarItems() + { + if (this._useFallback) + return [this.refreshButton.element]; + else + return [this.refreshButton.element, this.deleteButton.element]; + }, + + show: function(parentElement) + { + WebInspector.View.prototype.show.call(this, parentElement); + this.update(); + }, + + hide: function() + { + WebInspector.View.prototype.hide.call(this); + this.deleteButton.visible = false; + }, + + update: function() + { + if (this._useFallback) { + this.fallbackUpdate(); + return; + } + + this.element.removeChildren(); + var dataGrid = this.dataGridForCookies(); + if (dataGrid) { + this._dataGrid = dataGrid; + this.element.appendChild(dataGrid.element); + this.deleteButton.visible = true; + } else { + var emptyMsgElement = document.createElement("div"); + emptyMsgElement.className = "storage-table-empty"; + emptyMsgElement.textContent = WebInspector.UIString("This site has no cookies."); + this.element.appendChild(emptyMsgElement); + this._dataGrid = null; + this.deleteButton.visible = false; + } + }, + + buildCookies: function() + { + var rawCookies = InspectorController.cookies(); + var cookies = []; + for (var i = 0; i < rawCookies.length; ++i) { + var cookie = rawCookies[i]; + cookie.expires = new Date(cookie.expires); + cookies.push(cookie); + } + + return cookies; + }, + + dataGridForCookies: function() + { + var cookies = this.buildCookies(); + if (!cookies.length) + return null; + + var columns = { 0: {}, 1: {}, 2: {}, 3: {}, 4: {}, 5: {}, 6: {}, 7: {} }; + columns[0].title = WebInspector.UIString("Name"); + columns[0].width = columns[0].title.length; + columns[1].title = WebInspector.UIString("Value"); + columns[1].width = columns[1].title.length; + columns[2].title = WebInspector.UIString("Domain"); + columns[2].width = columns[2].title.length; + columns[3].title = WebInspector.UIString("Path"); + columns[3].width = columns[3].title.length; + columns[4].title = WebInspector.UIString("Expires"); + columns[4].width = columns[4].title.length; + columns[5].title = WebInspector.UIString("Size"); + columns[5].width = columns[5].title.length; + columns[5].aligned = "right"; + columns[6].title = WebInspector.UIString("HTTP"); + columns[6].width = columns[6].title.length; + columns[6].aligned = "centered"; + columns[7].title = WebInspector.UIString("Secure"); + columns[7].width = columns[7].title.length; + columns[7].aligned = "centered"; + + function updateDataAndColumn(index, value) { + data[index] = value; + if (value.length > columns[index].width) + columns[index].width = value.length; + } + + var data; + var nodes = []; + for (var i = 0; i < cookies.length; ++i) { + var cookie = cookies[i]; + data = {}; + + updateDataAndColumn(0, cookie.name); + updateDataAndColumn(1, cookie.value); + updateDataAndColumn(2, cookie.domain); + updateDataAndColumn(3, cookie.path); + updateDataAndColumn(4, (cookie.session ? "Session" : cookie.expires.toGMTString())); + updateDataAndColumn(5, Number.bytesToString(cookie.size, WebInspector.UIString)); + updateDataAndColumn(6, (cookie.httpOnly ? "\u2713" : "")); // Checkmark + updateDataAndColumn(7, (cookie.secure ? "\u2713" : "")); // Checkmark + + var node = new WebInspector.DataGridNode(data, false); + node.cookie = cookie; + node.selectable = true; + nodes.push(node); + } + + var totalColumnWidths = 0; + for (var columnIdentifier in columns) + totalColumnWidths += columns[columnIdentifier].width; + + // Enforce the Value column (the 2nd column) to be a max of 33% + // tweaking the raw total width because may massively outshadow the others + var valueColumnWidth = columns[1].width; + if (valueColumnWidth / totalColumnWidths > 0.33) { + totalColumnWidths -= valueColumnWidth; + totalColumnWidths *= 1.33; + columns[1].width = totalColumnWidths * 0.33; + } + + // Calculate the percentage width for the columns. + const minimumPrecent = 6; + var recoupPercent = 0; + for (var columnIdentifier in columns) { + var width = columns[columnIdentifier].width; + width = Math.round((width / totalColumnWidths) * 100); + if (width < minimumPrecent) { + recoupPercent += (minimumPrecent - width); + width = minimumPrecent; + } + columns[columnIdentifier].width = width; + } + + // Enforce the minimum percentage width. (need to narrow total percentage due to earlier additions) + while (recoupPercent > 0) { + for (var columnIdentifier in columns) { + if (columns[columnIdentifier].width > minimumPrecent) { + --columns[columnIdentifier].width; + --recoupPercent; + if (!recoupPercent) + break; + } + } + } + + for (var columnIdentifier in columns) + columns[columnIdentifier].width += "%"; + + var dataGrid = new WebInspector.DataGrid(columns); + var length = nodes.length; + for (var i = 0; i < length; ++i) + dataGrid.appendChild(nodes[i]); + if (length > 0) + nodes[0].selected = true; + + return dataGrid; + }, + + fallbackUpdate: function() + { + this.element.removeChildren(); + + var self = this; + function callback(rawCookieString) { + var cookies = self.fallbackBuildCookiesFromString(rawCookieString); + var dataGrid = self.fallbackDataGridForCookies(cookies); + if (dataGrid) { + self._dataGrid = dataGrid; + self.element.appendChild(dataGrid.element); + self.deleteButton.visible = true; + } else { + var emptyMsgElement = document.createElement("div"); + emptyMsgElement.className = "storage-table-empty"; + emptyMsgElement.textContent = WebInspector.UIString("This site has no cookies."); + self.element.appendChild(emptyMsgElement); + self._dataGrid = null; + self.deleteButton.visible = false; + } + } + + InspectorController.getCookies(callback); + }, + + fallbackBuildCookiesFromString: function(rawCookieString) + { + var rawCookies = rawCookieString.split(/;\s*/); + var cookies = []; + + if (!(/^\s*$/.test(rawCookieString))) { + for (var i = 0; i < rawCookies.length; ++i) { + var cookie = rawCookies[i]; + var delimIndex = cookie.indexOf("="); + var name = cookie.substring(0, delimIndex); + var value = cookie.substring(delimIndex + 1); + var size = name.length + value.length; + cookies.push({ name: name, value: value, size: size }); + } + } + + return cookies; + }, + + fallbackDataGridForCookies: function(cookies) + { + if (!cookies.length) + return null; + + var columns = {}; + columns[0] = {}; + columns[1] = {}; + columns[0].title = WebInspector.UIString("Name"); + columns[0].width = columns[0].title.length; + columns[1].title = WebInspector.UIString("Value"); + columns[1].width = columns[1].title.length; + + var nodes = []; + for (var i = 0; i < cookies.length; ++i) { + var cookie = cookies[i]; + var data = {}; + + var name = cookie.name; + data[0] = name; + if (name.length > columns[0].width) + columns[0].width = name.length; + + var value = cookie.value; + data[1] = value; + if (value.length > columns[1].width) + columns[1].width = value.length; + + var node = new WebInspector.DataGridNode(data, false); + node.selectable = true; + nodes.push(node); + } + + var totalColumnWidths = columns[0].width + columns[1].width; + var width = Math.round((columns[0].width * 100) / totalColumnWidths); + const minimumPrecent = 20; + if (width < minimumPrecent) + width = minimumPrecent; + if (width > 100 - minimumPrecent) + width = 100 - minimumPrecent; + columns[0].width = width; + columns[1].width = 100 - width; + columns[0].width += "%"; + columns[1].width += "%"; + + var dataGrid = new WebInspector.DataGrid(columns); + var length = nodes.length; + for (var i = 0; i < length; ++i) + dataGrid.appendChild(nodes[i]); + if (length > 0) + nodes[0].selected = true; + + return dataGrid; + }, + + _deleteButtonClicked: function(event) + { + if (!this._dataGrid || this._useFallback) + return; + + var cookie = this._dataGrid.selectedNode.cookie; + InspectorController.deleteCookie(cookie.name); + this.update(); + }, + + _refreshButtonClicked: function(event) + { + this.update(); + } +} + +WebInspector.CookieItemsView.prototype.__proto__ = WebInspector.View.prototype; diff --git a/WebCore/inspector/front-end/DOMAgent.js b/WebCore/inspector/front-end/DOMAgent.js index 5aacd41..7942f0a 100644 --- a/WebCore/inspector/front-end/DOMAgent.js +++ b/WebCore/inspector/front-end/DOMAgent.js @@ -31,7 +31,7 @@ WebInspector.DOMNode = function(doc, payload) { this.ownerDocument = doc; - this._id = payload.id; + this.id = payload.id; this.nodeType = payload.nodeType; this.nodeName = payload.nodeName; this._nodeValue = payload.nodeValue; @@ -48,14 +48,22 @@ WebInspector.DOMNode = function(doc, payload) { this.nextSibling = null; this.prevSibling = null; this.firstChild = null; + this.lastChild = null; this.parentNode = null; - if (payload.childNodes) - this._setChildrenPayload(payload.childNodes); + if (payload.children) + this._setChildrenPayload(payload.children); this._computedStyle = null; this.style = null; this._matchedCSSRules = []; + + if (this.nodeType == Node.ELEMENT_NODE) { + if (this.nodeName == "HTML") + this.ownerDocument.documentElement = this; + if (this.nodeName == "BODY") + this.ownerDocument.body = this; + } } WebInspector.DOMNode.prototype = { @@ -161,9 +169,11 @@ WebInspector.DOMNode.prototype = { this._childNodeCount = this.children.length; if (this._childNodeCount == 0) { this.firstChild = null; + this.lastChild = null; return; } this.firstChild = this.children[0]; + this.lastChild = this.children[this._childNodeCount - 1]; for (var i = 0; i < this._childNodeCount; ++i) { var child = this.children[i]; child.nextSibling = i + 1 < this._childNodeCount ? this.children[i + 1] : null; @@ -208,17 +218,9 @@ WebInspector.DOMNode.prototype = { } } -WebInspector.DOMDocument = function(domAgent, defaultView) +WebInspector.DOMDocument = function(domAgent, defaultView, payload) { - WebInspector.DOMNode.call(this, null, - { - id: 0, - nodeType: Node.DOCUMENT_NODE, - nodeName: "", - nodeValue: "", - attributes: [], - childNodeCount: 0 - }); + WebInspector.DOMNode.call(this, this, payload); this._listeners = {}; this._domAgent = domAgent; this.defaultView = defaultView; @@ -226,7 +228,7 @@ WebInspector.DOMDocument = function(domAgent, defaultView) WebInspector.DOMDocument.prototype = { - addEventListener: function(name, callback, useCapture) + addEventListener: function(name, callback) { var listeners = this._listeners[name]; if (!listeners) { @@ -236,7 +238,7 @@ WebInspector.DOMDocument.prototype = { listeners.push(callback); }, - removeEventListener: function(name, callback, useCapture) + removeEventListener: function(name, callback) { var listeners = this._listeners[name]; if (!listeners) @@ -251,10 +253,12 @@ WebInspector.DOMDocument.prototype = { { var listeners = this._listeners[name]; if (!listeners) - return; + return; - for (var i = 0; i < listeners.length; ++i) - listeners[i](event); + for (var i = 0; i < listeners.length; ++i) { + var listener = listeners[i]; + listener.call(this, event); + } } } @@ -302,23 +306,8 @@ WebInspector.DOMAgent = function() { this._idToDOMNode = null; this.document = null; - // Install onpopulate handler. This is a temporary measure. - // TODO: add this code into the original updateChildren once domAgent - // becomes primary source of DOM information. - // TODO2: update ElementsPanel to not track embedded iframes - it is already being handled + // TODO: update ElementsPanel to not track embedded iframes - it is already being handled // in the agent backend. - var domAgent = this; - var originalUpdateChildren = WebInspector.ElementsTreeElement.prototype.updateChildren; - WebInspector.ElementsTreeElement.prototype.updateChildren = function() - { - domAgent.getChildNodesAsync(this.representedObject, originalUpdateChildren.bind(this)); - }; - - // Mute console handle to avoid crash on selection change. - // TODO: Re-implement inspectorConsoleAPI to work in a serialized way and remove this workaround. - WebInspector.Console.prototype.addInspectedNode = function() - { - }; // Whitespace is ignored in InspectorDOMAgent already -> no need to filter. // TODO: Either remove all of its usages or push value into the agent backend. @@ -331,38 +320,36 @@ WebInspector.DOMAgent.prototype = { return this._window; }, - getChildNodesAsync: function(parent, opt_callback) + getChildNodesAsync: function(parent, callback) { var children = parent.children; - if (children && opt_callback) { - opt_callback(children); - return; + if (children) { + callback(children); + return; + } + function mycallback() { + callback(parent.children); } - var mycallback = function() { - if (opt_callback) { - opt_callback(parent.children); - } - }; var callId = WebInspector.Callback.wrap(mycallback); - InspectorController.getChildNodes(callId, parent._id); + InspectorController.getChildNodes(callId, parent.id); }, setAttributeAsync: function(node, name, value, callback) { var mycallback = this._didApplyDomChange.bind(this, node, callback); - InspectorController.setAttribute(WebInspector.Callback.wrap(mycallback), node._id, name, value); + InspectorController.setAttribute(WebInspector.Callback.wrap(mycallback), node.id, name, value); }, removeAttributeAsync: function(node, name, callback) { var mycallback = this._didApplyDomChange.bind(this, node, callback); - InspectorController.removeAttribute(WebInspector.Callback.wrap(mycallback), node._id, name); + InspectorController.removeAttribute(WebInspector.Callback.wrap(mycallback), node.id, name); }, setTextNodeValueAsync: function(node, text, callback) { var mycallback = this._didApplyDomChange.bind(this, node, callback); - InspectorController.setTextNodeValue(WebInspector.Callback.wrap(mycallback), node._id, text); + InspectorController.setTextNodeValue(WebInspector.Callback.wrap(mycallback), node.id, text); }, _didApplyDomChange: function(node, callback, success) @@ -383,26 +370,22 @@ WebInspector.DOMAgent.prototype = { node._setAttributesPayload(attrsArray); }, - getNodeForId: function(nodeId) { + nodeForId: function(nodeId) { return this._idToDOMNode[nodeId]; }, - _setDocumentElement: function(payload) + _setDocument: function(payload) { - this.document = new WebInspector.DOMDocument(this, this._window); - this._idToDOMNode = { 0 : this.document }; - this._setChildNodes(0, [payload]); - this.document.documentElement = this.document.firstChild; - this.document.documentElement.ownerDocument = this.document; + this.document = new WebInspector.DOMDocument(this, this._window, payload); + this._idToDOMNode = {}; + this._idToDOMNode[payload.id] = this.document; + this._bindNodes(this.document.children); WebInspector.panels.elements.reset(); }, _setChildNodes: function(parentId, payloads) { var parent = this._idToDOMNode[parentId]; - if (parent.children) { - return; - } parent._setChildrenPayload(payloads); this._bindNodes(parent.children); }, @@ -411,7 +394,7 @@ WebInspector.DOMAgent.prototype = { { for (var i = 0; i < children.length; ++i) { var child = children[i]; - this._idToDOMNode[child._id] = child; + this._idToDOMNode[child.id] = child; if (child.children) this._bindNodes(child.children); } @@ -433,7 +416,7 @@ WebInspector.DOMAgent.prototype = { var parent = this._idToDOMNode[parentId]; var prev = this._idToDOMNode[prevId]; var node = parent._insertChild(prev, payload); - this._idToDOMNode[node._id] = node; + this._idToDOMNode[node.id] = node; var event = { target : node, relatedNode : parent }; this.document._fireDomEvent("DOMNodeInserted", event); }, @@ -450,7 +433,7 @@ WebInspector.DOMAgent.prototype = { } WebInspector.CSSStyleDeclaration = function(payload) { - this._id = payload.id; + this.id = payload.id; this.width = payload.width; this.height = payload.height; this.__disabledProperties = payload.__disabledProperties; @@ -492,12 +475,13 @@ WebInspector.CSSStyleDeclaration.parseStyle = function(payload) WebInspector.CSSStyleDeclaration.parseRule = function(payload) { var rule = {}; - rule._id = payload.id; + rule.id = payload.id; rule.selectorText = payload.selectorText; rule.style = new WebInspector.CSSStyleDeclaration(payload.style); rule.style.parentRule = rule; rule.isUserAgent = payload.isUserAgent; rule.isUser = payload.isUser; + rule.isViaInspector = payload.isViaInspector; if (payload.parentStyleSheet) rule.parentStyleSheet = { href: payload.parentStyleSheet.href }; @@ -586,9 +570,9 @@ WebInspector.attributesUpdated = function() this.domAgent._attributesUpdated.apply(this.domAgent, arguments); } -WebInspector.setDocumentElement = function() +WebInspector.setDocument = function() { - this.domAgent._setDocumentElement.apply(this.domAgent, arguments); + this.domAgent._setDocument.apply(this.domAgent, arguments); } WebInspector.setChildNodes = function() @@ -604,13 +588,11 @@ WebInspector.hasChildrenUpdated = function() WebInspector.childNodeInserted = function() { this.domAgent._childNodeInserted.apply(this.domAgent, arguments); - this._childNodeInserted.bind(this); } WebInspector.childNodeRemoved = function() { this.domAgent._childNodeRemoved.apply(this.domAgent, arguments); - this._childNodeRemoved.bind(this); } WebInspector.didGetChildNodes = WebInspector.Callback.processCallback; @@ -619,106 +601,122 @@ WebInspector.didApplyDomChange = WebInspector.Callback.processCallback; WebInspector.didRemoveAttribute = WebInspector.Callback.processCallback; WebInspector.didSetTextNodeValue = WebInspector.Callback.processCallback; -// Temporary methods for DOMAgent migration. -WebInspector.wrapNodeWithStyles = function(node, styles) -{ - var windowStub = new WebInspector.DOMWindow(null); - var docStub = new WebInspector.DOMDocument(null, windowStub); - var payload = {}; - payload.nodeType = node.nodeType; - payload.nodeName = node.nodeName; - payload.nodeValue = node.nodeValue; - payload.attributes = []; - payload.childNodeCount = 0; - - for (var i = 0; i < node.attributes.length; ++i) { - var attr = node.attributes[i]; - payload.attributes.push(attr.name); - payload.attributes.push(attr.value); - } - var nodeStub = new WebInspector.DOMNode(docStub, payload); - nodeStub._setStyles(styles.computedStyle, styles.inlineStyle, styles.styleAttributes, styles.matchedCSSRules); - return nodeStub; -} - // Temporary methods that will be dispatched via InspectorController into the injected context. InspectorController.getStyles = function(nodeId, authorOnly, callback) { setTimeout(function() { callback(InjectedScript.getStyles(nodeId, authorOnly)); - }, 0) + }, 0); } InspectorController.getComputedStyle = function(nodeId, callback) { setTimeout(function() { callback(InjectedScript.getComputedStyle(nodeId)); - }, 0) + }, 0); } InspectorController.getInlineStyle = function(nodeId, callback) { setTimeout(function() { callback(InjectedScript.getInlineStyle(nodeId)); - }, 0) + }, 0); } InspectorController.applyStyleText = function(styleId, styleText, propertyName, callback) { setTimeout(function() { callback(InjectedScript.applyStyleText(styleId, styleText, propertyName)); - }, 0) + }, 0); } InspectorController.setStyleText = function(style, cssText, callback) { setTimeout(function() { callback(InjectedScript.setStyleText(style, cssText)); - }, 0) + }, 0); } InspectorController.toggleStyleEnabled = function(styleId, propertyName, disabled, callback) { setTimeout(function() { callback(InjectedScript.toggleStyleEnabled(styleId, propertyName, disabled)); - }, 0) + }, 0); } -InspectorController.applyStyleRuleText = function(ruleId, newContent, selectedNode, callback) +InspectorController.applyStyleRuleText = function(ruleId, newContent, selectedNodeId, callback) { setTimeout(function() { - callback(InjectedScript.applyStyleRuleText(ruleId, newContent, selectedNode)); - }, 0) + callback(InjectedScript.applyStyleRuleText(ruleId, newContent, selectedNodeId)); + }, 0); } -InspectorController.addStyleSelector = function(newContent, callback) +InspectorController.addStyleSelector = function(newContent, selectedNodeId, callback) { setTimeout(function() { - callback(InjectedScript.addStyleSelector(newContent)); - }, 0) + callback(InjectedScript.addStyleSelector(newContent, selectedNodeId)); + }, 0); } -InspectorController.setStyleProperty = function(styleId, name, value, callback) { +InspectorController.setStyleProperty = function(styleId, name, value, callback) +{ setTimeout(function() { callback(InjectedScript.setStyleProperty(styleId, name, value)); - }, 0) + }, 0); } -InspectorController.getPrototypes = function(objectProxy, callback) { +InspectorController.getPrototypes = function(nodeId, callback) +{ setTimeout(function() { - callback(InjectedScript.getPrototypes(objectProxy)); - }, 0) + callback(InjectedScript.getPrototypes(nodeId)); + }, 0); } -InspectorController.getProperties = function(objectProxy, ignoreHasOwnProperty, callback) { +InspectorController.getProperties = function(objectProxy, ignoreHasOwnProperty, callback) +{ setTimeout(function() { callback(InjectedScript.getProperties(objectProxy, ignoreHasOwnProperty)); - }, 0) + }, 0); } -InspectorController.setPropertyValue = function(objectProxy, propertyName, expression, callback) { +InspectorController.setPropertyValue = function(objectProxy, propertyName, expression, callback) +{ setTimeout(function() { callback(InjectedScript.setPropertyValue(objectProxy, propertyName, expression)); - }, 0) + }, 0); +} + +InspectorController.evaluate = function(expression, callback) +{ + setTimeout(function() { + callback(InjectedScript.evaluate(expression)); + }, 0); +} + +InspectorController.addInspectedNode = function(nodeId, callback) +{ + setTimeout(function() { + callback(InjectedScript.addInspectedNode(nodeId)); + }, 0); +} + +InspectorController.performSearch = function(whitespaceTrimmedQuery, callback) +{ + setTimeout(function() { + callback(InjectedScript.performSearch(whitespaceTrimmedQuery)); + }, 0); +} + +InspectorController.searchCanceled = function(callback) +{ + setTimeout(function() { + callback(InjectedScript.searchCanceled()); + }, 0); } +InspectorController.getCookies = function(callback) +{ + setTimeout(function() { + callback(InjectedScript.getCookies()); + }, 0); +} diff --git a/WebCore/inspector/front-end/DOMStorageItemsView.js b/WebCore/inspector/front-end/DOMStorageItemsView.js index fad6e3c..514883f 100644 --- a/WebCore/inspector/front-end/DOMStorageItemsView.js +++ b/WebCore/inspector/front-end/DOMStorageItemsView.js @@ -32,21 +32,18 @@ WebInspector.DOMStorageItemsView = function(domStorage) this.element.addStyleClass("storage-view"); this.element.addStyleClass("table"); - this.deleteButton = document.createElement("button"); - this.deleteButton.title = WebInspector.UIString("Delete"); - this.deleteButton.className = "delete-storage-status-bar-item status-bar-item hidden"; + this.deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item"); + this.deleteButton.visible = false; this.deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false); - this.refreshButton = document.createElement("button"); - this.refreshButton.title = WebInspector.UIString("Refresh"); - this.refreshButton.className = "refresh-storage-status-bar-item status-bar-item"; + this.refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item"); this.refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false); } WebInspector.DOMStorageItemsView.prototype = { get statusBarItems() { - return [this.refreshButton, this.deleteButton]; + return [this.refreshButton.element, this.deleteButton.element]; }, show: function(parentElement) @@ -58,7 +55,7 @@ WebInspector.DOMStorageItemsView.prototype = { hide: function() { WebInspector.View.prototype.hide.call(this); - this.deleteButton.addStyleClass("hidden"); + this.deleteButton.visible = false; }, update: function() @@ -76,7 +73,7 @@ WebInspector.DOMStorageItemsView.prototype = { this._dataGrid = dataGrid; this.element.appendChild(dataGrid.element); this._dataGrid.updateWidths(); - this.deleteButton.removeStyleClass("hidden"); + this.deleteButton.visible = true; } } @@ -87,7 +84,7 @@ WebInspector.DOMStorageItemsView.prototype = { emptyMsgElement.textContent = WebInspector.UIString("This storage is empty."); this.element.appendChild(emptyMsgElement); this._dataGrid = null; - this.deleteButton.addStyleClass("hidden"); + this.deleteButton.visible = false; } }, diff --git a/WebCore/inspector/front-end/DataGrid.js b/WebCore/inspector/front-end/DataGrid.js index 42e001c..ce61548 100644 --- a/WebCore/inspector/front-end/DataGrid.js +++ b/WebCore/inspector/front-end/DataGrid.js @@ -39,6 +39,8 @@ WebInspector.DataGrid = function(columns) this._dataTable.addEventListener("mousedown", this._mouseDownInDataTable.bind(this), true); this._dataTable.addEventListener("click", this._clickInDataTable.bind(this), true); + this.aligned = {}; + var scrollContainer = document.createElement("div"); scrollContainer.className = "data-container"; scrollContainer.appendChild(this._dataTable); @@ -78,6 +80,11 @@ WebInspector.DataGrid = function(columns) cell.addStyleClass("sortable"); } + if (column.aligned) { + cell.addStyleClass(column.aligned); + this.aligned[columnIdentifier] = column.aligned; + } + headerRow.appendChild(cell); ++columnCount; @@ -752,6 +759,10 @@ WebInspector.DataGridNode.prototype = { var cell = document.createElement("td"); cell.className = columnIdentifier + "-column"; + var alignment = this.dataGrid.aligned[columnIdentifier]; + if (alignment) + cell.addStyleClass(alignment); + var div = document.createElement("div"); div.textContent = this.data[columnIdentifier]; cell.appendChild(div); diff --git a/WebCore/inspector/front-end/DatabasesPanel.js b/WebCore/inspector/front-end/DatabasesPanel.js index a31e3ff..acbbe28 100644 --- a/WebCore/inspector/front-end/DatabasesPanel.js +++ b/WebCore/inspector/front-end/DatabasesPanel.js @@ -59,6 +59,10 @@ WebInspector.DatabasesPanel = function(database) this.sidebarTree.appendChild(this.sessionStorageListTreeElement); this.sessionStorageListTreeElement.expand(); + this.cookieListTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("COOKIES"), {}, true); + this.sidebarTree.appendChild(this.cookieListTreeElement); + this.cookieListTreeElement.expand(); + this.storageViews = document.createElement("div"); this.storageViews.id = "storage-views"; this.element.appendChild(this.storageViews); @@ -87,6 +91,12 @@ WebInspector.DatabasesPanel.prototype = { WebInspector.Panel.prototype.show.call(this); this._updateSidebarWidth(); this._registerStorageEventListener(); + this.populateInterface(); + }, + + populateInterface: function() + { + this.addCookies(); }, reset: function() @@ -116,11 +126,15 @@ WebInspector.DatabasesPanel.prototype = { this._domStorage = []; + delete this.cookieTreeElement; + delete this._cookieView; + this.databasesListTreeElement.removeChildren(); this.localStorageListTreeElement.removeChildren(); this.sessionStorageListTreeElement.removeChildren(); - this.storageViews.removeChildren(); - + this.cookieListTreeElement.removeChildren(); + this.storageViews.removeChildren(); + this.storageViewStatusBarItemsContainer.removeChildren(); }, @@ -149,6 +163,14 @@ WebInspector.DatabasesPanel.prototype = { this.sessionStorageListTreeElement.appendChild(domStorageTreeElement); }, + addCookies: function() + { + if (!this.cookieTreeElement) { + this.cookieTreeElement = new WebInspector.CookieSidebarTreeElement(); + this.cookieListTreeElement.appendChild(this.cookieTreeElement); + } + }, + selectDatabase: function(db) { var database; @@ -235,6 +257,27 @@ WebInspector.DatabasesPanel.prototype = { this.storageViewStatusBarItemsContainer.appendChild(statusBarItems[i]); }, + showCookies: function() + { + if (this.visibleView) + this.visibleView.hide(); + + var view = this._cookieView; + if (!view) { + view = new WebInspector.CookieItemsView(); + this._cookieView = view; + } + + view.show(this.storageViews); + + this.visibleView = view; + + this.storageViewStatusBarItemsContainer.removeChildren(); + var statusBarItems = view.statusBarItems; + for (var i = 0; i < statusBarItems.length; ++i) + this.storageViewStatusBarItemsContainer.appendChild(statusBarItems[i]); + }, + closeVisibleView: function() { if (this.visibleView) @@ -357,7 +400,7 @@ WebInspector.DatabasesPanel.prototype = { columns[0].title = WebInspector.UIString("Key"); columns[0].width = columns[0].title.length; columns[1].title = WebInspector.UIString("Value"); - columns[1].width = columns[0].title.length; + columns[1].width = columns[1].title.length; var nodes = []; @@ -380,7 +423,7 @@ WebInspector.DatabasesPanel.prototype = { } var totalColumnWidths = columns[0].width + columns[1].width; - width = Math.round((columns[0].width * 100) / totalColumnWidths); + var width = Math.round((columns[0].width * 100) / totalColumnWidths); const minimumPrecent = 10; if (width < minimumPrecent) width = minimumPrecent; @@ -400,7 +443,7 @@ WebInspector.DatabasesPanel.prototype = { nodes[0].selected = true; return dataGrid; }, - + resize: function() { var visibleView = this.visibleView; @@ -606,3 +649,39 @@ WebInspector.DOMStorageSidebarTreeElement.prototype = { } WebInspector.DOMStorageSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype; + +WebInspector.CookieSidebarTreeElement = function() +{ + WebInspector.SidebarTreeElement.call(this, "cookie-sidebar-tree-item", null, "", null, false); + + this.refreshTitles(); +} + +WebInspector.CookieSidebarTreeElement.prototype = { + onselect: function() + { + WebInspector.panels.databases.showCookies(); + }, + + get mainTitle() + { + return WebInspector.UIString("Cookies"); + }, + + set mainTitle(x) + { + // Do nothing. + }, + + get subtitle() + { + return ""; + }, + + set subtitle(x) + { + // Do nothing. + } +} + +WebInspector.CookieSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype; diff --git a/WebCore/inspector/front-end/Drawer.js b/WebCore/inspector/front-end/Drawer.js index 23dc483..1b50f91 100644 --- a/WebCore/inspector/front-end/Drawer.js +++ b/WebCore/inspector/front-end/Drawer.js @@ -64,6 +64,12 @@ WebInspector.Drawer.prototype = { } }, + showView: function(view) + { + if (!this.visible || this.visibleView !== view) + this.visibleView = view; + }, + show: function() { if (this._animating || this.visible) diff --git a/WebCore/inspector/front-end/ElementsPanel.js b/WebCore/inspector/front-end/ElementsPanel.js index ffa0000..1748159 100644 --- a/WebCore/inspector/front-end/ElementsPanel.js +++ b/WebCore/inspector/front-end/ElementsPanel.js @@ -61,7 +61,8 @@ WebInspector.ElementsPanel = function() InspectorController.toggleNodeSearch(); this.panel.nodeSearchButton.removeStyleClass("toggled-on"); } - WebInspector.console.addInspectedNode(this._focusedDOMNode); + if (this._focusedDOMNode) + InspectorController.addInspectedNode(this._focusedDOMNode.id, function() {}); }; this.contentElement.appendChild(this.treeOutline.element); @@ -97,10 +98,7 @@ WebInspector.ElementsPanel = function() this.sidebarResizeElement.className = "sidebar-resizer-vertical"; this.sidebarResizeElement.addEventListener("mousedown", this.rightSidebarResizerDragStart.bind(this), false); - this.nodeSearchButton = this.createStatusBarButton(); - this.nodeSearchButton.title = WebInspector.UIString("Select an element in the page to inspect it."); - this.nodeSearchButton.id = "node-search-status-bar-item"; - this.nodeSearchButton.className = "status-bar-item"; + this.nodeSearchButton = new WebInspector.StatusBarButton(WebInspector.UIString("Select an element in the page to inspect it."), "node-search-status-bar-item"); this.nodeSearchButton.addEventListener("click", this._nodeSearchButtonClicked.bind(this), false); this.searchingForNode = false; @@ -109,13 +107,7 @@ WebInspector.ElementsPanel = function() this.element.appendChild(this.sidebarElement); this.element.appendChild(this.sidebarResizeElement); - this._mutationMonitoredWindows = []; - this._nodeInsertedEventListener = InspectorController.wrapCallback(this._nodeInserted.bind(this)); - this._nodeRemovedEventListener = InspectorController.wrapCallback(this._nodeRemoved.bind(this)); - this._contentLoadedEventListener = InspectorController.wrapCallback(this._contentLoaded.bind(this)); - - this.stylesheet = null; - this.styles = {}; + this._changedStyles = {}; this.reset(); } @@ -130,7 +122,7 @@ WebInspector.ElementsPanel.prototype = { get statusBarItems() { - return [this.nodeSearchButton, this.crumbsElement]; + return [this.nodeSearchButton.element, this.crumbsElement]; }, updateStatusBarItems: function() @@ -156,7 +148,7 @@ WebInspector.ElementsPanel.prototype = { if (InspectorController.searchingForNode()) { InspectorController.toggleNodeSearch(); - this.nodeSearchButton.removeStyleClass("toggled-on"); + this.nodeSearchButton.toggled = false; } }, @@ -175,40 +167,27 @@ WebInspector.ElementsPanel.prototype = { if (InspectorController.searchingForNode()) { InspectorController.toggleNodeSearch(); - this.nodeSearchButton.removeStyleClass("toggled-on"); + this.nodeSearchButton.toggled = false; } this.recentlyModifiedNodes = []; - this.unregisterAllMutationEventListeners(); delete this.currentQuery; this.searchCanceled(); - var inspectedWindow = Preferences.useDOMAgent ? WebInspector.domAgent.inspectedWindow : InspectorController.inspectedWindow(); - if (!inspectedWindow || !inspectedWindow.document) + var inspectedWindow = WebInspector.domAgent.inspectedWindow; + if (!inspectedWindow || !inspectedWindow.document || !inspectedWindow.document.firstChild) return; - if (!inspectedWindow.document.firstChild) { - function contentLoaded() - { - inspectedWindow.document.removeEventListener("DOMContentLoaded", contentLoadedCallback, false); - - this.reset(); - } - - var contentLoadedCallback = InspectorController.wrapCallback(contentLoaded.bind(this)); - inspectedWindow.document.addEventListener("DOMContentLoaded", contentLoadedCallback, false); - return; - } - // If the window isn't visible, return early so the DOM tree isn't built // and mutation event listeners are not added. if (!InspectorController.isWindowVisible()) return; - this.registerMutationEventListeners(inspectedWindow); - var inspectedRootDocument = inspectedWindow.document; + inspectedRootDocument.addEventListener("DOMNodeInserted", this._nodeInserted.bind(this)); + inspectedRootDocument.addEventListener("DOMNodeRemoved", this._nodeRemoved.bind(this)); + this.rootDOMNode = inspectedRootDocument; var canidateFocusNode = inspectedRootDocument.body || inspectedRootDocument.documentElement; @@ -222,19 +201,11 @@ WebInspector.ElementsPanel.prototype = { } }, - includedInSearchResultsPropertyName: "__includedInInspectorSearchResults", - searchCanceled: function() { if (this._searchResults) { - const searchResultsProperty = this.includedInSearchResultsPropertyName; for (var i = 0; i < this._searchResults.length; ++i) { - var node = this._searchResults[i]; - - // Remove the searchResultsProperty since there might be an unfinished search. - delete node[searchResultsProperty]; - - var treeElement = this.treeOutline.findTreeElement(node); + var treeElement = this.treeOutline.findTreeElement(this._searchResults[i]); if (treeElement) treeElement.highlighted = false; } @@ -242,13 +213,9 @@ WebInspector.ElementsPanel.prototype = { WebInspector.updateSearchMatchesCount(0, this); - if (this._currentSearchChunkIntervalIdentifier) { - clearInterval(this._currentSearchChunkIntervalIdentifier); - delete this._currentSearchChunkIntervalIdentifier; - } - this._currentSearchResultIndex = 0; this._searchResults = []; + InspectorController.searchCanceled(function() {}); }, performSearch: function(query) @@ -260,241 +227,56 @@ WebInspector.ElementsPanel.prototype = { if (!whitespaceTrimmedQuery.length) return; - var tagNameQuery = whitespaceTrimmedQuery; - var attributeNameQuery = whitespaceTrimmedQuery; - var startTagFound = (tagNameQuery.indexOf("<") === 0); - var endTagFound = (tagNameQuery.lastIndexOf(">") === (tagNameQuery.length - 1)); - - if (startTagFound || endTagFound) { - var tagNameQueryLength = tagNameQuery.length; - tagNameQuery = tagNameQuery.substring((startTagFound ? 1 : 0), (endTagFound ? (tagNameQueryLength - 1) : tagNameQueryLength)); - } - - // Check the tagNameQuery is it is a possibly valid tag name. - if (!/^[a-zA-Z0-9\-_:]+$/.test(tagNameQuery)) - tagNameQuery = null; - - // Check the attributeNameQuery is it is a possibly valid tag name. - if (!/^[a-zA-Z0-9\-_:]+$/.test(attributeNameQuery)) - attributeNameQuery = null; - - const escapedQuery = query.escapeCharacters("'"); - const escapedTagNameQuery = (tagNameQuery ? tagNameQuery.escapeCharacters("'") : null); - const escapedWhitespaceTrimmedQuery = whitespaceTrimmedQuery.escapeCharacters("'"); - const searchResultsProperty = this.includedInSearchResultsPropertyName; - - var updatedMatchCountOnce = false; - var matchesCountUpdateTimeout = null; - - function updateMatchesCount() - { - WebInspector.updateSearchMatchesCount(this._searchResults.length, this); - matchesCountUpdateTimeout = null; - updatedMatchCountOnce = true; - } - - function updateMatchesCountSoon() - { - if (!updatedMatchCountOnce) - return updateMatchesCount.call(this); - if (matchesCountUpdateTimeout) - return; - // Update the matches count every half-second so it doesn't feel twitchy. - matchesCountUpdateTimeout = setTimeout(updateMatchesCount.bind(this), 500); - } - - function addNodesToResults(nodes, length, getItem) - { - if (!length) - return; - - for (var i = 0; i < length; ++i) { - var node = getItem.call(nodes, i); - // Skip this node if it already has the property. - if (searchResultsProperty in node) - continue; - - if (!this._searchResults.length) { - this._currentSearchResultIndex = 0; - this.focusedDOMNode = node; - } - - node[searchResultsProperty] = true; - this._searchResults.push(node); - - // Highlight the tree element to show it matched the search. - // FIXME: highlight the substrings in text nodes and attributes. - var treeElement = this.treeOutline.findTreeElement(node); - if (treeElement) - treeElement.highlighted = true; - } - - updateMatchesCountSoon.call(this); - } - - function matchExactItems(doc) - { - matchExactId.call(this, doc); - matchExactClassNames.call(this, doc); - matchExactTagNames.call(this, doc); - matchExactAttributeNames.call(this, doc); - } - - function matchExactId(doc) - { - const result = doc.__proto__.getElementById.call(doc, whitespaceTrimmedQuery); - addNodesToResults.call(this, result, (result ? 1 : 0), function() { return this }); - } - - function matchExactClassNames(doc) - { - const result = doc.__proto__.getElementsByClassName.call(doc, whitespaceTrimmedQuery); - addNodesToResults.call(this, result, result.length, result.item); - } - - function matchExactTagNames(doc) - { - if (!tagNameQuery) - return; - const result = doc.__proto__.getElementsByTagName.call(doc, tagNameQuery); - addNodesToResults.call(this, result, result.length, result.item); - } - - function matchExactAttributeNames(doc) - { - if (!attributeNameQuery) - return; - const result = doc.__proto__.querySelectorAll.call(doc, "[" + attributeNameQuery + "]"); - addNodesToResults.call(this, result, result.length, result.item); - } - - function matchPartialTagNames(doc) - { - if (!tagNameQuery) - return; - const result = doc.__proto__.evaluate.call(doc, "//*[contains(name(), '" + escapedTagNameQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); - addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); - } - - function matchStartOfTagNames(doc) - { - if (!tagNameQuery) - return; - const result = doc.__proto__.evaluate.call(doc, "//*[starts-with(name(), '" + escapedTagNameQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); - addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); - } + this._updatedMatchCountOnce = false; + this._matchesCountUpdateTimeout = null; - function matchPartialTagNamesAndAttributeValues(doc) - { - if (!tagNameQuery) { - matchPartialAttributeValues.call(this, doc); - return; - } - - const result = doc.__proto__.evaluate.call(doc, "//*[contains(name(), '" + escapedTagNameQuery + "') or contains(@*, '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); - addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); - } - - function matchPartialAttributeValues(doc) - { - const result = doc.__proto__.evaluate.call(doc, "//*[contains(@*, '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); - addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); - } - - function matchStyleSelector(doc) - { - const result = doc.__proto__.querySelectorAll.call(doc, whitespaceTrimmedQuery); - addNodesToResults.call(this, result, result.length, result.item); - } - - function matchPlainText(doc) - { - const result = doc.__proto__.evaluate.call(doc, "//text()[contains(., '" + escapedQuery + "')] | //comment()[contains(., '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); - addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); - } - - function matchXPathQuery(doc) - { - const result = doc.__proto__.evaluate.call(doc, whitespaceTrimmedQuery, doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); - addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); - } - - function finishedSearching() - { - // Remove the searchResultsProperty now that the search is finished. - for (var i = 0; i < this._searchResults.length; ++i) - delete this._searchResults[i][searchResultsProperty]; - } + InspectorController.performSearch(whitespaceTrimmedQuery, function() {}); + }, - const mainFrameDocument = InspectorController.inspectedWindow().document; - const searchDocuments = [mainFrameDocument]; - - if (tagNameQuery && startTagFound && endTagFound) - const searchFunctions = [matchExactTagNames, matchPlainText]; - else if (tagNameQuery && startTagFound) - const searchFunctions = [matchStartOfTagNames, matchPlainText]; - else if (tagNameQuery && endTagFound) { - // FIXME: we should have a matchEndOfTagNames search function if endTagFound is true but not startTagFound. - // This requires ends-with() support in XPath, WebKit only supports starts-with() and contains(). - const searchFunctions = [matchPartialTagNames, matchPlainText]; - } else if (whitespaceTrimmedQuery === "//*" || whitespaceTrimmedQuery === "*") { - // These queries will match every node. Matching everything isn't useful and can be slow for large pages, - // so limit the search functions list to plain text and attribute matching. - const searchFunctions = [matchPartialAttributeValues, matchPlainText]; - } else - const searchFunctions = [matchExactItems, matchStyleSelector, matchPartialTagNamesAndAttributeValues, matchPlainText, matchXPathQuery]; - - // Find all frames, iframes and object elements to search their documents. - const querySelectorAllFunction = InspectorController.inspectedWindow().Document.prototype.querySelectorAll; - const subdocumentResult = querySelectorAllFunction.call(mainFrameDocument, "iframe, frame, object"); - - for (var i = 0; i < subdocumentResult.length; ++i) { - var element = subdocumentResult.item(i); - if (element.contentDocument) - searchDocuments.push(element.contentDocument); - } + _updateMatchesCount: function() + { + WebInspector.updateSearchMatchesCount(this._searchResults.length, this); + this._matchesCountUpdateTimeout = null; + this._updatedMatchCountOnce = true; + }, - const panel = this; - var documentIndex = 0; - var searchFunctionIndex = 0; - var chunkIntervalIdentifier = null; + _updateMatchesCountSoon: function() + { + if (!this._updatedMatchCountOnce) + return this._updateMatchesCount(); + if (this._matchesCountUpdateTimeout) + return; + // Update the matches count every half-second so it doesn't feel twitchy. + this._matchesCountUpdateTimeout = setTimeout(this._updateMatchesCount.bind(this), 500); + }, - // Split up the work into chunks so we don't block the UI thread while processing. + addNodesToSearchResult: function(nodeIds) + { + if (!nodeIds) + return; - function processChunk() - { - var searchDocument = searchDocuments[documentIndex]; - var searchFunction = searchFunctions[searchFunctionIndex]; - - if (++searchFunctionIndex > searchFunctions.length) { - searchFunction = searchFunctions[0]; - searchFunctionIndex = 0; - - if (++documentIndex > searchDocuments.length) { - if (panel._currentSearchChunkIntervalIdentifier === chunkIntervalIdentifier) - delete panel._currentSearchChunkIntervalIdentifier; - clearInterval(chunkIntervalIdentifier); - finishedSearching.call(panel); - return; - } + var nodeIdsArray = nodeIds.split(","); + for (var i = 0; i < nodeIdsArray.length; ++i) { + var nodeId = nodeIdsArray[i]; + var node = WebInspector.domAgent.nodeForId(nodeId); + if (!node) + continue; - searchDocument = searchDocuments[documentIndex]; + if (!this._searchResults.length) { + this._currentSearchResultIndex = 0; + this.focusedDOMNode = node; } - if (!searchDocument || !searchFunction) - return; + this._searchResults.push(node); - try { - searchFunction.call(panel, searchDocument); - } catch(err) { - // ignore any exceptions. the query might be malformed, but we allow that. - } + // Highlight the tree element to show it matched the search. + // FIXME: highlight the substrings in text nodes and attributes. + var treeElement = this.treeOutline.findTreeElement(node); + if (treeElement) + treeElement.highlighted = true; } - processChunk(); - - chunkIntervalIdentifier = setInterval(processChunk, 25); - this._currentSearchChunkIntervalIdentifier = chunkIntervalIdentifier; + this._updateMatchesCountSoon(); }, jumpToNextSearchResult: function() @@ -515,12 +297,6 @@ WebInspector.ElementsPanel.prototype = { this.focusedDOMNode = this._searchResults[this._currentSearchResultIndex]; }, - inspectedWindowCleared: function(window) - { - if (InspectorController.isWindowVisible()) - this.updateMutationEventListeners(window); - }, - renameSelector: function(oldIdentifier, newIdentifier, oldSelector, newSelector) { // TODO: Implement Shifting the oldSelector, and its contents to a newSelector @@ -532,16 +308,16 @@ WebInspector.ElementsPanel.prototype = { return; var selector = style.parentRule.selectorText; - if (!this.styles[identifier]) - this.styles[identifier] = {}; + if (!this._changedStyles[identifier]) + this._changedStyles[identifier] = {}; - if (!this.styles[identifier][selector]) - this.styles[identifier][selector] = {}; + if (!this._changedStyles[identifier][selector]) + this._changedStyles[identifier][selector] = {}; - if (!this.styles[identifier][selector][property]) + if (!this._changedStyles[identifier][selector][property]) WebInspector.styleChanges += 1; - this.styles[identifier][selector][property] = style.getPropertyValue(property); + this._changedStyles[identifier][selector][property] = style.getPropertyValue(property); }, removeStyleChange: function(identifier, style, property) @@ -550,11 +326,11 @@ WebInspector.ElementsPanel.prototype = { return; var selector = style.parentRule.selectorText; - if (!this.styles[identifier] || !this.styles[identifier][selector]) + if (!this._changedStyles[identifier] || !this._changedStyles[identifier][selector]) return; - if (this.styles[identifier][selector][property]) { - delete this.styles[identifier][selector][property]; + if (this._changedStyles[identifier][selector][property]) { + delete this._changedStyles[identifier][selector][property]; WebInspector.styleChanges -= 1; } }, @@ -566,20 +342,20 @@ WebInspector.ElementsPanel.prototype = { // Merge Down to Just Selectors var mergedSelectors = {}; - for (var identifier in this.styles) { - for (var selector in this.styles[identifier]) { + for (var identifier in this._changedStyles) { + for (var selector in this._changedStyles[identifier]) { if (!mergedSelectors[selector]) - mergedSelectors[selector] = this.styles[identifier][selector]; + mergedSelectors[selector] = this._changedStyles[identifier][selector]; else { // merge on selector var merge = {}; for (var property in mergedSelectors[selector]) merge[property] = mergedSelectors[selector][property]; - for (var property in this.styles[identifier][selector]) { + for (var property in this._changedStyles[identifier][selector]) { if (!merge[property]) - merge[property] = this.styles[identifier][selector][property]; + merge[property] = this._changedStyles[identifier][selector][property]; else { // merge on property within a selector, include comment to notify user var value1 = merge[property]; - var value2 = this.styles[identifier][selector][property]; + var value2 = this._changedStyles[identifier][selector][property]; if (value1 === value2) merge[property] = [value1]; @@ -636,53 +412,6 @@ WebInspector.ElementsPanel.prototype = { InspectorController.inspectedWindow().console.log(result); }, - _addMutationEventListeners: function(monitoredWindow) - { - monitoredWindow.document.addEventListener("DOMNodeInserted", this._nodeInsertedEventListener, true); - monitoredWindow.document.addEventListener("DOMNodeRemoved", this._nodeRemovedEventListener, true); - if (monitoredWindow.frameElement) - monitoredWindow.addEventListener("DOMContentLoaded", this._contentLoadedEventListener, true); - }, - - _removeMutationEventListeners: function(monitoredWindow) - { - if (monitoredWindow.frameElement) - monitoredWindow.removeEventListener("DOMContentLoaded", this._contentLoadedEventListener, true); - if (!monitoredWindow.document) - return; - monitoredWindow.document.removeEventListener("DOMNodeInserted", this._nodeInsertedEventListener, true); - monitoredWindow.document.removeEventListener("DOMNodeRemoved", this._nodeRemovedEventListener, true); - }, - - updateMutationEventListeners: function(monitoredWindow) - { - this._addMutationEventListeners(monitoredWindow); - }, - - registerMutationEventListeners: function(monitoredWindow) - { - if (!monitoredWindow || this._mutationMonitoredWindows.indexOf(monitoredWindow) !== -1) - return; - this._mutationMonitoredWindows.push(monitoredWindow); - if (InspectorController.isWindowVisible()) - this._addMutationEventListeners(monitoredWindow); - }, - - unregisterMutationEventListeners: function(monitoredWindow) - { - if (!monitoredWindow || this._mutationMonitoredWindows.indexOf(monitoredWindow) === -1) - return; - this._mutationMonitoredWindows.remove(monitoredWindow); - this._removeMutationEventListeners(monitoredWindow); - }, - - unregisterAllMutationEventListeners: function() - { - for (var i = 0; i < this._mutationMonitoredWindows.length; ++i) - this._removeMutationEventListeners(this._mutationMonitoredWindows[i]); - this._mutationMonitoredWindows = []; - }, - get rootDOMNode() { return this.treeOutline.rootDOMNode; @@ -703,13 +432,6 @@ WebInspector.ElementsPanel.prototype = { this.treeOutline.focusedDOMNode = x; }, - _contentLoaded: function(event) - { - this.recentlyModifiedNodes.push({node: event.target, parent: event.target.defaultView.frameElement, replaced: true}); - if (this.visible) - this._updateModifiedNodesSoon(); - }, - _nodeInserted: function(event) { this.recentlyModifiedNodes.push({node: event.target, parent: event.relatedNode, inserted: true}); @@ -747,14 +469,14 @@ WebInspector.ElementsPanel.prototype = { if (!parent) continue; - var parentNodeItem = this.treeOutline.findTreeElement(parent, null, null, objectsAreSame); + var parentNodeItem = this.treeOutline.findTreeElement(parent); if (parentNodeItem && !parentNodeItem.alreadyUpdatedChildren) { parentNodeItem.updateChildren(replaced); parentNodeItem.alreadyUpdatedChildren = true; updatedParentTreeElements.push(parentNodeItem); } - if (!updateBreadcrumbs && (objectsAreSame(this.focusedDOMNode, parent) || isAncestorIncludingParentFrames(this.focusedDOMNode, parent))) + if (!updateBreadcrumbs && (this.focusedDOMNode === parent || isAncestorIncludingParentFrames(this.focusedDOMNode, parent))) updateBreadcrumbs = true; } @@ -814,7 +536,7 @@ WebInspector.ElementsPanel.prototype = { var foundRoot = false; var crumb = crumbs.firstChild; while (crumb) { - if (objectsAreSame(crumb.representedObject, this.rootDOMNode)) + if (crumb.representedObject === this.rootDOMNode) foundRoot = true; if (foundRoot) @@ -822,7 +544,7 @@ WebInspector.ElementsPanel.prototype = { else crumb.removeStyleClass("dimmed"); - if (objectsAreSame(crumb.representedObject, this.focusedDOMNode)) { + if (crumb.representedObject === this.focusedDOMNode) { crumb.addStyleClass("selected"); handled = true; } else { @@ -879,7 +601,7 @@ WebInspector.ElementsPanel.prototype = { if (current.nodeType === Node.DOCUMENT_NODE) continue; - if (objectsAreSame(current, this.rootDOMNode)) + if (current === this.rootDOMNode) foundRoot = true; var crumb = document.createElement("span"); @@ -962,7 +684,7 @@ WebInspector.ElementsPanel.prototype = { if (foundRoot) crumb.addStyleClass("dimmed"); - if (objectsAreSame(current, this.focusedDOMNode)) + if (current === this.focusedDOMNode) crumb.addStyleClass("selected"); if (!crumbs.childNodes.length) crumb.addStyleClass("end"); @@ -1269,7 +991,8 @@ WebInspector.ElementsPanel.prototype = { switch (this.focusedDOMNode.nodeType) { case Node.ELEMENT_NODE: - var data = this.focusedDOMNode.outerHTML; + // TODO: Introduce InspectorController.copyEvent that pushes appropriate markup into the clipboard. + var data = null; break; case Node.COMMENT_NODE: @@ -1316,10 +1039,7 @@ WebInspector.ElementsPanel.prototype = { { InspectorController.toggleNodeSearch(); - if (InspectorController.searchingForNode()) - this.nodeSearchButton.addStyleClass("toggled-on"); - else - this.nodeSearchButton.removeStyleClass("toggled-on"); + this.nodeSearchButton.toggled = InspectorController.searchingForNode(); } } diff --git a/WebCore/inspector/front-end/ElementsTreeOutline.js b/WebCore/inspector/front-end/ElementsTreeOutline.js index ef53209..345a084 100644 --- a/WebCore/inspector/front-end/ElementsTreeOutline.js +++ b/WebCore/inspector/front-end/ElementsTreeOutline.js @@ -51,7 +51,7 @@ WebInspector.ElementsTreeOutline.prototype = { set rootDOMNode(x) { - if (objectsAreSame(this._rootDOMNode, x)) + if (this._rootDOMNode === x) return; this._rootDOMNode = x; @@ -66,7 +66,7 @@ WebInspector.ElementsTreeOutline.prototype = { set focusedDOMNode(x) { - if (objectsAreSame(this._focusedDOMNode, x)) { + if (this._focusedDOMNode === x) { this.revealAndSelectNode(x); return; } @@ -79,11 +79,11 @@ WebInspector.ElementsTreeOutline.prototype = { // and the select() call would change the focusedDOMNode and reenter this setter. So to // avoid calling focusedNodeChanged() twice, first check if _focusedDOMNode is the same // node as the one passed in. - if (objectsAreSame(this._focusedDOMNode, x)) { + if (this._focusedDOMNode === x) { this.focusedNodeChanged(); if (x && !this.suppressSelectHighlight) { - InspectorController.highlightDOMNode(x); + InspectorController.highlightDOMNode(x.id); if ("_restorePreviousHighlightNodeTimeout" in this) clearTimeout(this._restorePreviousHighlightNodeTimeout); @@ -92,7 +92,7 @@ WebInspector.ElementsTreeOutline.prototype = { { var hoveredNode = WebInspector.hoveredDOMNode; if (hoveredNode) - InspectorController.highlightDOMNode(hoveredNode); + InspectorController.highlightDOMNode(hoveredNode.id); else InspectorController.hideDOMNodeHighlight(); } @@ -138,19 +138,17 @@ WebInspector.ElementsTreeOutline.prototype = { focusedNodeChanged: function(forceUpdate) {}, - findTreeElement: function(node, isAncestor, getParent, equal) + findTreeElement: function(node, isAncestor, getParent) { if (typeof isAncestor === "undefined") isAncestor = isAncestorIncludingParentFrames; if (typeof getParent === "undefined") getParent = parentNodeOrFrameElement; - if (typeof equal === "undefined") - equal = objectsAreSame; - var treeElement = TreeOutline.prototype.findTreeElement.call(this, node, isAncestor, getParent, equal); + var treeElement = TreeOutline.prototype.findTreeElement.call(this, node, isAncestor, getParent); if (!treeElement && node.nodeType === Node.TEXT_NODE) { // The text node might have been inlined if it was short, so try to find the parent element. - treeElement = TreeOutline.prototype.findTreeElement.call(this, node.parentNode, isAncestor, getParent, equal); + treeElement = TreeOutline.prototype.findTreeElement.call(this, node.parentNode, isAncestor, getParent); } return treeElement; @@ -248,7 +246,7 @@ WebInspector.ElementsTreeOutline.prototype.__proto__ = TreeOutline.prototype; WebInspector.ElementsTreeElement = function(node) { - var hasChildren = node.contentDocument || (Preferences.ignoreWhitespace ? (firstChildSkippingWhitespace.call(node) ? true : false) : node.hasChildNodes()); + var hasChildren = Preferences.ignoreWhitespace ? (firstChildSkippingWhitespace.call(node) ? true : false) : node.hasChildNodes(); var titleInfo = nodeTitleInfo.call(node, hasChildren, WebInspector.linkifyURL); if (titleInfo.hasChildren) @@ -387,9 +385,14 @@ WebInspector.ElementsTreeElement.prototype = { this.updateChildren(); }, - + updateChildren: function(fullRefresh) { + WebInspector.domAgent.getChildNodesAsync(this.representedObject, this._updateChildren.bind(this, fullRefresh)); + }, + + _updateChildren: function(fullRefresh) + { if (fullRefresh) { var selectedTreeElement = this.treeOutline.selectedTreeElement; if (selectedTreeElement && selectedTreeElement.hasAncestor(this)) @@ -406,11 +409,11 @@ WebInspector.ElementsTreeElement.prototype = { var child = (Preferences.ignoreWhitespace ? firstChildSkippingWhitespace.call(node) : node.firstChild); while (child) { var currentTreeElement = treeElement.children[treeChildIndex]; - if (!currentTreeElement || !objectsAreSame(currentTreeElement.representedObject, child)) { + if (!currentTreeElement || currentTreeElement.representedObject !== child) { // Find any existing element that is later in the children list. var existingTreeElement = null; for (var i = (treeChildIndex + 1); i < treeElement.children.length; ++i) { - if (objectsAreSame(treeElement.children[i].representedObject, child)) { + if (treeElement.children[i].representedObject === child) { existingTreeElement = treeElement.children[i]; break; } @@ -445,9 +448,7 @@ WebInspector.ElementsTreeElement.prototype = { var currentNode = currentChild.representedObject; var currentParentNode = currentNode.parentNode; - if (objectsAreSame(currentParentNode, this.representedObject)) - continue; - if (this.representedObject.contentDocument && objectsAreSame(currentParentNode, this.representedObject.contentDocument)) + if (currentParentNode === this.representedObject) continue; var selectedTreeElement = this.treeOutline.selectedTreeElement; @@ -455,13 +456,8 @@ WebInspector.ElementsTreeElement.prototype = { this.select(); this.removeChildAtIndex(i); - - if (this.treeOutline.panel && currentNode.contentDocument) - this.treeOutline.panel.unregisterMutationEventListeners(currentNode.contentDocument.defaultView); } - if (this.representedObject.contentDocument) - updateChildrenOfNode(this.representedObject.contentDocument); updateChildrenOfNode(this.representedObject); var lastChild = this.children[this.children.length - 1]; @@ -477,9 +473,6 @@ WebInspector.ElementsTreeElement.prototype = { onexpand: function() { this.treeOutline.updateSelection(); - - if (this.treeOutline.panel && this.representedObject.contentDocument) - this.treeOutline.panel.registerMutationEventListeners(this.representedObject.contentDocument.defaultView); }, oncollapse: function() @@ -693,7 +686,7 @@ WebInspector.ElementsTreeElement.prototype = { } if (!parseElement.hasAttributes()) { - InspectorController.inspectedWindow().Element.prototype.removeAttribute.call(this.representedObject, attributeName); + this.representedObject.removeAttribute(attributeName); this._updateTitle(); moveToNextAttributeIfNeeded.call(this); return; @@ -704,12 +697,12 @@ WebInspector.ElementsTreeElement.prototype = { var attr = parseElement.attributes[i]; foundOriginalAttribute = foundOriginalAttribute || attr.name === attributeName; try { - InspectorController.inspectedWindow().Element.prototype.setAttribute.call(this.representedObject, attr.name, attr.value); + this.representedObject.setAttribute(attr.name, attr.value); } catch(e) {} // ignore invalid attribute (innerHTML doesn't throw errors, but this can) } if (!foundOriginalAttribute) - InspectorController.inspectedWindow().Element.prototype.removeAttribute.call(this.representedObject, attributeName); + this.representedObject.removeAttribute(attributeName); this._updateTitle(); diff --git a/WebCore/inspector/front-end/Images/cookie.png b/WebCore/inspector/front-end/Images/cookie.png Binary files differnew file mode 100644 index 0000000..386d52b --- /dev/null +++ b/WebCore/inspector/front-end/Images/cookie.png diff --git a/WebCore/inspector/front-end/InjectedScript.js b/WebCore/inspector/front-end/InjectedScript.js index 4611b48..4144826 100644 --- a/WebCore/inspector/front-end/InjectedScript.js +++ b/WebCore/inspector/front-end/InjectedScript.js @@ -27,12 +27,20 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -var InjectedScript = { - _styles: {}, - _styleRules: {}, - _lastStyleId: 0, - _lastStyleRuleId: 0 -}; +var InjectedScript = {}; + +// Called from within InspectorController on the 'inspected page' side. +InjectedScript.reset = function() +{ + InjectedScript._styles = {}; + InjectedScript._styleRules = {}; + InjectedScript._lastStyleId = 0; + InjectedScript._lastStyleRuleId = 0; + InjectedScript._searchResults = []; + InjectedScript._includedInSearchResultsPropertyName = "__includedInInspectorSearchResults"; +} + +InjectedScript.reset(); InjectedScript.getStyles = function(nodeId, authorOnly) { @@ -174,12 +182,14 @@ InjectedScript.toggleStyleEnabled = function(styleId, propertyName, disabled) return InjectedScript._serializeStyle(style, true); } -InjectedScript.applyStyleRuleText = function(ruleId, newContent, selectedNode) +InjectedScript.applyStyleRuleText = function(ruleId, newContent, selectedNodeId) { var rule = InjectedScript._styleRules[ruleId]; if (!rule) return false; + var selectedNode = InjectedScript._nodeForId(selectedNodeId); + try { var stylesheet = rule.parentStyleSheet; stylesheet.addRule(newContent); @@ -194,20 +204,14 @@ InjectedScript.applyStyleRuleText = function(ruleId, newContent, selectedNode) } } - var nodes = selectedNode.ownerDocument.querySelectorAll(newContent); - for (var i = 0; i < nodes.length; ++i) { - if (nodes[i] === selectedNode) { - return [InjectedScript._serializeRule(newRule), true]; - } - } - return [InjectedScript._serializeRule(newRule), false]; + return [InjectedScript._serializeRule(newRule), InjectedScript._doesSelectorAffectNode(newContent, selectedNode)]; } catch(e) { // Report invalid syntax. return false; } } -InjectedScript.addStyleSelector = function(newContent) +InjectedScript.addStyleSelector = function(newContent, selectedNodeId) { var stylesheet = InjectedScript.stylesheet; if (!stylesheet) { @@ -227,10 +231,28 @@ InjectedScript.addStyleSelector = function(newContent) return false; } - return InjectedScript._serializeRule(stylesheet.cssRules[stylesheet.cssRules.length - 1]); + var selectedNode = InjectedScript._nodeForId(selectedNodeId); + var rule = stylesheet.cssRules[stylesheet.cssRules.length - 1]; + rule.__isViaInspector = true; + + return [ InjectedScript._serializeRule(rule), InjectedScript._doesSelectorAffectNode(newContent, selectedNode) ]; +} + +InjectedScript._doesSelectorAffectNode = function(selectorText, node) +{ + if (!node) + return false; + var nodes = node.ownerDocument.querySelectorAll(selectorText); + for (var i = 0; i < nodes.length; ++i) { + if (nodes[i] === node) { + return true; + } + } + return false; } -InjectedScript.setStyleProperty = function(styleId, name, value) { +InjectedScript.setStyleProperty = function(styleId, name, value) +{ var style = InjectedScript._styles[styleId]; if (!style) return false; @@ -251,17 +273,18 @@ InjectedScript._serializeRule = function(rule) } ruleValue.isUserAgent = parentStyleSheet && !parentStyleSheet.ownerNode && !parentStyleSheet.href; ruleValue.isUser = parentStyleSheet && parentStyleSheet.ownerNode && parentStyleSheet.ownerNode.nodeName == "#document"; + ruleValue.isViaInspector = !!rule.__isViaInspector; // Bind editable scripts only. var doBind = !ruleValue.isUserAgent && !ruleValue.isUser; ruleValue.style = InjectedScript._serializeStyle(rule.style, doBind); if (doBind) { - if (!rule._id) { - rule._id = InjectedScript._lastStyleRuleId++; - InjectedScript._styleRules[rule._id] = rule; + if (!rule.id) { + rule.id = InjectedScript._lastStyleRuleId++; + InjectedScript._styleRules[rule.id] = rule; } - ruleValue.id = rule._id; + ruleValue.id = rule.id; } return ruleValue; } @@ -295,11 +318,11 @@ InjectedScript._serializeStyle = function(style, doBind) result.uniqueStyleProperties = InjectedScript._getUniqueStyleProperties(style); if (doBind) { - if (!style._id) { - style._id = InjectedScript._lastStyleId++; - InjectedScript._styles[style._id] = style; + if (!style.id) { + style.id = InjectedScript._lastStyleId++; + InjectedScript._styles[style.id] = style; } - result.id = style._id; + result.id = style.id; } return result; } @@ -405,6 +428,7 @@ InjectedScript.getProperties = function(objectProxy, ignoreHasOwnProperty) return false; var properties = []; + // Go over properties, prepare results. for (var propertyName in object) { if (!ignoreHasOwnProperty && "hasOwnProperty" in object && !object.hasOwnProperty(propertyName)) @@ -415,29 +439,31 @@ InjectedScript.getProperties = function(objectProxy, ignoreHasOwnProperty) continue; var property = {}; property.name = propertyName; + property.parentObjectProxy = objectProxy; var isGetter = object["__lookupGetter__"] && object.__lookupGetter__(propertyName); if (!property.isGetter) { var childObject = object[propertyName]; - property.type = typeof childObject; - property.textContent = Object.describe(childObject, true); - property.parentObjectProxy = objectProxy; - var parentPath = objectProxy.path.slice(); - property.childObjectProxy = { - objectId : objectProxy.objectId, - path : parentPath.splice(parentPath.length, 0, propertyName), - protoDepth : objectProxy.protoDepth - }; - if (childObject && (property.type === "object" || property.type === "function")) { + var childObjectProxy = {}; + childObjectProxy.objectId = objectProxy.objectId; + childObjectProxy.path = objectProxy.path ? objectProxy.path.slice() : []; + childObjectProxy.path.push(propertyName); + + childObjectProxy.protoDepth = objectProxy.protoDepth || 0; + childObjectProxy.description = Object.describe(childObject, true); + property.value = childObjectProxy; + + var type = typeof childObject; + if (type === "object" || type === "function") { for (var subPropertyName in childObject) { if (propertyName === "__treeElementIdentifier") continue; - property.hasChildren = true; + childObjectProxy.hasChildren = true; break; } } } else { // FIXME: this should show something like "getter" (bug 16734). - property.textContent = "\u2014"; // em dash + property.value = { description: "\u2014" }; // em dash property.isGetter = true; } properties.push(property); @@ -479,6 +505,338 @@ InjectedScript.setPropertyValue = function(objectProxy, propertyName, expression } } +InjectedScript.evaluate = function(expression) +{ + InjectedScript._ensureCommandLineAPIInstalled(); + // Surround the expression in with statements to inject our command line API so that + // the window object properties still take more precedent than our API functions. + expression = "with (window._inspectorCommandLineAPI) { with (window) { " + expression + " } }"; + + var result = {}; + try { + var value = InjectedScript._window().eval(expression); + var wrapper = InspectorController.wrapObject(value); + if (typeof wrapper === "object" && wrapper.exception) + result.exception = wrapper.exception; + else + result.value = wrapper; + } catch (e) { + result.exception = e.toString(); + } + return result; +} + +InjectedScript.addInspectedNode = function(nodeId) +{ + var node = InjectedScript._nodeForId(nodeId); + if (!node) + return false; + + InjectedScript._ensureCommandLineAPIInstalled(); + var inspectedNodes = InjectedScript._window()._inspectorCommandLineAPI._inspectedNodes; + inspectedNodes.unshift(node); + if (inspectedNodes.length >= 5) + inspectedNodes.pop(); + return true; +} + +InjectedScript.performSearch = function(whitespaceTrimmedQuery, searchResultsProperty) +{ + var tagNameQuery = whitespaceTrimmedQuery; + var attributeNameQuery = whitespaceTrimmedQuery; + var startTagFound = (tagNameQuery.indexOf("<") === 0); + var endTagFound = (tagNameQuery.lastIndexOf(">") === (tagNameQuery.length - 1)); + + if (startTagFound || endTagFound) { + var tagNameQueryLength = tagNameQuery.length; + tagNameQuery = tagNameQuery.substring((startTagFound ? 1 : 0), (endTagFound ? (tagNameQueryLength - 1) : tagNameQueryLength)); + } + + // Check the tagNameQuery is it is a possibly valid tag name. + if (!/^[a-zA-Z0-9\-_:]+$/.test(tagNameQuery)) + tagNameQuery = null; + + // Check the attributeNameQuery is it is a possibly valid tag name. + if (!/^[a-zA-Z0-9\-_:]+$/.test(attributeNameQuery)) + attributeNameQuery = null; + + const escapedQuery = whitespaceTrimmedQuery.escapeCharacters("'"); + const escapedTagNameQuery = (tagNameQuery ? tagNameQuery.escapeCharacters("'") : null); + const escapedWhitespaceTrimmedQuery = whitespaceTrimmedQuery.escapeCharacters("'"); + const searchResultsProperty = InjectedScript._includedInSearchResultsPropertyName; + + function addNodesToResults(nodes, length, getItem) + { + if (!length) + return; + + var nodeIds = []; + for (var i = 0; i < length; ++i) { + var node = getItem.call(nodes, i); + // Skip this node if it already has the property. + if (searchResultsProperty in node) + continue; + + if (!InjectedScript._searchResults.length) { + InjectedScript._currentSearchResultIndex = 0; + } + + node[searchResultsProperty] = true; + InjectedScript._searchResults.push(node); + var nodeId = InspectorController.pushNodePathToFrontend(node, false); + nodeIds.push(nodeId); + } + InspectorController.addNodesToSearchResult(nodeIds.join(",")); + } + + function matchExactItems(doc) + { + matchExactId.call(this, doc); + matchExactClassNames.call(this, doc); + matchExactTagNames.call(this, doc); + matchExactAttributeNames.call(this, doc); + } + + function matchExactId(doc) + { + const result = doc.__proto__.getElementById.call(doc, whitespaceTrimmedQuery); + addNodesToResults.call(this, result, (result ? 1 : 0), function() { return this }); + } + + function matchExactClassNames(doc) + { + const result = doc.__proto__.getElementsByClassName.call(doc, whitespaceTrimmedQuery); + addNodesToResults.call(this, result, result.length, result.item); + } + + function matchExactTagNames(doc) + { + if (!tagNameQuery) + return; + const result = doc.__proto__.getElementsByTagName.call(doc, tagNameQuery); + addNodesToResults.call(this, result, result.length, result.item); + } + + function matchExactAttributeNames(doc) + { + if (!attributeNameQuery) + return; + const result = doc.__proto__.querySelectorAll.call(doc, "[" + attributeNameQuery + "]"); + addNodesToResults.call(this, result, result.length, result.item); + } + + function matchPartialTagNames(doc) + { + if (!tagNameQuery) + return; + const result = doc.__proto__.evaluate.call(doc, "//*[contains(name(), '" + escapedTagNameQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); + addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); + } + + function matchStartOfTagNames(doc) + { + if (!tagNameQuery) + return; + const result = doc.__proto__.evaluate.call(doc, "//*[starts-with(name(), '" + escapedTagNameQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); + addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); + } + + function matchPartialTagNamesAndAttributeValues(doc) + { + if (!tagNameQuery) { + matchPartialAttributeValues.call(this, doc); + return; + } + + const result = doc.__proto__.evaluate.call(doc, "//*[contains(name(), '" + escapedTagNameQuery + "') or contains(@*, '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); + addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); + } + + function matchPartialAttributeValues(doc) + { + const result = doc.__proto__.evaluate.call(doc, "//*[contains(@*, '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); + addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); + } + + function matchStyleSelector(doc) + { + const result = doc.__proto__.querySelectorAll.call(doc, whitespaceTrimmedQuery); + addNodesToResults.call(this, result, result.length, result.item); + } + + function matchPlainText(doc) + { + const result = doc.__proto__.evaluate.call(doc, "//text()[contains(., '" + escapedQuery + "')] | //comment()[contains(., '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); + addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); + } + + function matchXPathQuery(doc) + { + const result = doc.__proto__.evaluate.call(doc, whitespaceTrimmedQuery, doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); + addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); + } + + function finishedSearching() + { + // Remove the searchResultsProperty now that the search is finished. + for (var i = 0; i < InjectedScript._searchResults.length; ++i) + delete InjectedScript._searchResults[i][searchResultsProperty]; + } + + const mainFrameDocument = InjectedScript._window().document; + const searchDocuments = [mainFrameDocument]; + var searchFunctions; + if (tagNameQuery && startTagFound && endTagFound) + searchFunctions = [matchExactTagNames, matchPlainText]; + else if (tagNameQuery && startTagFound) + searchFunctions = [matchStartOfTagNames, matchPlainText]; + else if (tagNameQuery && endTagFound) { + // FIXME: we should have a matchEndOfTagNames search function if endTagFound is true but not startTagFound. + // This requires ends-with() support in XPath, WebKit only supports starts-with() and contains(). + searchFunctions = [matchPartialTagNames, matchPlainText]; + } else if (whitespaceTrimmedQuery === "//*" || whitespaceTrimmedQuery === "*") { + // These queries will match every node. Matching everything isn't useful and can be slow for large pages, + // so limit the search functions list to plain text and attribute matching. + searchFunctions = [matchPartialAttributeValues, matchPlainText]; + } else + searchFunctions = [matchExactItems, matchStyleSelector, matchPartialTagNamesAndAttributeValues, matchPlainText, matchXPathQuery]; + + // Find all frames, iframes and object elements to search their documents. + const querySelectorAllFunction = InjectedScript._window().Document.prototype.querySelectorAll; + const subdocumentResult = querySelectorAllFunction.call(mainFrameDocument, "iframe, frame, object"); + + for (var i = 0; i < subdocumentResult.length; ++i) { + var element = subdocumentResult.item(i); + if (element.contentDocument) + searchDocuments.push(element.contentDocument); + } + + const panel = InjectedScript; + var documentIndex = 0; + var searchFunctionIndex = 0; + var chunkIntervalIdentifier = null; + + // Split up the work into chunks so we don't block the UI thread while processing. + + function processChunk() + { + var searchDocument = searchDocuments[documentIndex]; + var searchFunction = searchFunctions[searchFunctionIndex]; + + if (++searchFunctionIndex > searchFunctions.length) { + searchFunction = searchFunctions[0]; + searchFunctionIndex = 0; + + if (++documentIndex > searchDocuments.length) { + if (panel._currentSearchChunkIntervalIdentifier === chunkIntervalIdentifier) + delete panel._currentSearchChunkIntervalIdentifier; + clearInterval(chunkIntervalIdentifier); + finishedSearching.call(panel); + return; + } + + searchDocument = searchDocuments[documentIndex]; + } + + if (!searchDocument || !searchFunction) + return; + + try { + searchFunction.call(panel, searchDocument); + } catch(err) { + // ignore any exceptions. the query might be malformed, but we allow that. + } + } + + processChunk(); + + chunkIntervalIdentifier = setInterval(processChunk, 25); + InjectedScript._currentSearchChunkIntervalIdentifier = chunkIntervalIdentifier; + return true; +} + +InjectedScript.searchCanceled = function() +{ + if (InjectedScript._searchResults) { + const searchResultsProperty = InjectedScript._includedInSearchResultsPropertyName; + for (var i = 0; i < this._searchResults.length; ++i) { + var node = this._searchResults[i]; + + // Remove the searchResultsProperty since there might be an unfinished search. + delete node[searchResultsProperty]; + } + } + + if (InjectedScript._currentSearchChunkIntervalIdentifier) { + clearInterval(InjectedScript._currentSearchChunkIntervalIdentifier); + delete InjectedScript._currentSearchChunkIntervalIdentifier; + } + InjectedScript._searchResults = []; + return true; +} + +InjectedScript.getCookies = function() +{ + return InjectedScript._window().document.cookie; +} + +InjectedScript._ensureCommandLineAPIInstalled = function(inspectedWindow) +{ + var inspectedWindow = InjectedScript._window(); + if (inspectedWindow._inspectorCommandLineAPI) + return; + + inspectedWindow.eval("window._inspectorCommandLineAPI = { \ + $: function() { return document.getElementById.apply(document, arguments) }, \ + $$: function() { return document.querySelectorAll.apply(document, arguments) }, \ + $x: function(xpath, context) { \ + var nodes = []; \ + try { \ + var doc = context || document; \ + var results = doc.evaluate(xpath, doc, null, XPathResult.ANY_TYPE, null); \ + var node; \ + while (node = results.iterateNext()) nodes.push(node); \ + } catch (e) {} \ + return nodes; \ + }, \ + dir: function() { return console.dir.apply(console, arguments) }, \ + dirxml: function() { return console.dirxml.apply(console, arguments) }, \ + keys: function(o) { var a = []; for (var k in o) a.push(k); return a; }, \ + values: function(o) { var a = []; for (var k in o) a.push(o[k]); return a; }, \ + profile: function() { return console.profile.apply(console, arguments) }, \ + profileEnd: function() { return console.profileEnd.apply(console, arguments) }, \ + _inspectedNodes: [], \ + get $0() { return _inspectorCommandLineAPI._inspectedNodes[0] }, \ + get $1() { return _inspectorCommandLineAPI._inspectedNodes[1] }, \ + get $2() { return _inspectorCommandLineAPI._inspectedNodes[2] }, \ + get $3() { return _inspectorCommandLineAPI._inspectedNodes[3] }, \ + get $4() { return _inspectorCommandLineAPI._inspectedNodes[4] } \ + };"); + + inspectedWindow._inspectorCommandLineAPI.clear = InspectorController.wrapCallback(InspectorController.clearMessages.bind(InspectorController, true)); + inspectedWindow._inspectorCommandLineAPI.inspect = InspectorController.wrapCallback(inspectObject.bind(this)); + + function inspectObject(o) + { + if (arguments.length === 0) + return; + + inspectedWindow.console.log(o); + if (Object.type(o, inspectedWindow) === "node") { + InspectorController.pushNodePathToFrontend(o, true); + } else { + switch (Object.describe(o)) { + case "Database": + InspectorController.selectDatabase(o); + break; + case "Storage": + InspectorController.selectDOMStorage(o); + break; + } + } + } +} + InjectedScript._resolveObject = function(objectProxy) { var object = InjectedScript._objectForId(objectProxy.objectId); @@ -486,11 +844,11 @@ InjectedScript._resolveObject = function(objectProxy) var protoDepth = objectProxy.protoDepth; // Follow the property path. - for (var i = 0; object && i < path.length; ++i) + for (var i = 0; object && path && i < path.length; ++i) object = object[path[i]]; // Get to the necessary proto layer. - for (var i = 0; object && i < protoDepth; ++i) + for (var i = 0; object && protoDepth && i < protoDepth; ++i) object = object.__proto__; return object; @@ -505,12 +863,34 @@ InjectedScript._window = function() InjectedScript._nodeForId = function(nodeId) { - // TODO: replace with node lookup in the InspectorDOMAgent once DOMAgent nodes are used. - return nodeId; + if (!nodeId) + return null; + return InspectorController.nodeForId(nodeId); } InjectedScript._objectForId = function(objectId) { - // TODO: replace with node lookups for node ids and evaluation result lookups for the rest of ids. + if (typeof objectId === "number") + return InjectedScript._nodeForId(objectId); + else if (typeof objectId === "string") + return InspectorController.unwrapObject(objectId); + + // TODO: move scope chain objects to proxy-based schema. return objectId; } + +// Called from within InspectorController on the 'inspected page' side. +InjectedScript.createProxyObject = function(object, objectId) +{ + var result = {}; + result.objectId = objectId; + result.type = Object.type(object, InjectedScript._window()); + if (result.type === "node") + result.nodeId = InspectorController.pushNodePathToFrontend(object, false); + try { + result.description = Object.describe(object, true, InjectedScript._window()); + } catch (e) { + result.exception = e.toString(); + } + return result; +} diff --git a/WebCore/inspector/front-end/ObjectPropertiesSection.js b/WebCore/inspector/front-end/ObjectPropertiesSection.js index 9b03940..f0b877d 100644 --- a/WebCore/inspector/front-end/ObjectPropertiesSection.js +++ b/WebCore/inspector/front-end/ObjectPropertiesSection.js @@ -124,13 +124,6 @@ WebInspector.ObjectPropertyTreeElement = function(property) } WebInspector.ObjectPropertyTreeElement.prototype = { - safePropertyValue: function(object, propertyName) - { - if (object["__lookupGetter__"] && object.__lookupGetter__(propertyName)) - return; - return object[propertyName]; - }, - onpopulate: function() { if (this.children.length && !this.shouldRefreshChildren) @@ -147,7 +140,7 @@ WebInspector.ObjectPropertyTreeElement.prototype = { self.appendChild(new self.treeOutline.section.treeElementConstructor(properties[i])); } }; - InspectorController.getProperties(this.property.childObjectProxy, false, callback); + InspectorController.getProperties(this.property.value, false, callback); }, ondblclick: function(element, event) @@ -168,7 +161,7 @@ WebInspector.ObjectPropertyTreeElement.prototype = { this.valueElement = document.createElement("span"); this.valueElement.className = "value"; - this.valueElement.textContent = this.property.textContent; + this.valueElement.textContent = this.property.value.description; if (this.property.isGetter) this.valueElement.addStyleClass("dimmed"); @@ -177,7 +170,7 @@ WebInspector.ObjectPropertyTreeElement.prototype = { this.listItemElement.appendChild(nameElement); this.listItemElement.appendChild(document.createTextNode(": ")); this.listItemElement.appendChild(this.valueElement); - this.hasChildren = this.property.hasChildren; + this.hasChildren = this.property.value.hasChildren; }, updateSiblings: function() diff --git a/WebCore/inspector/front-end/ObjectProxy.js b/WebCore/inspector/front-end/ObjectProxy.js index fa7816e..dbb9e48 100644 --- a/WebCore/inspector/front-end/ObjectProxy.js +++ b/WebCore/inspector/front-end/ObjectProxy.js @@ -28,18 +28,17 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -WebInspector.ObjectProxy = function(objectId, path, protoDepth) +WebInspector.ObjectProxy = function(objectId, path, protoDepth, description, hasChildren) { this.objectId = objectId; this.path = path || []; this.protoDepth = protoDepth || 0; + this.description = description; + this.hasChildren = hasChildren; } WebInspector.ObjectPropertyProxy = function(name, object) { this.name = name; - this.type = "object"; - this.hasChildren = true; - this.textContent = Object.describe(object, true); - this.childObjectProxy = new WebInspector.ObjectProxy(object); + this.value = new WebInspector.ObjectProxy(object, [], 0, Object.describe(object, true), true); } diff --git a/WebCore/inspector/front-end/Panel.js b/WebCore/inspector/front-end/Panel.js index 3e2212c..5046f6b 100644 --- a/WebCore/inspector/front-end/Panel.js +++ b/WebCore/inspector/front-end/Panel.js @@ -66,18 +66,6 @@ WebInspector.Panel.prototype = { return this._toolbarItem; }, - createStatusBarButton: function() - { - var button = document.createElement("button"); - var glyph = document.createElement("div"); - glyph.className = "glyph"; - button.appendChild(glyph); - var glyphShadow = document.createElement("div"); - glyphShadow.className = "glyph shadow"; - button.appendChild(glyphShadow); - return button; - }, - show: function() { WebInspector.View.prototype.show.call(this); diff --git a/WebCore/inspector/front-end/ProfileView.js b/WebCore/inspector/front-end/ProfileView.js index 2517bd2..5c9fcda 100644 --- a/WebCore/inspector/front-end/ProfileView.js +++ b/WebCore/inspector/front-end/ProfileView.js @@ -56,25 +56,19 @@ WebInspector.ProfileView = function(profile) this.viewSelectElement.appendChild(heavyViewOption); this.viewSelectElement.appendChild(treeViewOption); - this.percentButton = document.createElement("button"); - this.percentButton.className = "percent-time-status-bar-item status-bar-item"; + this.percentButton = new WebInspector.StatusBarButton("", "percent-time-status-bar-item"); this.percentButton.addEventListener("click", this._percentClicked.bind(this), false); - this.focusButton = document.createElement("button"); - this.focusButton.title = WebInspector.UIString("Focus selected function."); - this.focusButton.className = "focus-profile-node-status-bar-item status-bar-item"; + this.focusButton = new WebInspector.StatusBarButton(WebInspector.UIString("Focus selected function."), "focus-profile-node-status-bar-item"); this.focusButton.disabled = true; this.focusButton.addEventListener("click", this._focusClicked.bind(this), false); - this.excludeButton = document.createElement("button"); - this.excludeButton.title = WebInspector.UIString("Exclude selected function."); - this.excludeButton.className = "exclude-profile-node-status-bar-item status-bar-item"; + this.excludeButton = new WebInspector.StatusBarButton(WebInspector.UIString("Exclude selected function."), "exclude-profile-node-status-bar-item"); this.excludeButton.disabled = true; this.excludeButton.addEventListener("click", this._excludeClicked.bind(this), false); - this.resetButton = document.createElement("button"); - this.resetButton.title = WebInspector.UIString("Restore all functions."); - this.resetButton.className = "reset-profile-status-bar-item status-bar-item hidden"; + this.resetButton = new WebInspector.StatusBarButton(WebInspector.UIString("Restore all functions."), "reset-profile-status-bar-item"); + this.resetButton.visible = false; this.resetButton.addEventListener("click", this._resetClicked.bind(this), false); this.profile = profile; @@ -90,7 +84,7 @@ WebInspector.ProfileView = function(profile) WebInspector.ProfileView.prototype = { get statusBarItems() { - return [this.viewSelectElement, this.percentButton, this.focusButton, this.excludeButton, this.resetButton]; + return [this.viewSelectElement, this.percentButton.element, this.focusButton.element, this.excludeButton.element, this.resetButton.element]; }, get profile() @@ -439,10 +433,10 @@ WebInspector.ProfileView.prototype = { { if (this.showSelfTimeAsPercent && this.showTotalTimeAsPercent && this.showAverageTimeAsPercent) { this.percentButton.title = WebInspector.UIString("Show absolute total and self times."); - this.percentButton.addStyleClass("toggled-on"); + this.percentButton.toggled = true; } else { this.percentButton.title = WebInspector.UIString("Show total and self times as percentages."); - this.percentButton.removeStyleClass("toggled-on"); + this.percentButton.toggled = false; } }, @@ -451,7 +445,7 @@ WebInspector.ProfileView.prototype = { if (!this.dataGrid.selectedNode) return; - this.resetButton.removeStyleClass("hidden"); + this.resetButton.visible = true; this.profileDataGridTree.focus(this.dataGrid.selectedNode); this.refresh(); this.refreshVisibleData(); @@ -466,7 +460,7 @@ WebInspector.ProfileView.prototype = { selectedNode.deselect(); - this.resetButton.removeStyleClass("hidden"); + this.resetButton.visible = true; this.profileDataGridTree.exclude(selectedNode); this.refresh(); this.refreshVisibleData(); @@ -474,7 +468,7 @@ WebInspector.ProfileView.prototype = { _resetClicked: function(event) { - this.resetButton.addStyleClass("hidden"); + this.resetButton.visible = false; this.profileDataGridTree.restore(); this.refresh(); this.refreshVisibleData(); diff --git a/WebCore/inspector/front-end/ProfilesPanel.js b/WebCore/inspector/front-end/ProfilesPanel.js index c8b948a..e7ee064 100644 --- a/WebCore/inspector/front-end/ProfilesPanel.js +++ b/WebCore/inspector/front-end/ProfilesPanel.js @@ -59,14 +59,10 @@ WebInspector.ProfilesPanel = function() this.profileViews.id = "profile-views"; this.element.appendChild(this.profileViews); - this.enableToggleButton = this.createStatusBarButton(); - this.enableToggleButton.className = "enable-toggle-status-bar-item status-bar-item"; + this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item"); this.enableToggleButton.addEventListener("click", this._toggleProfiling.bind(this), false); - this.recordButton = this.createStatusBarButton(); - this.recordButton.title = WebInspector.UIString("Start profiling."); - this.recordButton.id = "record-profile-status-bar-item"; - this.recordButton.className = "status-bar-item"; + this.recordButton = new WebInspector.StatusBarButton(WebInspector.UIString("Start profiling."), "record-profile-status-bar-item"); this.recordButton.addEventListener("click", this._recordClicked.bind(this), false); this.recording = false; @@ -87,7 +83,7 @@ WebInspector.ProfilesPanel.prototype = { get statusBarItems() { - return [this.enableToggleButton, this.recordButton, this.profileViewStatusBarItemsContainer]; + return [this.enableToggleButton.element, this.recordButton.element, this.profileViewStatusBarItemsContainer]; }, show: function() @@ -317,10 +313,10 @@ WebInspector.ProfilesPanel.prototype = { this.recording = isProfiling; if (isProfiling) { - this.recordButton.addStyleClass("toggled-on"); + this.recordButton.toggled = true; this.recordButton.title = WebInspector.UIString("Stop profiling."); } else { - this.recordButton.removeStyleClass("toggled-on"); + this.recordButton.toggled = false; this.recordButton.title = WebInspector.UIString("Start profiling."); } }, @@ -336,14 +332,14 @@ WebInspector.ProfilesPanel.prototype = { { if (InspectorController.profilerEnabled()) { this.enableToggleButton.title = WebInspector.UIString("Profiling enabled. Click to disable."); - this.enableToggleButton.addStyleClass("toggled-on"); - this.recordButton.removeStyleClass("hidden"); + this.enableToggleButton.toggled = true; + this.recordButton.visible = true; this.profileViewStatusBarItemsContainer.removeStyleClass("hidden"); this.panelEnablerView.visible = false; } else { this.enableToggleButton.title = WebInspector.UIString("Profiling disabled. Click to enable."); - this.enableToggleButton.removeStyleClass("toggled-on"); - this.recordButton.addStyleClass("hidden"); + this.enableToggleButton.toggled = false; + this.recordButton.visible = false; this.profileViewStatusBarItemsContainer.addStyleClass("hidden"); this.panelEnablerView.visible = true; } diff --git a/WebCore/inspector/front-end/PropertiesSidebarPane.js b/WebCore/inspector/front-end/PropertiesSidebarPane.js index 2d32137..4e55761 100644 --- a/WebCore/inspector/front-end/PropertiesSidebarPane.js +++ b/WebCore/inspector/front-end/PropertiesSidebarPane.js @@ -32,7 +32,7 @@ WebInspector.PropertiesSidebarPane = function() } WebInspector.PropertiesSidebarPane.prototype = { - update: function(object) + update: function(node) { var body = this.bodyElement; @@ -40,7 +40,7 @@ WebInspector.PropertiesSidebarPane.prototype = { this.sections = []; - if (!object) + if (!node) return; var self = this; @@ -51,13 +51,13 @@ WebInspector.PropertiesSidebarPane.prototype = { // Get array of prototype user-friendly names. for (var i = 0; i < prototypes.length; ++i) { - var prototype = new WebInspector.ObjectProxy(object, [], i); + var prototype = new WebInspector.ObjectProxy(node.id, [], i); var section = new WebInspector.ObjectPropertiesSection(prototype, prototypes[i], WebInspector.UIString("Prototype")); self.sections.push(section); body.appendChild(section.element); } }; - InspectorController.getPrototypes(object, callback); + InspectorController.getPrototypes(node.id, callback); } } diff --git a/WebCore/inspector/front-end/ResourcesPanel.js b/WebCore/inspector/front-end/ResourcesPanel.js index fb43551..bb7faa6 100644 --- a/WebCore/inspector/front-end/ResourcesPanel.js +++ b/WebCore/inspector/front-end/ResourcesPanel.js @@ -139,14 +139,11 @@ WebInspector.ResourcesPanel = function() this.element.appendChild(this.panelEnablerView.element); - this.enableToggleButton = this.createStatusBarButton(); - this.enableToggleButton.className = "enable-toggle-status-bar-item status-bar-item"; + this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item"); this.enableToggleButton.addEventListener("click", this._toggleResourceTracking.bind(this), false); - this.largerResourcesButton = this.createStatusBarButton(); - this.largerResourcesButton.id = "resources-larger-resources-status-bar-item"; - this.largerResourcesButton.className = "status-bar-item toggled-on"; - this.largerResourcesButton.title = WebInspector.UIString("Use small resource rows."); + this.largerResourcesButton = new WebInspector.StatusBarButton(WebInspector.UIString("Use small resource rows."), "resources-larger-resources-status-bar-item"); + this.largerResourcesButton.toggled = true; this.largerResourcesButton.addEventListener("click", this._toggleLargerResources.bind(this), false); this.sortingSelectElement = document.createElement("select"); @@ -211,7 +208,7 @@ WebInspector.ResourcesPanel.prototype = { get statusBarItems() { - return [this.enableToggleButton, this.largerResourcesButton, this.sortingSelectElement]; + return [this.enableToggleButton.element, this.largerResourcesButton.element, this.sortingSelectElement]; }, show: function() @@ -467,14 +464,14 @@ WebInspector.ResourcesPanel.prototype = { if (InspectorController.resourceTrackingEnabled()) { this.enableToggleButton.title = WebInspector.UIString("Resource tracking enabled. Click to disable."); - this.enableToggleButton.addStyleClass("toggled-on"); - this.largerResourcesButton.removeStyleClass("hidden"); + this.enableToggleButton.toggled = true; + this.largerResourcesButton.visible = true; this.sortingSelectElement.removeStyleClass("hidden"); this.panelEnablerView.visible = false; } else { this.enableToggleButton.title = WebInspector.UIString("Resource tracking disabled. Click to enable."); - this.enableToggleButton.removeStyleClass("toggled-on"); - this.largerResourcesButton.addStyleClass("hidden"); + this.enableToggleButton.toggled = false; + this.largerResourcesButton.visible = false; this.sortingSelectElement.addStyleClass("hidden"); this.panelEnablerView.visible = true; } @@ -1076,12 +1073,12 @@ WebInspector.ResourcesPanel.prototype = { if (this.resourcesTreeElement.smallChildren) { this.resourcesGraphsElement.addStyleClass("small"); this.largerResourcesButton.title = WebInspector.UIString("Use large resource rows."); - this.largerResourcesButton.removeStyleClass("toggled-on"); + this.largerResourcesButton.toggled = false; this._adjustScrollPosition(); } else { this.resourcesGraphsElement.removeStyleClass("small"); this.largerResourcesButton.title = WebInspector.UIString("Use small resource rows."); - this.largerResourcesButton.addStyleClass("toggled-on"); + this.largerResourcesButton.toggled = true; } }, @@ -1546,6 +1543,11 @@ WebInspector.ResourceSidebarTreeElement.prototype = { // Do nothing. }, + get selectable() + { + return WebInspector.panels.resources._filterCategory == "all" || WebInspector.panels.resources._filterCategory == this.resource.category.name; + }, + createIconElement: function() { var previousIconElement = this.iconElement; diff --git a/WebCore/inspector/front-end/ScriptsPanel.js b/WebCore/inspector/front-end/ScriptsPanel.js index 0058374..a97d5cf 100644 --- a/WebCore/inspector/front-end/ScriptsPanel.js +++ b/WebCore/inspector/front-end/ScriptsPanel.js @@ -151,13 +151,10 @@ WebInspector.ScriptsPanel = function() this.element.appendChild(this.sidebarElement); this.element.appendChild(this.sidebarResizeElement); - this.enableToggleButton = this.createStatusBarButton(); - this.enableToggleButton.className = "enable-toggle-status-bar-item status-bar-item"; + this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item"); this.enableToggleButton.addEventListener("click", this._toggleDebugging.bind(this), false); - this.pauseOnExceptionButton = this.createStatusBarButton(); - this.pauseOnExceptionButton.id = "scripts-pause-on-exceptions-status-bar-item"; - this.pauseOnExceptionButton.className = "status-bar-item"; + this.pauseOnExceptionButton = new WebInspector.StatusBarButton("", "scripts-pause-on-exceptions-status-bar-item"); this.pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions.bind(this), false); this._breakpointsURLMap = {}; @@ -208,7 +205,7 @@ WebInspector.ScriptsPanel.prototype = { get statusBarItems() { - return [this.enableToggleButton, this.pauseOnExceptionButton]; + return [this.enableToggleButton.element, this.pauseOnExceptionButton.element]; }, get paused() @@ -377,13 +374,8 @@ WebInspector.ScriptsPanel.prototype = { var panel = this; function delayedEvaluation() { - if (!code) { - // Evaluate into properties in scope of the selected call frame. - callback(panel._variablesInScope(callFrame)); - return; - } try { - callback(callFrame.evaluate(code)); + callback(InspectorController.wrapObject(callFrame.evaluate(code))); } catch (e) { callback(e, true); } @@ -391,10 +383,14 @@ WebInspector.ScriptsPanel.prototype = { setTimeout(delayedEvaluation, 0); }, - _variablesInScope: function(callFrame) + variablesInSelectedCallFrame: function() { + var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame; + if (!this._paused || !selectedCallFrame) + return {}; + var result = {}; - var scopeChain = callFrame.scopeChain; + var scopeChain = selectedCallFrame.scopeChain; for (var i = 0; i < scopeChain.length; ++i) { var scopeObject = scopeChain[i]; for (var property in scopeObject) @@ -764,10 +760,10 @@ WebInspector.ScriptsPanel.prototype = { { if (InspectorController.pauseOnExceptions()) { this.pauseOnExceptionButton.title = WebInspector.UIString("Don't pause on exceptions."); - this.pauseOnExceptionButton.addStyleClass("toggled-on"); + this.pauseOnExceptionButton.toggled = true; } else { this.pauseOnExceptionButton.title = WebInspector.UIString("Pause on exceptions."); - this.pauseOnExceptionButton.removeStyleClass("toggled-on"); + this.pauseOnExceptionButton.toggled = false; } }, @@ -775,13 +771,13 @@ WebInspector.ScriptsPanel.prototype = { { if (InspectorController.debuggerEnabled()) { this.enableToggleButton.title = WebInspector.UIString("Debugging enabled. Click to disable."); - this.enableToggleButton.addStyleClass("toggled-on"); - this.pauseOnExceptionButton.removeStyleClass("hidden"); + this.enableToggleButton.toggled = true; + this.pauseOnExceptionButton.visible = true; this.panelEnablerView.visible = false; } else { this.enableToggleButton.title = WebInspector.UIString("Debugging disabled. Click to enable."); - this.enableToggleButton.removeStyleClass("toggled-on"); - this.pauseOnExceptionButton.addStyleClass("hidden"); + this.enableToggleButton.toggled = false; + this.pauseOnExceptionButton.visible = false; this.panelEnablerView.visible = true; } diff --git a/WebCore/inspector/front-end/SourceFrame.js b/WebCore/inspector/front-end/SourceFrame.js index 930eb16..9c0f7e0 100644 --- a/WebCore/inspector/front-end/SourceFrame.js +++ b/WebCore/inspector/front-end/SourceFrame.js @@ -289,8 +289,10 @@ WebInspector.SourceFrame.prototype = { return; var sourceRow = event.target.enclosingNodeOrSelfWithNodeName("tr"); - if (sourceRow._breakpointObject) - sourceRow._breakpointObject.enabled = !sourceRow._breakpointObject.enabled; + if (sourceRow._breakpointObject && sourceRow._breakpointObject.enabled) + sourceRow._breakpointObject.enabled = false; + else if (sourceRow._breakpointObject) + WebInspector.panels.scripts.removeBreakpoint(sourceRow._breakpointObject); else if (this.addBreakpointDelegate) this.addBreakpointDelegate(this.lineNumberForSourceRow(sourceRow)); }, diff --git a/WebCore/inspector/front-end/StatusBarButton.js b/WebCore/inspector/front-end/StatusBarButton.js new file mode 100644 index 0000000..5c69ed5 --- /dev/null +++ b/WebCore/inspector/front-end/StatusBarButton.js @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT + * OWNER 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. + */ + +WebInspector.StatusBarButton = function(title, className) +{ + this.element = document.createElement("button"); + this.element.className = className + " status-bar-item"; + this.element.addEventListener("click", this._clicked.bind(this), false); + + this.glyph = document.createElement("div"); + this.glyph.className = "glyph"; + this.element.appendChild(this.glyph); + + this.glyphShadow = document.createElement("div"); + this.glyphShadow.className = "glyph shadow"; + this.element.appendChild(this.glyphShadow); + + this.title = title; + this.disabled = false; + this._toggled = false; + this._visible = true; +} + +WebInspector.StatusBarButton.prototype = { + _clicked: function() + { + this.dispatchEventToListeners("click"); + }, + + get disabled() + { + return this._disabled; + }, + + set disabled(x) + { + if (this._disabled === x) + return; + this._disabled = x; + this.element.disabled = x; + }, + + get title() + { + return this._title; + }, + + set title(x) + { + if (this._title === x) + return; + this._title = x; + this.element.title = x; + }, + + get toggled() + { + return this._toggled; + }, + + set toggled(x) + { + if (this._toggled === x) + return; + + if (x) + this.element.addStyleClass("toggled-on"); + else + this.element.removeStyleClass("toggled-on"); + this._toggled = x; + }, + + get visible() + { + return this._visible; + }, + + set visible(x) + { + if (this._visible === x) + return; + + if (x) + this.element.removeStyleClass("hidden"); + else + this.element.addStyleClass("hidden"); + this._visible = x; + } +} + +WebInspector.StatusBarButton.prototype.__proto__ = WebInspector.Object.prototype; diff --git a/WebCore/inspector/front-end/StylesSidebarPane.js b/WebCore/inspector/front-end/StylesSidebarPane.js index 8a3a67f..db585e0 100644 --- a/WebCore/inspector/front-end/StylesSidebarPane.js +++ b/WebCore/inspector/front-end/StylesSidebarPane.js @@ -67,10 +67,10 @@ WebInspector.StylesSidebarPane.prototype = { var callback = function(styles) { if (!styles) return; - var nodeWrapper = WebInspector.wrapNodeWithStyles(node, styles); - self._update(refresh, body, nodeWrapper, editedSection, forceUpdate); + node._setStyles(styles.computedStyle, styles.inlineStyle, styles.styleAttributes, styles.matchedCSSRules); + self._update(refresh, body, node, editedSection, forceUpdate); }; - InspectorController.getStyles(node, !Preferences.showUserAgentStyles, callback); + InspectorController.getStyles(node.id, !Preferences.showUserAgentStyles, callback); }, _update: function(refresh, body, node, editedSection, forceUpdate) @@ -322,8 +322,9 @@ WebInspector.StylePropertiesSection = function(styleRule, subtitle, computedStyl this.editable = (editable && !computedStyle); // Prevent editing the user agent and user rules. - var isUserAgent = this.styleRule.isUserAgent; - var isUser = this.styleRule.isUser; + var isUserAgent = this.rule && this.rule.isUserAgent; + var isUser = this.rule && this.rule.isUser; + var isViaInspector = this.rule && this.rule.isViaInspector; if (isUserAgent || isUser) this.editable = false; @@ -366,7 +367,7 @@ WebInspector.StylePropertiesSection = function(styleRule, subtitle, computedStyl subtitle = WebInspector.UIString("user agent stylesheet"); else if (isUser) subtitle = WebInspector.UIString("user stylesheet"); - else if (this.styleRule.parentStyleSheet === WebInspector.panels.elements.stylesheet) + else if (isViaInspector) subtitle = WebInspector.UIString("via inspector"); else subtitle = WebInspector.UIString("inline stylesheet"); @@ -611,24 +612,12 @@ WebInspector.StylePropertiesSection.prototype = { moveToNextIfNeeded.call(self); }; - InspectorController.applyStyleRuleText(this.rule._id, newContent, this.pane.node, callback); + InspectorController.applyStyleRuleText(this.rule.id, newContent, this.pane.node.id, callback); }, editingSelectorCancelled: function(element, context) { element.textContent = context; - }, - - _doesSelectorAffectSelectedNode: function(selector) - { - var selectedNode = this.pane.node; - var nodes = selectedNode.ownerDocument.querySelectorAll(selector); - for (var i = 0; i < nodes.length; ++i) { - if (nodes[i] === selectedNode) - return true; - } - - return false; } } @@ -673,15 +662,17 @@ WebInspector.BlankStylePropertiesSection.prototype = { editingCommitted: function(element, newContent, oldContent, context) { var self = this; - var callback = function(styleRule) { - if (!styleRule) { + var callback = function(result) { + if (!result) { // Invalid Syntax for a Selector self.editingCancelled(); return; } + var styleRule = result[0]; + var doesSelectorAffectSelectedNode = result[1]; self.makeNormal(WebInspector.CSSStyleDeclaration.parseRule(styleRule)); - if (!self._doesSelectorAffectSelectedNode(newContent)) { + if (!doesSelectorAffectSelectedNode) { self.noAffect = true; self.element.addStyleClass("no-affect"); } @@ -692,7 +683,7 @@ WebInspector.BlankStylePropertiesSection.prototype = { self.pane.addBlankSection(); self.addNewBlankProperty().startEditing(); }; - InspectorController.addStyleSelector(newContent, callback); + InspectorController.addStyleSelector(newContent, this.pane.node.id, callback); }, makeNormal: function(styleRule) @@ -896,63 +887,70 @@ WebInspector.StylePropertyTreeElement.prototype = { // Simple: rgb -> hsl -> nickname? -> shorthex? -> hex -> ... // Advanced: rgba -> hsla -> nickname? -> ... if (colors && colors.length === 1) { - var color = new WebInspector.Color(htmlValue); - swatch.addEventListener("click", changeColorDisplay, false); - swatch.addEventListener("dblclick", function(event) { - event.stopPropagation(); - }, false); - - var mode = color.mode; - var valueElement = this.valueElement; - function changeColorDisplay(event) { - - function changeTo(newMode, content) { - mode = newMode; - valueElement.textContent = content; - } + try { + var color = new WebInspector.Color(htmlValue); + } catch(e) { + var color = null; + } + + if (color) { + swatch.addEventListener("click", changeColorDisplay, false); + swatch.addEventListener("dblclick", function(event) { + event.stopPropagation(); + }, false); - switch (mode) { - case "rgb": - changeTo("hsl", color.toHsl()); - break; + var mode = color.mode; + var valueElement = this.valueElement; + function changeColorDisplay(event) { - case "shorthex": - changeTo("hex", color.toHex()); - break; + function changeTo(newMode, content) { + mode = newMode; + valueElement.textContent = content; + } - case "hex": - changeTo("rgb", color.toRgb()); - break; + switch (mode) { + case "rgb": + changeTo("hsl", color.toHsl()); + break; - case "nickname": - if (color.simple) { - if (color.hasShortHex()) + case "shorthex": + changeTo("hex", color.toHex()); + break; + + case "hex": + changeTo("rgb", color.toRgb()); + break; + + case "nickname": + if (color.simple) { + if (color.hasShortHex()) + changeTo("shorthex", color.toShortHex()); + else + changeTo("hex", color.toHex()); + } else + changeTo("rgba", color.toRgba()); + break; + + case "hsl": + if (color.nickname) + changeTo("nickname", color.toNickname()); + else if (color.hasShortHex()) changeTo("shorthex", color.toShortHex()); else changeTo("hex", color.toHex()); - } else - changeTo("rgba", color.toRgba()); - break; - - case "hsl": - if (color.nickname) - changeTo("nickname", color.toNickname()); - else if (color.hasShortHex()) - changeTo("shorthex", color.toShortHex()); - else - changeTo("hex", color.toHex()); - break; - - case "rgba": - changeTo("hsla", color.toHsla()); - break; - - case "hsla": - if (color.nickname) - changeTo("nickname", color.toNickname()); - else - changeTo("rgba", color.toRgba()); - break; + break; + + case "rgba": + changeTo("hsla", color.toHsla()); + break; + + case "hsla": + if (color.nickname) + changeTo("nickname", color.toNickname()); + else + changeTo("rgba", color.toRgba()); + break; + } } } } @@ -992,7 +990,7 @@ WebInspector.StylePropertyTreeElement.prototype = { self.updateAll(true); }; - InspectorController.toggleStyleEnabled(this.style._id, this.name, disabled, callback); + InspectorController.toggleStyleEnabled(this.style.id, this.name, disabled, callback); }, updateState: function() @@ -1155,7 +1153,7 @@ WebInspector.StylePropertyTreeElement.prototype = { } else { // Restore the original CSS text before applying user changes. This is needed to prevent // new properties from sticking around if the user adds one, then removes it. - InspectorController.setStyleText(this.style, this.originalCSSText); + InspectorController.setStyleText(this.style.id, this.originalCSSText); } this.applyStyleText(this.listItemElement.textContent); @@ -1175,7 +1173,7 @@ WebInspector.StylePropertyTreeElement.prototype = { if (this._newProperty) this.treeOutline.removeChild(this); else if (this.originalCSSText) { - InspectorController.setStyleText(this.style, this.originalCSSText); + InspectorController.setStyleText(this.style.id, this.originalCSSText); if (this.treeOutline.section && this.treeOutline.section.pane) this.treeOutline.section.pane.dispatchEventToListeners("style edited"); @@ -1294,7 +1292,7 @@ WebInspector.StylePropertyTreeElement.prototype = { if (!self.rule) WebInspector.panels.elements.treeOutline.update(); }; - InspectorController.applyStyleText(this.style._id, styleText.trimWhitespace(), this.name, callback); + InspectorController.applyStyleText(this.style.id, styleText.trimWhitespace(), this.name, callback); } } diff --git a/WebCore/inspector/front-end/WebKit.qrc b/WebCore/inspector/front-end/WebKit.qrc index c39c95b..c82de61 100644 --- a/WebCore/inspector/front-end/WebKit.qrc +++ b/WebCore/inspector/front-end/WebKit.qrc @@ -9,6 +9,7 @@ <file>ChangesView.js</file> <file>Color.js</file> <file>ConsoleView.js</file> + <file>CookieItemsView.js</file> <file>Database.js</file> <file>DatabaseQueryView.js</file> <file>DatabasesPanel.js</file> @@ -50,6 +51,7 @@ <file>SidebarTreeElement.js</file> <file>SourceFrame.js</file> <file>SourceView.js</file> + <file>StatusBarButton.js</file> <file>StylesSidebarPane.js</file> <file>TextPrompt.js</file> <file>TopDownProfileDataGridTree.js</file> @@ -62,6 +64,7 @@ <file>Images/clearConsoleButtonGlyph.png</file> <file>Images/closeButtons.png</file> <file>Images/consoleButtonGlyph.png</file> + <file>Images/cookie.png</file> <file>Images/database.png</file> <file>Images/databasesIcon.png</file> <file>Images/databaseTable.png</file> diff --git a/WebCore/inspector/front-end/inspector.css b/WebCore/inspector/front-end/inspector.css index 51d626a..3292d8d 100644 --- a/WebCore/inspector/front-end/inspector.css +++ b/WebCore/inspector/front-end/inspector.css @@ -1626,6 +1626,10 @@ body.inactive .sidebar { content: url(Images/domStorage.png); } +.cookie-sidebar-tree-item .icon { + content: url(Images/cookie.png); +} + #storage-views { position: absolute; top: 0; @@ -1785,6 +1789,14 @@ body.inactive .sidebar { overflow: hidden; } +.data-grid .centered div { + text-align: center; +} + +.data-grid .right div { + text-align: right; +} + .data-grid th.sortable div { position: relative; } @@ -2091,7 +2103,7 @@ button.enable-toggle-status-bar-item.toggled-on .glyph { -webkit-mask-image: url(Images/enableSolidButtonGlyph.png); } -#scripts-pause-on-exceptions-status-bar-item .glyph { +.scripts-pause-on-exceptions-status-bar-item .glyph { -webkit-mask-image: url(Images/pauseOnExceptionButtonGlyph.png); } @@ -2209,7 +2221,7 @@ button.enable-toggle-status-bar-item.toggled-on .glyph { overflow: auto; } -#resources-larger-resources-status-bar-item .glyph { +.resources-larger-resources-status-bar-item .glyph { -webkit-mask-image: url(Images/largerResourcesButtonGlyph.png); } @@ -3093,16 +3105,16 @@ body.inactive .sidebar-tree-item.selected .bubble.search-matches { button.enable-toggle-status-bar-item .glyph { } -#record-profile-status-bar-item .glyph { +.record-profile-status-bar-item .glyph { -webkit-mask-image: url(Images/recordButtonGlyph.png); } -#record-profile-status-bar-item.toggled-on .glyph { +.record-profile-status-bar-item.toggled-on .glyph { -webkit-mask-image: url(Images/recordToggledButtonGlyph.png); - background-color: rgb(216, 0, 0); + background-color: rgb(216, 0, 0) !important; } -#node-search-status-bar-item .glyph { +.node-search-status-bar-item .glyph { -webkit-mask-image: url(Images/nodeSearchButtonGlyph.png); } @@ -3136,12 +3148,8 @@ button.enable-toggle-status-bar-item .glyph { margin-left: -1px; } -.refresh-storage-status-bar-item { - background-image: url(Images/reloadButtons.png) !important; -} - -.refresh-storage-status-bar-item:active { - background-position: 32px 0; +.refresh-storage-status-bar-item .glyph { + -webkit-mask-image: url(Images/reloadButtonGlyph.png); } #storage-view-status-bar-items { diff --git a/WebCore/inspector/front-end/inspector.html b/WebCore/inspector/front-end/inspector.html index a3dc407..4857c7a 100644 --- a/WebCore/inspector/front-end/inspector.html +++ b/WebCore/inspector/front-end/inspector.html @@ -49,6 +49,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <script type="text/javascript" src="DOMStorageItemsView.js"></script> <script type="text/javascript" src="DataGrid.js"></script> <script type="text/javascript" src="DOMStorageDataGrid.js"></script> + <script type="text/javascript" src="CookieItemsView.js"></script> <script type="text/javascript" src="Script.js"></script> <script type="text/javascript" src="Breakpoint.js"></script> <script type="text/javascript" src="SidebarPane.js"></script> @@ -66,6 +67,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <script type="text/javascript" src="StylesSidebarPane.js"></script> <script type="text/javascript" src="Panel.js"></script> <script type="text/javascript" src="PanelEnablerView.js"></script> + <script type="text/javascript" src="StatusBarButton.js"></script> <script type="text/javascript" src="ElementsPanel.js"></script> <script type="text/javascript" src="ResourcesPanel.js"></script> <script type="text/javascript" src="ScriptsPanel.js"></script> diff --git a/WebCore/inspector/front-end/inspector.js b/WebCore/inspector/front-end/inspector.js index aa21a86..f6377c2 100644 --- a/WebCore/inspector/front-end/inspector.js +++ b/WebCore/inspector/front-end/inspector.js @@ -39,7 +39,6 @@ var Preferences = { showInheritedComputedStyleProperties: false, styleRulesExpandedState: {}, showMissingLocalizedStrings: false, - useDOMAgent: false } var WebInspector = { @@ -307,7 +306,7 @@ var WebInspector = { set hoveredDOMNode(x) { - if (objectsAreSame(this._hoveredDOMNode, x)) + if (this._hoveredDOMNode === x) return; this._hoveredDOMNode = x; @@ -333,7 +332,7 @@ var WebInspector = { } if (this._hoveredDOMNode) { - InspectorController.highlightDOMNode(this._hoveredDOMNode); + InspectorController.highlightDOMNode(this._hoveredDOMNode.id); this.showingDOMNodeHighlight = true; } else { InspectorController.hideDOMNodeHighlight(); @@ -353,9 +352,7 @@ WebInspector.loaded = function() // this.changes = new WebInspector.ChangesView(this.drawer); // TODO: Remove class="hidden" from inspector.html on button#changes-status-bar-item this.drawer.visibleView = this.console; - - if (Preferences.useDOMAgent) - this.domAgent = new WebInspector.DOMAgent(); + this.domAgent = new WebInspector.DOMAgent(); this.resourceCategories = { documents: new WebInspector.ResourceCategory(WebInspector.UIString("Documents"), "documents"), @@ -441,7 +438,7 @@ WebInspector.loaded = function() document.getElementById("toolbar").addEventListener("mousedown", this.toolbarDragStart, true); document.getElementById("close-button").addEventListener("click", this.close, true); - InspectorController.loaded(Preferences.useDOMAgent); + InspectorController.loaded(); } var windowLoaded = function() @@ -853,12 +850,12 @@ WebInspector.elementDragEnd = function(event) WebInspector.showConsole = function() { - this.drawer.visibleView = this.console; + this.drawer.showView(this.console); } WebInspector.showChanges = function() { - this.drawer.visibleView = this.changes; + this.drawer.showView(this.changes); } WebInspector.showElementsPanel = function() @@ -909,6 +906,23 @@ WebInspector.addResource = function(identifier, payload) this.panels.resources.addResource(resource); } +WebInspector.clearConsoleMessages = function() +{ + WebInspector.console.clearMessages(false); +} + +WebInspector.selectDatabase = function(o) +{ + WebInspector.showDatabasesPanel(); + WebInspector.panels.databases.selectDatabase(o); +} + +WebInspector.selectDOMStorage = function(o) +{ + WebInspector.showDatabasesPanel(); + WebInspector.panels.databases.selectDOMStorage(o); +} + WebInspector.updateResource = function(identifier, payload) { var resource = this.resources[identifier]; @@ -1073,11 +1087,6 @@ WebInspector.reset = function() this.console.clearMessages(); } -WebInspector.inspectedWindowCleared = function(inspectedWindow) -{ - this.panels.elements.inspectedWindowCleared(inspectedWindow); -} - WebInspector.resourceURLChanged = function(resource, oldURL) { delete this.resourceURLMap[oldURL]; @@ -1138,8 +1147,9 @@ WebInspector.drawLoadingPieChart = function(canvas, percent) { g.fill(); } -WebInspector.updateFocusedNode = function(node) +WebInspector.updateFocusedNode = function(nodeId) { + var node = WebInspector.domAgent.nodeForId(nodeId); if (!node) // FIXME: Should we deselect if null is passed in? return; @@ -1329,6 +1339,11 @@ WebInspector.performSearch = function(event) this.currentPanel.performSearch(query); } +WebInspector.addNodesToSearchResult = function(nodeIds) +{ + WebInspector.panels.elements.addNodesToSearchResult(nodeIds); +} + WebInspector.updateSearchMatchesCount = function(matches, panel) { if (!panel) diff --git a/WebCore/inspector/front-end/treeoutline.js b/WebCore/inspector/front-end/treeoutline.js index 579e7fb..67f35c2 100644 --- a/WebCore/inspector/front-end/treeoutline.js +++ b/WebCore/inspector/front-end/treeoutline.js @@ -249,21 +249,18 @@ TreeOutline.prototype._forgetChildrenRecursive = function(parentElement) } } -TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, getParent, equal) +TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, getParent) { if (!representedObject) return null; - if (!equal) - equal = function(a, b) { return a === b }; - if ("__treeElementIdentifier" in representedObject) { // If this representedObject has a tree element identifier, and it is a known TreeElement // in our tree we can just return that tree element. var elements = this._knownTreeElements[representedObject.__treeElementIdentifier]; if (elements) { for (var i = 0; i < elements.length; ++i) - if (equal(elements[i].representedObject, representedObject)) + if (elements[i].representedObject === representedObject) return elements[i]; } } @@ -277,7 +274,7 @@ TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, var found = false; for (var i = 0; i < this.children.length; ++i) { item = this.children[i]; - if (equal(item.representedObject, representedObject) || isAncestor(item.representedObject, representedObject)) { + if (item.representedObject === representedObject || isAncestor(item.representedObject, representedObject)) { found = true; break; } @@ -292,7 +289,7 @@ TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, var currentObject = representedObject; while (currentObject) { ancestors.unshift(currentObject); - if (equal(currentObject, item.representedObject)) + if (currentObject === item.representedObject) break; currentObject = getParent(currentObject); } @@ -301,18 +298,18 @@ TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, for (var i = 0; i < ancestors.length; ++i) { // Make sure we don't call findTreeElement with the same representedObject // again, to prevent infinite recursion. - if (equal(ancestors[i], representedObject)) + if (ancestors[i] === representedObject) continue; // FIXME: we could do something faster than findTreeElement since we will know the next // ancestor exists in the tree. - item = this.findTreeElement(ancestors[i], isAncestor, getParent, equal); + item = this.findTreeElement(ancestors[i], isAncestor, getParent); if (item && item.onpopulate) item.onpopulate(item); } // Now that all the ancestors are populated, try to find the representedObject again. This time // without the isAncestor and getParent functions to prevent an infinite recursion if it isn't found. - return this.findTreeElement(representedObject, null, null, equal); + return this.findTreeElement(representedObject); } TreeOutline.prototype.treeElementFromPoint = function(x, y) diff --git a/WebCore/inspector/front-end/utilities.js b/WebCore/inspector/front-end/utilities.js index eec0b87..e60af42 100644 --- a/WebCore/inspector/front-end/utilities.js +++ b/WebCore/inspector/front-end/utilities.js @@ -56,6 +56,18 @@ Object.type = function(obj, win) return type; } +Object.proxyType = function(objectProxy) +{ + if (objectProxy === null) + return "null"; + + var type = typeof objectProxy; + if (type !== "object" && type !== "function") + return type; + + return objectProxy.type; +} + Object.hasProperties = function(obj) { if (typeof obj === "undefined" || typeof obj === "null") @@ -65,9 +77,9 @@ Object.hasProperties = function(obj) return false; } -Object.describe = function(obj, abbreviated) +Object.describe = function(obj, abbreviated, win) { - var type1 = Object.type(obj); + var type1 = Object.type(obj, win); var type2 = Object.prototype.toString.call(obj).replace(/^\[object (.*)\]$/i, "$1"); switch (type1) { @@ -238,7 +250,7 @@ Element.prototype.hasStyleClass = function(className) Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = function(nameArray) { - for (var node = this; node && !objectsAreSame(node, this.ownerDocument); node = node.parentNode) + for (var node = this; node && node !== this.ownerDocument; node = node.parentNode) for (var i = 0; i < nameArray.length; ++i) if (node.nodeName.toLowerCase() === nameArray[i].toLowerCase()) return node; @@ -252,7 +264,7 @@ Node.prototype.enclosingNodeOrSelfWithNodeName = function(nodeName) Node.prototype.enclosingNodeOrSelfWithClass = function(className) { - for (var node = this; node && !objectsAreSame(node, this.ownerDocument); node = node.parentNode) + for (var node = this; node && node !== this.ownerDocument; node = node.parentNode) if (node.nodeType === Node.ELEMENT_NODE && node.hasStyleClass(className)) return node; return null; @@ -518,21 +530,6 @@ function nodeContentPreview() return preview.collapseWhitespace(); } -function objectsAreSame(a, b) -{ - // FIXME: Make this more generic so is works with any wrapped object, not just nodes. - // This function is used to compare nodes that might be JSInspectedObjectWrappers, since - // JavaScript equality is not true for JSInspectedObjectWrappers of the same node wrapped - // with different global ExecStates, we use isSameNode to compare them. - if (a === b) - return true; - if (!a || !b) - return false; - if (a.isSameNode && b.isSameNode) - return a.isSameNode(b); - return false; -} - function isAncestorNode(ancestor) { if (!this || !ancestor) @@ -540,7 +537,7 @@ function isAncestorNode(ancestor) var currentNode = ancestor.parentNode; while (currentNode) { - if (objectsAreSame(this, currentNode)) + if (this === currentNode) return true; currentNode = currentNode.parentNode; } @@ -561,13 +558,13 @@ function firstCommonNodeAncestor(node) var node1 = this.parentNode; var node2 = node.parentNode; - if ((!node1 || !node2) || !objectsAreSame(node1, node2)) + if ((!node1 || !node2) || node1 !== node2) return null; while (node1 && node2) { if (!node1.parentNode || !node2.parentNode) break; - if (!objectsAreSame(node1, node2)) + if (node1 !== node2) break; node1 = node1.parentNode; @@ -626,7 +623,7 @@ function traverseNextNode(skipWhitespace, stayWithin) if (node) return node; - if (stayWithin && objectsAreSame(this, stayWithin)) + if (stayWithin && this === stayWithin) return null; node = skipWhitespace ? nextSiblingSkippingWhitespace.call(this) : this.nextSibling; @@ -634,7 +631,7 @@ function traverseNextNode(skipWhitespace, stayWithin) return node; node = this; - while (node && !(skipWhitespace ? nextSiblingSkippingWhitespace.call(node) : node.nextSibling) && (!stayWithin || !node.parentNode || !objectsAreSame(node.parentNode, stayWithin))) + while (node && !(skipWhitespace ? nextSiblingSkippingWhitespace.call(node) : node.nextSibling) && (!stayWithin || !node.parentNode || node.parentNode !== stayWithin)) node = node.parentNode; if (!node) return null; @@ -646,7 +643,7 @@ function traversePreviousNode(skipWhitespace, stayWithin) { if (!this) return; - if (stayWithin && objectsAreSame(this, stayWithin)) + if (stayWithin && this === stayWithin) return null; var node = skipWhitespace ? previousSiblingSkippingWhitespace.call(this) : this.previousSibling; while (node && (skipWhitespace ? lastChildSkippingWhitespace.call(node) : node.lastChild) ) @@ -756,10 +753,10 @@ function parentNodeOrFrameElement(node) { } function isAncestorIncludingParentFrames(a, b) { - if (objectsAreSame(a, b)) + if (a === b) return false; for (var node = b; node; node = getDocumentForNode(node).defaultView.frameElement) - if (objectsAreSame(a, node) || isAncestorNode.call(a, node)) + if (a === node || isAncestorNode.call(a, node)) return true; return false; } @@ -790,20 +787,27 @@ Number.secondsToString = function(seconds, formatterFunction, higherResolution) return formatterFunction("%.1f days", days); } -Number.bytesToString = function(bytes, formatterFunction) +Number.bytesToString = function(bytes, formatterFunction, higherResolution) { if (!formatterFunction) formatterFunction = String.sprintf; + if (typeof higherResolution === "undefined") + higherResolution = true; if (bytes < 1024) return formatterFunction("%.0fB", bytes); var kilobytes = bytes / 1024; - if (kilobytes < 1024) + if (higherResolution && kilobytes < 1024) return formatterFunction("%.2fKB", kilobytes); + else if (kilobytes < 1024) + return formatterFunction("%.0fKB", kilobytes); var megabytes = kilobytes / 1024; - return formatterFunction("%.3fMB", megabytes); + if (higherResolution) + return formatterFunction("%.3fMB", megabytes); + else + return formatterFunction("%.0fMB", megabytes); } Number.constrain = function(num, min, max) |