summaryrefslogtreecommitdiffstats
path: root/WebCore/inspector/front-end
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/inspector/front-end')
-rwxr-xr-xWebCore/inspector/front-end/AuditFormatters.js86
-rw-r--r--WebCore/inspector/front-end/AuditLauncherView.js78
-rw-r--r--WebCore/inspector/front-end/AuditResultView.js13
-rw-r--r--WebCore/inspector/front-end/AuditRules.js4
-rw-r--r--WebCore/inspector/front-end/AuditsPanel.js25
-rw-r--r--WebCore/inspector/front-end/BreakpointManager.js3
-rw-r--r--WebCore/inspector/front-end/BreakpointsSidebarPane.js2
-rw-r--r--WebCore/inspector/front-end/CSSStyleModel.js14
-rw-r--r--WebCore/inspector/front-end/DOMAgent.js57
-rw-r--r--WebCore/inspector/front-end/DOMStorage.js9
-rw-r--r--WebCore/inspector/front-end/Database.js5
-rw-r--r--WebCore/inspector/front-end/ElementsPanel.js9
-rw-r--r--WebCore/inspector/front-end/ElementsTreeOutline.js37
-rw-r--r--WebCore/inspector/front-end/EventListenersSidebarPane.js4
-rw-r--r--WebCore/inspector/front-end/ExtensionAPI.js157
-rw-r--r--WebCore/inspector/front-end/ExtensionAuditCategory.js111
-rw-r--r--WebCore/inspector/front-end/ExtensionCommon.js46
-rw-r--r--WebCore/inspector/front-end/ExtensionServer.js79
-rw-r--r--WebCore/inspector/front-end/HeapSnapshotView.js1008
-rw-r--r--WebCore/inspector/front-end/InjectedScriptAccess.js4
-rw-r--r--WebCore/inspector/front-end/MetricsSidebarPane.js6
-rw-r--r--WebCore/inspector/front-end/ObjectPropertiesSection.js2
-rw-r--r--WebCore/inspector/front-end/Panel.js5
-rw-r--r--WebCore/inspector/front-end/ProfileView.js5
-rw-r--r--WebCore/inspector/front-end/ProfilesPanel.js45
-rw-r--r--WebCore/inspector/front-end/ResourcesPanel.js2
-rw-r--r--WebCore/inspector/front-end/ScriptView.js6
-rw-r--r--WebCore/inspector/front-end/ScriptsPanel.js3
-rw-r--r--WebCore/inspector/front-end/Settings.js4
-rw-r--r--WebCore/inspector/front-end/SourceCSSTokenizer.re2js4
-rw-r--r--WebCore/inspector/front-end/WebKit.qrc4
-rw-r--r--WebCore/inspector/front-end/inspector.css109
-rw-r--r--WebCore/inspector/front-end/inspector.html4
-rw-r--r--WebCore/inspector/front-end/inspector.js29
-rw-r--r--WebCore/inspector/front-end/utilities.js10
35 files changed, 1807 insertions, 182 deletions
diff --git a/WebCore/inspector/front-end/AuditFormatters.js b/WebCore/inspector/front-end/AuditFormatters.js
new file mode 100755
index 0000000..de277ad
--- /dev/null
+++ b/WebCore/inspector/front-end/AuditFormatters.js
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2010 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.applyFormatters = function(value)
+{
+ var formatter;
+ var type = typeof value;
+ var args;
+
+ switch (type) {
+ case "string":
+ case "boolean":
+ case "number":
+ formatter = WebInspector.AuditFormatters.text;
+ args = [ value.toString() ];
+ break;
+
+ case "object":
+ if (value instanceof Array) {
+ formatter = WebInspector.AuditFormatters.concat;
+ args = value;
+ } else if (value.type && value.arguments) {
+ formatter = WebInspector.AuditFormatters[value.type];
+ args = value.arguments;
+ }
+ }
+ if (!formatter)
+ throw "Invalid value or formatter: " + type + JSON.stringify(value);
+
+ return formatter.apply(null, args);
+}
+
+WebInspector.AuditFormatters = {
+ text: function(text)
+ {
+ return document.createTextNode(text);
+ },
+
+ snippet: function(snippetText)
+ {
+ var div = document.createElement("div");
+ div.innerText = snippetText;
+ div.className = "source-code";
+ return div;
+ },
+
+ concat: function()
+ {
+ var parent = document.createElement("span");
+ for (var arg = 0; arg < arguments.length; ++arg)
+ parent.appendChild(WebInspector.applyFormatters(arguments[arg]));
+ return parent;
+ },
+
+ url: function(url, displayText)
+ {
+ return WebInspector.linkifyURLAsNode(url, displayText || url, null, (url in WebInspector.resourceURLMap));
+ }
+};
diff --git a/WebCore/inspector/front-end/AuditLauncherView.js b/WebCore/inspector/front-end/AuditLauncherView.js
index 33d3872..18daee6 100644
--- a/WebCore/inspector/front-end/AuditLauncherView.js
+++ b/WebCore/inspector/front-end/AuditLauncherView.js
@@ -28,10 +28,9 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-WebInspector.AuditLauncherView = function(categoriesById, runnerCallback)
+WebInspector.AuditLauncherView = function(runnerCallback)
{
WebInspector.View.call(this);
- this._categoriesById = categoriesById;
this._runnerCallback = runnerCallback;
this._categoryIdPrefix = "audit-category-item-";
this._auditRunning = false;
@@ -41,27 +40,16 @@ WebInspector.AuditLauncherView = function(categoriesById, runnerCallback)
this._contentElement = document.createElement("div");
this._contentElement.className = "audit-launcher-view-content";
this.element.appendChild(this._contentElement);
+ this._boundCategoryClickListener = this._categoryClicked.bind(this);
this._resetResourceCount();
- function categorySortFunction(a, b)
- {
- var aTitle = a.displayName || "";
- var bTitle = b.displayName || "";
- return aTitle.localeCompare(bTitle);
- }
- var sortedCategories = [];
- for (var id in this._categoriesById)
- sortedCategories.push(this._categoriesById[id]);
- sortedCategories.sort(categorySortFunction);
+ this._sortedCategories = [];
- if (!sortedCategories.length) {
- this._headerElement = document.createElement("h1");
- this._headerElement.className = "no-audits";
- this._headerElement.textContent = WebInspector.UIString("No audits to run");
- this._contentElement.appendChild(this._headerElement);
- } else
- this._createLauncherUI(sortedCategories);
+ this._headerElement = document.createElement("h1");
+ this._headerElement.className = "no-audits";
+ this._headerElement.textContent = WebInspector.UIString("No audits to run");
+ this._contentElement.appendChild(this._headerElement);
}
WebInspector.AuditLauncherView.prototype = {
@@ -133,6 +121,30 @@ WebInspector.AuditLauncherView.prototype = {
this._resetResourceCount();
},
+ addCategory: function(category)
+ {
+ if (!this._sortedCategories.length)
+ this._createLauncherUI();
+
+ var categoryElement = this._createCategoryElement(category.displayName, category.id);
+ category._checkboxElement = categoryElement.firstChild;
+ if (this._selectAllCheckboxElement.checked) {
+ category._checkboxElement.checked = true;
+ ++this._currentCategoriesCount;
+ }
+
+ function compareCategories(a, b)
+ {
+ var aTitle = a.displayName || "";
+ var bTitle = b.displayName || "";
+ return aTitle.localeCompare(bTitle);
+ }
+ var insertBefore = insertionIndexForObjectInListSortedByFunction(category, this._sortedCategories, compareCategories);
+ this._categoriesElement.insertBefore(categoryElement, this._categoriesElement.children[insertBefore]);
+ this._sortedCategories.splice(insertBefore, 0, category);
+ this._updateButton();
+ },
+
_setAuditRunning: function(auditRunning)
{
if (this._auditRunning === auditRunning)
@@ -146,10 +158,11 @@ WebInspector.AuditLauncherView.prototype = {
{
var catIds = [];
var childNodes = this._categoriesElement.childNodes;
- for (var id in this._categoriesById) {
- if (this._categoriesById[id]._checkboxElement.checked)
- catIds.push(id);
+ for (var category = 0; category < this._sortedCategories.length; ++category) {
+ if (this._sortedCategories[category]._checkboxElement.checked)
+ catIds.push(this._sortedCategories[category].id);
}
+
this._setAuditRunning(true);
this._runnerCallback(catIds, this._auditPresentStateElement.checked, this._setAuditRunning.bind(this, false));
},
@@ -159,14 +172,14 @@ WebInspector.AuditLauncherView.prototype = {
var childNodes = this._categoriesElement.childNodes;
for (var i = 0, length = childNodes.length; i < length; ++i)
childNodes[i].firstChild.checked = checkCategories;
- this._currentCategoriesCount = checkCategories ? this._totalCategoriesCount : 0;
+ this._currentCategoriesCount = checkCategories ? this._sortedCategories.length : 0;
this._updateButton();
},
_categoryClicked: function(event)
{
this._currentCategoriesCount += event.target.checked ? 1 : -1;
- this._selectAllCheckboxElement.checked = this._currentCategoriesCount === this._totalCategoriesCount;
+ this._selectAllCheckboxElement.checked = this._currentCategoriesCount === this._sortedCategories.length;
this._updateButton();
},
@@ -177,16 +190,21 @@ WebInspector.AuditLauncherView.prototype = {
var element = document.createElement("input");
element.type = "checkbox";
+ element.addEventListener("click", this._boundCategoryClickListener, false);
labelElement.appendChild(element);
labelElement.appendChild(document.createTextNode(title));
return labelElement;
},
- _createLauncherUI: function(sortedCategories)
+ _createLauncherUI: function()
{
this._headerElement = document.createElement("h1");
this._headerElement.textContent = WebInspector.UIString("Select audits to run");
+
+ for (var child = 0; child < this._contentElement.children.length; ++child)
+ this._contentElement.removeChild(this._contentElement.children[child]);
+
this._contentElement.appendChild(this._headerElement);
function handleSelectAllClick(event)
@@ -204,16 +222,6 @@ WebInspector.AuditLauncherView.prototype = {
this._categoriesElement.className = "audit-categories-container";
this._contentElement.appendChild(this._categoriesElement);
- var boundCategoryClickListener = this._categoryClicked.bind(this);
-
- for (var i = 0; i < sortedCategories.length; ++i) {
- categoryElement = this._createCategoryElement(sortedCategories[i].displayName, sortedCategories[i].id);
- categoryElement.firstChild.addEventListener("click", boundCategoryClickListener, false);
- sortedCategories[i]._checkboxElement = categoryElement.firstChild;
- this._categoriesElement.appendChild(categoryElement);
- }
-
- this._totalCategoriesCount = this._categoriesElement.childNodes.length;
this._currentCategoriesCount = 0;
var flexibleSpaceElement = document.createElement("div");
diff --git a/WebCore/inspector/front-end/AuditResultView.js b/WebCore/inspector/front-end/AuditResultView.js
index 2f4afbd..2636463 100644
--- a/WebCore/inspector/front-end/AuditResultView.js
+++ b/WebCore/inspector/front-end/AuditResultView.js
@@ -81,15 +81,22 @@ WebInspector.AuditCategoryResultPane = function(categoryResult)
WebInspector.AuditCategoryResultPane.prototype = {
_appendResult: function(parentTreeElement, result)
{
- var title = result.value;
- if (result.violationCount)
- title = String.sprintf("%s (%d)", title, result.violationCount);
+ var title = "";
+
+ if (typeof result.value === "string") {
+ title = result.value;
+ if (result.violationCount)
+ title = String.sprintf("%s (%d)", title, result.violationCount);
+ }
var treeElement = new TreeElement(title, null, !!result.children);
parentTreeElement.appendChild(treeElement);
if (result.className)
treeElement.listItemElement.addStyleClass(result.className);
+ if (typeof result.value !== "string")
+ treeElement.listItemElement.appendChild(WebInspector.applyFormatters(result.value));
+
if (result.children) {
for (var i = 0; i < result.children.length; ++i)
this._appendResult(treeElement, result.children[i]);
diff --git a/WebCore/inspector/front-end/AuditRules.js b/WebCore/inspector/front-end/AuditRules.js
index e28a364..a72de56 100644
--- a/WebCore/inspector/front-end/AuditRules.js
+++ b/WebCore/inspector/front-end/AuditRules.js
@@ -371,7 +371,7 @@ WebInspector.AuditRules.UnusedCssRule.prototype = {
return routineResult;
}
- InspectorBackend.getAllStyles(WebInspector.Callback.wrap(evalCallback));
+ InspectorBackend.getAllStyles(evalCallback);
}
}
@@ -693,7 +693,7 @@ WebInspector.AuditRules.ImageDimensionsRule.prototype = {
return callback(null);
var context = {imagesLeft: imageIds.length, urlToNoDimensionCount: {}};
for (var i = imageIds.length - 1; i >= 0; --i)
- InspectorBackend.getStyles(WebInspector.Callback.wrap(imageStylesReady.bind(this, imageIds[i], context)), imageIds[i], true);
+ InspectorBackend.getStyles(imageIds[i], true, imageStylesReady.bind(this, imageIds[i], context));
}
function pushImageNodes()
diff --git a/WebCore/inspector/front-end/AuditsPanel.js b/WebCore/inspector/front-end/AuditsPanel.js
index bc7f3b3..f6cbed0 100644
--- a/WebCore/inspector/front-end/AuditsPanel.js
+++ b/WebCore/inspector/front-end/AuditsPanel.js
@@ -32,8 +32,6 @@ WebInspector.AuditsPanel = function()
{
WebInspector.Panel.call(this, "audits");
- this._constructCategories();
-
this.createSidebar();
this.auditsTreeElement = new WebInspector.SidebarSectionTreeElement("", {}, true);
this.sidebarTree.appendChild(this.auditsTreeElement);
@@ -54,7 +52,11 @@ WebInspector.AuditsPanel = function()
this.viewsContainerElement.id = "audit-views";
this.element.appendChild(this.viewsContainerElement);
- this._launcherView = new WebInspector.AuditLauncherView(this.categoriesById, this.initiateAudit.bind(this));
+ this._constructCategories();
+
+ this._launcherView = new WebInspector.AuditLauncherView(this.initiateAudit.bind(this));
+ for (id in this.categoriesById)
+ this._launcherView.addCategory(this.categoriesById[id]);
}
WebInspector.AuditsPanel.prototype = {
@@ -104,6 +106,17 @@ WebInspector.AuditsPanel.prototype = {
this._launcherView.resourceFinished(resource);
},
+ addCategory: function(category)
+ {
+ this.categoriesById[category.id] = category;
+ this._launcherView.addCategory(category);
+ },
+
+ getCategory: function(id)
+ {
+ return this.categoriesById[id];
+ },
+
_constructCategories: function()
{
this._auditCategoriesById = {};
@@ -147,7 +160,7 @@ WebInspector.AuditsPanel.prototype = {
var category = categories[i];
var result = new WebInspector.AuditCategoryResult(category);
results.push(result);
- category.runRules(resources, ruleResultReadyCallback.bind(null, result));
+ category.run(resources, ruleResultReadyCallback.bind(null, result));
}
},
@@ -220,7 +233,7 @@ WebInspector.AuditsPanel.prototype = {
{
this.visibleView = this._launcherView;
},
-
+
get visibleView()
{
return this._visibleView;
@@ -311,7 +324,7 @@ WebInspector.AuditCategory.prototype = {
this._rules.push(rule);
},
- runRules: function(resources, callback)
+ run: function(resources, callback)
{
this._ensureInitialized();
for (var i = 0; i < this._rules.length; ++i)
diff --git a/WebCore/inspector/front-end/BreakpointManager.js b/WebCore/inspector/front-end/BreakpointManager.js
index 824bc31..8518618 100644
--- a/WebCore/inspector/front-end/BreakpointManager.js
+++ b/WebCore/inspector/front-end/BreakpointManager.js
@@ -123,8 +123,7 @@ WebInspector.BreakpointManager.prototype = {
this._setBreakpoint(breakpoint.sourceID, breakpoint.url, line, breakpoint.enabled, breakpoint.condition);
}
}
- var callbackId = WebInspector.Callback.wrap(didSetBreakpoint.bind(this));
- InspectorBackend.setBreakpoint(callbackId, breakpoint.sourceID, breakpoint.line, breakpoint.enabled, breakpoint.condition);
+ InspectorBackend.setBreakpoint(breakpoint.sourceID, breakpoint.line, breakpoint.enabled, breakpoint.condition, didSetBreakpoint.bind(this));
}
}
diff --git a/WebCore/inspector/front-end/BreakpointsSidebarPane.js b/WebCore/inspector/front-end/BreakpointsSidebarPane.js
index ccf45b6..3a0860f 100644
--- a/WebCore/inspector/front-end/BreakpointsSidebarPane.js
+++ b/WebCore/inspector/front-end/BreakpointsSidebarPane.js
@@ -191,7 +191,7 @@ WebInspector.DOMBreakpointItem = function(breakpoint)
var link = WebInspector.panels.elements.linkifyNodeReference(this._breakpoint.node);
this._element.appendChild(link);
- var type = WebInspector.DOMBreakpoint.Labels[this._breakpoint.type];
+ var type = WebInspector.DOMBreakpoint.labelForType(this._breakpoint.type);
var typeElement = document.createTextNode(" - " + type);
this._element.appendChild(typeElement);
}
diff --git a/WebCore/inspector/front-end/CSSStyleModel.js b/WebCore/inspector/front-end/CSSStyleModel.js
index 66a20ce..bda4064 100644
--- a/WebCore/inspector/front-end/CSSStyleModel.js
+++ b/WebCore/inspector/front-end/CSSStyleModel.js
@@ -35,12 +35,12 @@ WebInspector.CSSStyleModel = function()
WebInspector.CSSStyleModel.prototype = {
getStylesAsync: function(nodeId, authOnly, userCallback)
{
- InspectorBackend.getStyles(WebInspector.Callback.wrap(userCallback), nodeId, authOnly);
+ InspectorBackend.getStyles(nodeId, authOnly, userCallback);
},
getComputedStyleAsync: function(nodeId, userCallback)
{
- InspectorBackend.getComputedStyle(WebInspector.Callback.wrap(userCallback), nodeId);
+ InspectorBackend.getComputedStyle(nodeId, userCallback);
},
setRuleSelector: function(ruleId, newContent, nodeId, successCallback, failureCallback)
@@ -53,7 +53,7 @@ WebInspector.CSSStyleModel.prototype = {
successCallback(WebInspector.CSSStyleDeclaration.parseRule(newRulePayload), doesAffectSelectedNode);
}
- InspectorBackend.setRuleSelector(WebInspector.Callback.wrap(callback), ruleId, newContent, nodeId);
+ InspectorBackend.setRuleSelector(ruleId, newContent, nodeId, callback);
},
addRule: function(nodeId, newContent, successCallback, failureCallback)
@@ -70,7 +70,7 @@ WebInspector.CSSStyleModel.prototype = {
}
}
- InspectorBackend.addRule(WebInspector.Callback.wrap(callback), newContent, nodeId);
+ InspectorBackend.addRule(newContent, nodeId, callback);
},
toggleStyleEnabled: function(styleId, propertyName, disabled, userCallback)
@@ -86,12 +86,12 @@ WebInspector.CSSStyleModel.prototype = {
userCallback(newStyle);
}
- InspectorBackend.toggleStyleEnabled(WebInspector.Callback.wrap(callback), styleId, propertyName, disabled);
+ InspectorBackend.toggleStyleEnabled(styleId, propertyName, disabled, callback);
},
setCSSText: function(styleId, cssText)
{
- InspectorBackend.setStyleText(WebInspector.Callback.wrap(null), styleId, cssText);
+ InspectorBackend.setStyleText(styleId, cssText);
},
applyStyleText: function(styleId, styleText, propertyName, successCallback, failureCallback)
@@ -106,6 +106,6 @@ WebInspector.CSSStyleModel.prototype = {
}
}
- InspectorBackend.applyStyleText(WebInspector.Callback.wrap(callback), styleId, styleText, propertyName);
+ InspectorBackend.applyStyleText(styleId, styleText, propertyName, callback);
}
}
diff --git a/WebCore/inspector/front-end/DOMAgent.js b/WebCore/inspector/front-end/DOMAgent.js
index 0d79d51..5aaa0d3 100644
--- a/WebCore/inspector/front-end/DOMAgent.js
+++ b/WebCore/inspector/front-end/DOMAgent.js
@@ -72,8 +72,12 @@ WebInspector.DOMNode = function(doc, payload) {
this.publicId = payload.publicId;
this.systemId = payload.systemId;
this.internalSubset = payload.internalSubset;
- } else if (this.nodeType === Node.DOCUMENT_NODE)
+ } else if (this.nodeType === Node.DOCUMENT_NODE) {
this.documentURL = payload.documentURL;
+ } else if (this.nodeType === Node.ATTRIBUTE_NODE) {
+ this.name = payload.name;
+ this.value = payload.value;
+ }
}
WebInspector.DOMNode.prototype = {
@@ -306,26 +310,25 @@ WebInspector.DOMAgent.prototype = {
function mycallback() {
callback(parent.children);
}
- var callId = WebInspector.Callback.wrap(mycallback);
- InspectorBackend.getChildNodes(callId, parent.id);
+ InspectorBackend.getChildNodes(parent.id, mycallback);
},
setAttributeAsync: function(node, name, value, callback)
{
var mycallback = this._didApplyDomChange.bind(this, node, callback);
- InspectorBackend.setAttribute(WebInspector.Callback.wrap(mycallback), node.id, name, value);
+ InspectorBackend.setAttribute(node.id, name, value, mycallback);
},
removeAttributeAsync: function(node, name, callback)
{
var mycallback = this._didApplyDomChange.bind(this, node, callback);
- InspectorBackend.removeAttribute(WebInspector.Callback.wrap(mycallback), node.id, name);
+ InspectorBackend.removeAttribute(node.id, name, mycallback);
},
setTextNodeValueAsync: function(node, text, callback)
{
var mycallback = this._didApplyDomChange.bind(this, node, callback);
- InspectorBackend.setTextNodeValue(WebInspector.Callback.wrap(mycallback), node.id, text);
+ InspectorBackend.setTextNodeValue(node.id, text, mycallback);
},
_didApplyDomChange: function(node, callback, success)
@@ -429,8 +432,7 @@ WebInspector.ApplicationCache.getApplicationCachesAsync = function(callback)
callback(applicationCaches);
}
- var callId = WebInspector.Callback.wrap(mycallback);
- InspectorBackend.getApplicationCaches(callId);
+ InspectorBackend.getApplicationCaches(mycallback);
}
WebInspector.Cookies = {}
@@ -445,8 +447,7 @@ WebInspector.Cookies.getCookiesAsync = function(callback)
callback(cookies, true);
}
- var callId = WebInspector.Callback.wrap(mycallback);
- InspectorBackend.getCookies(callId);
+ InspectorBackend.getCookies(mycallback);
}
WebInspector.Cookies.buildCookiesFromString = function(rawCookieString)
@@ -496,9 +497,7 @@ WebInspector.EventListeners.getEventListenersForNodeAsync = function(node, callb
{
if (!node)
return;
-
- var callId = WebInspector.Callback.wrap(callback);
- InspectorBackend.getEventListenersForNode(callId, node.id);
+ InspectorBackend.getEventListenersForNode(node.id, callback);
}
WebInspector.CSSStyleDeclaration = function(payload)
@@ -697,6 +696,13 @@ WebInspector.DOMBreakpointManager.prototype = {
this.dispatchEventToListeners("dom-breakpoint-added", breakpoint);
},
+ findBreakpoint: function(nodeId, type)
+ {
+ var nodeBreakpoints = this._breakpoints[nodeId];
+ if (nodeBreakpoints && type in nodeBreakpoints)
+ return nodeBreakpoints[type];
+ },
+
removeBreakpointsForNode: function(node)
{
var nodeBreakpoints = this._breakpoints[node.id];
@@ -733,10 +739,27 @@ WebInspector.DOMBreakpoint.Types = {
NodeRemoved: 2
};
-WebInspector.DOMBreakpoint.Labels = {};
-WebInspector.DOMBreakpoint.Labels[WebInspector.DOMBreakpoint.Types.SubtreeModified] = WebInspector.UIString("Subtree Modified");
-WebInspector.DOMBreakpoint.Labels[WebInspector.DOMBreakpoint.Types.AttributeModified] = WebInspector.UIString("Attribute Modified");
-WebInspector.DOMBreakpoint.Labels[WebInspector.DOMBreakpoint.Types.NodeRemoved] = WebInspector.UIString("Node Removed");
+WebInspector.DOMBreakpoint.labelForType = function(type)
+{
+ if (!WebInspector.DOMBreakpoint._labels) {
+ WebInspector.DOMBreakpoint._labels = {};
+ WebInspector.DOMBreakpoint._labels[WebInspector.DOMBreakpoint.Types.SubtreeModified] = WebInspector.UIString("Subtree Modified");
+ WebInspector.DOMBreakpoint._labels[WebInspector.DOMBreakpoint.Types.AttributeModified] = WebInspector.UIString("Attribute Modified");
+ WebInspector.DOMBreakpoint._labels[WebInspector.DOMBreakpoint.Types.NodeRemoved] = WebInspector.UIString("Node Removed");
+ }
+ return WebInspector.DOMBreakpoint._labels[type];
+}
+
+WebInspector.DOMBreakpoint.contextMenuLabelForType = function(type)
+{
+ if (!WebInspector.DOMBreakpoint._contextMenuLabels) {
+ WebInspector.DOMBreakpoint._contextMenuLabels = {};
+ WebInspector.DOMBreakpoint._contextMenuLabels[WebInspector.DOMBreakpoint.Types.SubtreeModified] = WebInspector.UIString("Break on Subtree Modifications");
+ WebInspector.DOMBreakpoint._contextMenuLabels[WebInspector.DOMBreakpoint.Types.AttributeModified] = WebInspector.UIString("Break on Attributes Modifications");
+ WebInspector.DOMBreakpoint._contextMenuLabels[WebInspector.DOMBreakpoint.Types.NodeRemoved] = WebInspector.UIString("Break on Node Removal");
+ }
+ return WebInspector.DOMBreakpoint._contextMenuLabels[type];
+}
WebInspector.DOMBreakpoint.prototype = {
get enabled()
diff --git a/WebCore/inspector/front-end/DOMStorage.js b/WebCore/inspector/front-end/DOMStorage.js
index 5c28e29..37be8f6 100644
--- a/WebCore/inspector/front-end/DOMStorage.js
+++ b/WebCore/inspector/front-end/DOMStorage.js
@@ -56,20 +56,17 @@ WebInspector.DOMStorage.prototype = {
getEntries: function(callback)
{
- var callId = WebInspector.Callback.wrap(callback);
- InspectorBackend.getDOMStorageEntries(callId, this._id);
+ InspectorBackend.getDOMStorageEntries(this._id, callback);
},
setItem: function(key, value, callback)
{
- var callId = WebInspector.Callback.wrap(callback);
- InspectorBackend.setDOMStorageItem(callId, this._id, key, value);
+ InspectorBackend.setDOMStorageItem(this._id, key, value, callback);
},
removeItem: function(key, callback)
{
- var callId = WebInspector.Callback.wrap(callback);
- InspectorBackend.removeDOMStorageItem(callId, this._id, key);
+ InspectorBackend.removeDOMStorageItem(this._id, key, callback);
}
}
diff --git a/WebCore/inspector/front-end/Database.js b/WebCore/inspector/front-end/Database.js
index 45b7a0e..ca3e968 100644
--- a/WebCore/inspector/front-end/Database.js
+++ b/WebCore/inspector/front-end/Database.js
@@ -84,8 +84,7 @@ WebInspector.Database.prototype = {
{
callback(names.sort());
}
- var callId = WebInspector.Callback.wrap(sortingCallback);
- InspectorBackend.getDatabaseTableNames(callId, this._id);
+ InspectorBackend.getDatabaseTableNames(this._id, sortingCallback);
},
executeSql: function(query, onSuccess, onError)
@@ -99,7 +98,7 @@ WebInspector.Database.prototype = {
WebInspector.Database.successCallbacks[transactionId] = onSuccess;
WebInspector.Database.errorCallbacks[transactionId] = onError;
}
- InspectorBackend.executeSQL(WebInspector.Callback.wrap(callback), this._id, query);
+ InspectorBackend.executeSQL(this._id, query, callback);
}
}
diff --git a/WebCore/inspector/front-end/ElementsPanel.js b/WebCore/inspector/front-end/ElementsPanel.js
index f18299a..e1bc637 100644
--- a/WebCore/inspector/front-end/ElementsPanel.js
+++ b/WebCore/inspector/front-end/ElementsPanel.js
@@ -58,7 +58,7 @@ WebInspector.ElementsPanel = function()
if (this._focusedDOMNode) {
InspectorBackend.addInspectedNode(this._focusedDOMNode.id);
- WebInspector.extensionServer.notifyObjectSelected(this.name, "DOMNode");
+ WebInspector.extensionServer.notifyObjectSelected(this.panel.name, "DOMNode");
}
};
@@ -224,10 +224,9 @@ WebInspector.ElementsPanel.prototype = {
selectNode.call(this, node);
}
- if (this._selectedPathOnReset) {
- var callId = WebInspector.Callback.wrap(selectLastSelectedNode.bind(this));
- InspectorBackend.pushNodeByPathToFrontend(callId, this._selectedPathOnReset.join(","));
- } else
+ if (this._selectedPathOnReset)
+ InspectorBackend.pushNodeByPathToFrontend(this._selectedPathOnReset.join(","), selectLastSelectedNode.bind(this));
+ else
selectNode.call(this);
delete this._selectedPathOnReset;
},
diff --git a/WebCore/inspector/front-end/ElementsTreeOutline.js b/WebCore/inspector/front-end/ElementsTreeOutline.js
index 7f48161..ba3b320 100644
--- a/WebCore/inspector/front-end/ElementsTreeOutline.js
+++ b/WebCore/inspector/front-end/ElementsTreeOutline.js
@@ -765,16 +765,16 @@ WebInspector.ElementsTreeElement.prototype = {
if (Preferences.domBreakpointsEnabled) {
// Add debbuging-related actions
contextMenu.appendSeparator();
-
- contextMenu.appendItem(WebInspector.UIString("Stop on Subtree Modifications"),
- WebInspector.domBreakpointManager.setBreakpoint.bind(WebInspector.domBreakpointManager, this.representedObject, WebInspector.DOMBreakpoint.Types.SubtreeModified));
- contextMenu.appendItem(WebInspector.UIString("Stop on Attributes Modifications"),
- WebInspector.domBreakpointManager.setBreakpoint.bind(WebInspector.domBreakpointManager, this.representedObject, WebInspector.DOMBreakpoint.Types.AttributeModified));
- contextMenu.appendItem(WebInspector.UIString("Stop on Node Removal"),
- WebInspector.domBreakpointManager.setBreakpoint.bind(WebInspector.domBreakpointManager, this.representedObject, WebInspector.DOMBreakpoint.Types.NodeRemoved));
-
- contextMenu.appendItem(WebInspector.UIString("Remove Breakpoints"),
- WebInspector.domBreakpointManager.removeBreakpointsForNode.bind(WebInspector.domBreakpointManager, this.representedObject));
+ for (var type in WebInspector.DOMBreakpoint.Types) {
+ var typeId = WebInspector.DOMBreakpoint.Types[type];
+ var label = WebInspector.DOMBreakpoint.contextMenuLabelForType(typeId);
+ var breakpoint = WebInspector.domBreakpointManager.findBreakpoint(this.representedObject.id, typeId);
+ if (!breakpoint)
+ var handler = WebInspector.domBreakpointManager.setBreakpoint.bind(WebInspector.domBreakpointManager, this.representedObject, typeId);
+ else
+ var handler = breakpoint.remove.bind(breakpoint);
+ contextMenu.appendCheckboxItem(label, handler, !!breakpoint);
+ }
}
},
@@ -1125,8 +1125,7 @@ WebInspector.ElementsTreeElement.prototype = {
moveToNextAttributeIfNeeded.call(newTreeItem);
}
- var callId = WebInspector.Callback.wrap(changeTagNameCallback);
- InspectorBackend.changeTagName(callId, this.representedObject.id, newText);
+ InspectorBackend.changeTagName(this.representedObject.id, newText, changeTagNameCallback);
},
_textNodeEditingCommitted: function(element, newText)
@@ -1265,6 +1264,11 @@ WebInspector.ElementsTreeElement.prototype = {
info.title = "Document Fragment";
break;
+ case Node.ATTRIBUTE_NODE:
+ var value = node.value || "\u200B"; // Zero width space to force showing an empty value.
+ info.title = this._attributeHTML(node.name, value);
+ break;
+
case Node.ELEMENT_NODE:
var tagName = this.treeOutline.nodeNameToCorrectCase(node.nodeName).escapeHTML();
if (this._elementCloseTag) {
@@ -1374,8 +1378,7 @@ WebInspector.ElementsTreeElement.prototype = {
parentElement.adjustCollapsedRange(true);
}
- var callId = WebInspector.Callback.wrap(removeNodeCallback);
- InspectorBackend.removeNode(callId, this.representedObject.id);
+ InspectorBackend.removeNode(this.representedObject.id, removeNodeCallback);
},
_editAsHTML: function()
@@ -1402,12 +1405,10 @@ WebInspector.ElementsTreeElement.prototype = {
function commitChange(value)
{
- var setCallId = WebInspector.Callback.wrap(selectNode);
- InspectorBackend.setOuterHTML(setCallId, node.id, value);
+ InspectorBackend.setOuterHTML(node.id, value, selectNode);
}
- var getCallId = WebInspector.Callback.wrap(this._startEditingAsHTML.bind(this, commitChange));
- InspectorBackend.getOuterHTML(getCallId, node.id);
+ InspectorBackend.getOuterHTML(node.id, this._startEditingAsHTML.bind(this, commitChange));
},
_copyHTML: function()
diff --git a/WebCore/inspector/front-end/EventListenersSidebarPane.js b/WebCore/inspector/front-end/EventListenersSidebarPane.js
index 2800d6e..34dea00 100644
--- a/WebCore/inspector/front-end/EventListenersSidebarPane.js
+++ b/WebCore/inspector/front-end/EventListenersSidebarPane.js
@@ -183,7 +183,7 @@ WebInspector.EventListenerBar = function(eventListener, nodeId)
this._setFunctionSubtitle();
this.editable = false;
this.element.className = "event-bar"; /* Changed from "section" */
- this.propertiesElement.className = "event-properties"; /* Changed from "properties" */
+ this.propertiesElement.className = "event-properties source-code"; /* Changed from "properties" */
}
WebInspector.EventListenerBar.prototype = {
@@ -196,7 +196,7 @@ WebInspector.EventListenerBar.prototype = {
properties.push(new WebInspector.RemoteObjectProperty("node", nodeObject));
for (var propertyName in this.eventListener) {
- var value = WebInspector.RemoteObject.fromPrimitiveValue(value);
+ var value = WebInspector.RemoteObject.fromPrimitiveValue(this.eventListener[propertyName]);
properties.push(new WebInspector.RemoteObjectProperty(propertyName, value));
}
this.updateProperties(properties);
diff --git a/WebCore/inspector/front-end/ExtensionAPI.js b/WebCore/inspector/front-end/ExtensionAPI.js
index a89dcf1..64f5482 100644
--- a/WebCore/inspector/front-end/ExtensionAPI.js
+++ b/WebCore/inspector/front-end/ExtensionAPI.js
@@ -28,7 +28,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-var injectedExtensionAPI = function(InjectedScriptHost, inspectedWindow, injectedScriptId)
+WebInspector.injectedExtensionAPI = function(InjectedScriptHost, inspectedWindow, injectedScriptId)
{
// Here and below, all constructors are private to API implementation.
@@ -37,19 +37,22 @@ var injectedExtensionAPI = function(InjectedScriptHost, inspectedWindow, injecte
// by Foo consutrctor to re-bind publicly exported members to an instance
// of Foo.
-function EventSinkImpl(type)
+function EventSinkImpl(type, customDispatch)
{
this._type = type;
this._listeners = [];
+ this._customDispatch = customDispatch;
}
EventSinkImpl.prototype = {
addListener: function(callback)
{
+ if (typeof callback != "function")
+ throw new "addListener: callback is not a function";
if (this._listeners.length === 0)
extensionServer.sendRequest({ command: "subscribe", type: this._type });
this._listeners.push(callback);
- extensionServer.registerHandler("notify-" + this._type, bind(this._fire, this));
+ extensionServer.registerHandler("notify-" + this._type, bind(this._dispatch, this));
},
removeListener: function(callback)
@@ -66,26 +69,36 @@ EventSinkImpl.prototype = {
extensionServer.sendRequest({ command: "unsubscribe", type: this._type });
},
- _fire: function(request)
+ _fire: function()
{
var listeners = this._listeners.slice();
for (var i = 0; i < listeners.length; ++i)
- listeners[i].apply(null, request.arguments);
+ listeners[i].apply(null, arguments);
+ },
+
+ _dispatch: function(request)
+ {
+ if (this._customDispatch)
+ this._customDispatch.call(this, request);
+ else
+ this._fire.apply(this, request.arguments);
}
}
-function EventSink(type)
+function EventSink(type, customDispatch)
{
- var impl = new EventSinkImpl(type);
+ var impl = new EventSinkImpl(type, customDispatch);
this.addListener = bind(impl.addListener, impl);
this.removeListener = bind(impl.removeListener, impl);
}
function InspectorExtensionAPI()
{
+ this.audits = new Audits();
this.inspectedWindow = new InspectedWindow();
this.panels = new Panels();
this.resources = new Resources();
+
this.onReset = new EventSink("reset");
}
@@ -125,7 +138,7 @@ function Panels()
{
return panels[name];
}
-
+
for (var i = 0; i < wellKnownPanelNames.length; ++i) {
var name = wellKnownPanelNames[i];
panels[name] = new Panel(name);
@@ -151,7 +164,7 @@ Panels.prototype = {
id: id,
label: label,
url: expandURL(pageURL),
- icon: expandURL(iconURL)
+ icon: expandURL(iconURL)
};
extensionServer.sendRequest(request, callback && bind(callbackWrapper, this));
}
@@ -219,6 +232,124 @@ function ExtensionSidebarPane(id)
this.setExpanded = bind(impl.setExpanded, impl);
}
+function Audits()
+{
+}
+
+Audits.prototype = {
+ addCategory: function(displayName, ruleCount)
+ {
+ var id = "extension-audit-category-" + extensionServer.nextObjectId();
+ extensionServer.sendRequest({ command: "addAuditCategory", id: id, displayName: displayName, ruleCount: ruleCount });
+ return new AuditCategory(id);
+ }
+}
+
+function AuditCategory(id)
+{
+ function customDispatch(request)
+ {
+ var auditResult = new AuditResult(request.arguments[0]);
+ try {
+ this._fire(auditResult);
+ } catch (e) {
+ console.error("Uncaught exception in extension audit event handler: " + e);
+ auditResult.done();
+ }
+ }
+ var impl = new AuditCategoryImpl(id);
+ this.onAuditStarted = new EventSink("audit-started-" + id, customDispatch);
+}
+
+function AuditCategoryImpl(id)
+{
+ this._id = id;
+}
+
+function AuditResult(id)
+{
+ var impl = new AuditResultImpl(id);
+
+ this.addResult = bind(impl.addResult, impl);
+ this.createResult = bind(impl.createResult, impl);
+ this.done = bind(impl.done, impl);
+
+ var formatterTypes = [
+ "url",
+ "snippet",
+ "text"
+ ];
+ for (var i = 0; i < formatterTypes.length; ++i)
+ this[formatterTypes[i]] = bind(impl._nodeFactory, null, formatterTypes[i]);
+}
+
+AuditResult.prototype = {
+ get Severity()
+ {
+ return private.audits.Severity;
+ }
+}
+
+function AuditResultImpl(id)
+{
+ this._id = id;
+}
+
+AuditResultImpl.prototype = {
+ addResult: function(displayName, description, severity, details)
+ {
+ // shorthand for specifying details directly in addResult().
+ if (details && !(details instanceof AuditResultNode))
+ details = details instanceof Array ? this.createNode.apply(this, details) : this.createNode(details);
+
+ var request = {
+ command: "addAuditResult",
+ resultId: this._id,
+ displayName: displayName,
+ description: description,
+ severity: severity,
+ details: details
+ };
+ extensionServer.sendRequest(request);
+ },
+
+ createResult: function()
+ {
+ var node = new AuditResultNode();
+ node.contents = Array.prototype.slice.call(arguments);
+ return node;
+ },
+
+ done: function()
+ {
+ extensionServer.sendRequest({ command: "stopAuditCategoryRun", resultId: this._id });
+ },
+
+ _nodeFactory: function(type)
+ {
+ return {
+ type: type,
+ arguments: Array.prototype.slice.call(arguments, 1)
+ };
+ }
+}
+
+function AuditResultNode(contents)
+{
+ this.contents = contents;
+ this.children = [];
+ this.expanded = false;
+}
+
+AuditResultNode.prototype = {
+ addChild: function()
+ {
+ var node = AuditResultImpl.prototype.createResult.apply(null, arguments);
+ this.children.push(node);
+ return node;
+ }
+};
+
function InspectedWindow()
{
this.onLoaded = new EventSink("inspectedPageLoaded");
@@ -234,7 +365,13 @@ InspectedWindow.prototype = {
evaluate: function(expression, callback)
{
- return extensionServer.sendRequest({ command: "evaluateOnInspectedPage", expression: expression }, callback);
+ function callbackWrapper(result)
+ {
+ if (result && !result.isException)
+ result.value = result.value === "undefined" ? undefined : JSON.parse(result.value);
+ callback(result);
+ }
+ return extensionServer.sendRequest({ command: "evaluateOnInspectedPage", expression: expression }, callback && callbackWrapper);
}
}
diff --git a/WebCore/inspector/front-end/ExtensionAuditCategory.js b/WebCore/inspector/front-end/ExtensionAuditCategory.js
new file mode 100644
index 0000000..5d155d7
--- /dev/null
+++ b/WebCore/inspector/front-end/ExtensionAuditCategory.js
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2010 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.ExtensionAuditCategory = function(id, displayName, ruleCount)
+{
+ this._id = id;
+ this._displayName = displayName;
+ this._ruleCount = ruleCount;
+}
+
+WebInspector.ExtensionAuditCategory.prototype = {
+ // AuditCategory interface
+ get id()
+ {
+ return this._id;
+ },
+
+ get displayName()
+ {
+ return this._displayName;
+ },
+
+ get ruleCount()
+ {
+ return this._ruleCount;
+ },
+
+ run: function(resources, callback)
+ {
+ new WebInspector.ExtensionAuditCategoryResults(this, callback);
+ }
+}
+
+WebInspector.ExtensionAuditCategoryResults = function(category, callback)
+{
+ this._category = category;
+ this._pendingRules = category.ruleCount;
+ this._ruleCompletionCallback = callback;
+
+ this.id = category.id + "-" + ++WebInspector.ExtensionAuditCategoryResults._lastId;
+ WebInspector.extensionServer.startAuditRun(category, this);
+}
+
+WebInspector.ExtensionAuditCategoryResults.prototype = {
+ get complete()
+ {
+ return !this._pendingRules;
+ },
+
+ cancel: function()
+ {
+ while (!this.complete)
+ this._addResult(null);
+ },
+
+ addResult: function(displayName, description, severity, details)
+ {
+ var result = new WebInspector.AuditRuleResult(displayName);
+ result.addChild(description);
+ result.severity = severity;
+ if (details)
+ this._addNode(result, details);
+ this._addResult(result);
+ },
+
+ _addNode: function(parent, node)
+ {
+ var addedNode = parent.addChild(node.contents, node.expanded);
+ if (node.children) {
+ for (var i = 0; i < node.children.length; ++i)
+ this._addNode(addedNode, node.children[i]);
+ }
+ },
+
+ _addResult: function(result)
+ {
+ this._ruleCompletionCallback(result);
+ this._pendingRules--;
+ if (!this._pendingRules)
+ WebInspector.extensionServer.stopAuditRun(this);
+ }
+}
+
+WebInspector.ExtensionAuditCategoryResults._lastId = 0;
diff --git a/WebCore/inspector/front-end/ExtensionCommon.js b/WebCore/inspector/front-end/ExtensionCommon.js
new file mode 100644
index 0000000..b04c18c
--- /dev/null
+++ b/WebCore/inspector/front-end/ExtensionCommon.js
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2010 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.commonExtensionSymbols = function(private)
+{
+
+ if (!private.audits)
+ private.audits = {};
+
+ private.audits.Severity = {
+ Info: "info",
+ Warning: "warning",
+ Severe: "severe"
+ };
+}
+
+WebInspector.extensionAPI = {};
+
+WebInspector.commonExtensionSymbols(WebInspector.extensionAPI);
diff --git a/WebCore/inspector/front-end/ExtensionServer.js b/WebCore/inspector/front-end/ExtensionServer.js
index 95f373f..f410d8c 100644
--- a/WebCore/inspector/front-end/ExtensionServer.js
+++ b/WebCore/inspector/front-end/ExtensionServer.js
@@ -40,11 +40,15 @@ WebInspector.ExtensionServer = function()
this._registerHandler("getResources", this._onGetResources.bind(this));
this._registerHandler("createPanel", this._onCreatePanel.bind(this));
this._registerHandler("createSidebarPane", this._onCreateSidebar.bind(this));
- this._registerHandler("log", this._onLog.bind(this));
+ this._registerHandler("log", this._onLog.bind(this));
this._registerHandler("evaluateOnInspectedPage", this._onEvaluateOnInspectedPage.bind(this));
this._registerHandler("setSidebarHeight", this._onSetSidebarHeight.bind(this));
this._registerHandler("setSidebarExpanded", this._onSetSidebarExpansion.bind(this));
+ this._registerHandler("addAuditCategory", this._onAddAuditCategory.bind(this));
+ this._registerHandler("addAuditResult", this._onAddAuditResult.bind(this));
+ this._registerHandler("stopAuditCategoryRun", this._onStopAuditCategoryRun.bind(this));
+
window.addEventListener("message", this._onWindowMessage.bind(this), false);
}
@@ -84,6 +88,17 @@ WebInspector.ExtensionServer.prototype = {
this._postNotification("reset");
},
+ startAuditRun: function(category, auditRun)
+ {
+ this._clientObjects[auditRun.id] = auditRun;
+ this._postNotification("audit-started-" + category.id, auditRun.id);
+ },
+
+ stopAuditRun: function(auditRun)
+ {
+ delete this._clientObjects[auditRun.id];
+ },
+
_convertResource: function(resource)
{
return {
@@ -100,7 +115,7 @@ WebInspector.ExtensionServer.prototype = {
return;
var message = {
command: "notify-" + type,
- arguments: Array.prototype.slice.call(arguments, 1)
+ arguments: Array.prototype.slice.call(arguments, 1)
};
for (var i = 0; i < subscribers.length; ++i)
subscribers[i].postMessage(message);
@@ -195,7 +210,6 @@ WebInspector.ExtensionServer.prototype = {
_onEvaluateOnInspectedPage: function(message, port)
{
- var escapedMessage = escape(message.expression);
function callback(resultPayload)
{
var resultObject = WebInspector.RemoteObject.fromPayload(resultPayload);
@@ -205,7 +219,10 @@ WebInspector.ExtensionServer.prototype = {
result.value = resultObject.description;
this._dispatchCallback(message.requestId, port, result);
}
- InjectedScriptAccess.getDefault().evaluate("(function() { var a = window.eval(unescape(\"" + escapedMessage + "\")); return JSON.stringify(a); })();", "", callback.bind(this));
+ var evalExpression = "JSON.stringify(eval('" +
+ "with (window.console._commandLineAPI) with (window) {' + unescape('" + escape(message.expression) +
+ "') + '}'));";
+ InjectedScriptAccess.getDefault().evaluate(evalExpression, callback.bind(this));
},
_onRevealAndSelect: function(message)
@@ -248,6 +265,36 @@ WebInspector.ExtensionServer.prototype = {
return response;
},
+ _onAddAuditCategory: function(request)
+ {
+ var category = new WebInspector.ExtensionAuditCategory(request.id, request.displayName, request.ruleCount);
+ if (WebInspector.panels.audits.getCategory(category.id))
+ return this._status.E_EXISTS(category.id);
+ this._clientObjects[request.id] = category;
+ WebInspector.panels.audits.addCategory(category);
+ },
+
+ _onAddAuditResult: function(request)
+ {
+ var auditResult = this._clientObjects[request.resultId];
+ if (!auditResult)
+ return this._status.E_NOTFOUND(request.resultId);
+ try {
+ auditResult.addResult(request.displayName, request.description, request.severity, request.details);
+ } catch (e) {
+ return e;
+ }
+ return this._status.OK();
+ },
+
+ _onStopAuditCategoryRun: function(request)
+ {
+ var auditRun = this._clientObjects[request.resultId];
+ if (!auditRun)
+ return this._status.E_NOTFOUND(request.resultId);
+ auditRun.cancel();
+ },
+
initExtensions: function()
{
InspectorExtensionRegistry.getExtensionsAsync();
@@ -255,7 +302,8 @@ WebInspector.ExtensionServer.prototype = {
_addExtensions: function(extensions)
{
- InspectorFrontendHost.setExtensionAPI("(" + injectedExtensionAPI.toString() + ")"); // See ExtensionAPI.js for details.
+ // See ExtensionAPI.js and ExtensionCommon.js for details.
+ InspectorFrontendHost.setExtensionAPI(this._buildExtensionAPIInjectedScript());
for (var i = 0; i < extensions.length; ++i) {
var extension = extensions[i];
try {
@@ -271,6 +319,15 @@ WebInspector.ExtensionServer.prototype = {
}
},
+ _buildExtensionAPIInjectedScript: function()
+ {
+ return "(function(){ " +
+ "var private = {};" +
+ "(" + WebInspector.commonExtensionSymbols.toString() + ")(private);" +
+ "(" + WebInspector.injectedExtensionAPI.toString() + ").apply(this, arguments);" +
+ "})";
+ },
+
_onWindowMessage: function(event)
{
if (event.data !== "registerExtension")
@@ -300,12 +357,14 @@ WebInspector.ExtensionServer.prototype = {
}
}
-WebInspector.ExtensionServer._statuses =
+WebInspector.ExtensionServer._statuses =
{
OK: "",
- E_NOTFOUND: "Object not found (%s)",
- E_NOTSUPPORTED: "Object does not support requested operation (%s)",
- E_EXISTS: "Object already exists (%s)"
+ E_EXISTS: "Object already exists: %s",
+ E_BADARG: "Invalid argument %s: %s",
+ E_BADARGTYPE: "Invalid type for argument %s: got %s, expected %s",
+ E_NOTFOUND: "Object not found: %s",
+ E_NOTSUPPORTED: "Object does not support requested operation: %s",
}
WebInspector.ExtensionStatus = function()
@@ -319,7 +378,7 @@ WebInspector.ExtensionStatus = function()
status.isError = true;
console.log("Extension server error: " + String.vsprintf(description, details));
}
- return status;
+ return status;
}
for (status in WebInspector.ExtensionServer._statuses)
this[status] = makeStatus.bind(null, status);
diff --git a/WebCore/inspector/front-end/HeapSnapshotView.js b/WebCore/inspector/front-end/HeapSnapshotView.js
new file mode 100644
index 0000000..6bcc0ff
--- /dev/null
+++ b/WebCore/inspector/front-end/HeapSnapshotView.js
@@ -0,0 +1,1008 @@
+/*
+ * Copyright (C) 2010 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.HeapSnapshotView = function(parent, profile)
+{
+ WebInspector.View.call(this);
+
+ this.element.addStyleClass("heap-snapshot-view");
+
+ this.parent = parent;
+ this.parent.addEventListener("profile added", this._updateBaseOptions, this);
+
+ this.showCountAsPercent = false;
+ this.showSizeAsPercent = false;
+ this.showCountDeltaAsPercent = false;
+ this.showSizeDeltaAsPercent = false;
+
+ this.categories = {
+ code: new WebInspector.ResourceCategory("code", WebInspector.UIString("Code"), "rgb(255,121,0)"),
+ data: new WebInspector.ResourceCategory("data", WebInspector.UIString("Objects"), "rgb(47,102,236)")
+ };
+
+ var summaryContainer = document.createElement("div");
+ summaryContainer.id = "heap-snapshot-summary-container";
+
+ this.countsSummaryBar = new WebInspector.SummaryBar(this.categories);
+ this.countsSummaryBar.element.className = "heap-snapshot-summary";
+ this.countsSummaryBar.calculator = new WebInspector.HeapSummaryCountCalculator();
+ var countsLabel = document.createElement("div");
+ countsLabel.className = "heap-snapshot-summary-label";
+ countsLabel.textContent = WebInspector.UIString("Count");
+ this.countsSummaryBar.element.appendChild(countsLabel);
+ summaryContainer.appendChild(this.countsSummaryBar.element);
+
+ this.sizesSummaryBar = new WebInspector.SummaryBar(this.categories);
+ this.sizesSummaryBar.element.className = "heap-snapshot-summary";
+ this.sizesSummaryBar.calculator = new WebInspector.HeapSummarySizeCalculator();
+ var sizesLabel = document.createElement("label");
+ sizesLabel.className = "heap-snapshot-summary-label";
+ sizesLabel.textContent = WebInspector.UIString("Size");
+ this.sizesSummaryBar.element.appendChild(sizesLabel);
+ summaryContainer.appendChild(this.sizesSummaryBar.element);
+
+ this.element.appendChild(summaryContainer);
+
+ var columns = {
+ cons: { title: WebInspector.UIString("Constructor"), disclosure: true, sortable: true },
+ count: { title: WebInspector.UIString("Count"), width: "54px", sortable: true },
+ size: { title: WebInspector.UIString("Size"), width: "72px", sort: "descending", sortable: true },
+ // \xb1 is a "plus-minus" sign.
+ countDelta: { title: WebInspector.UIString("\xb1 Count"), width: "72px", sortable: true },
+ sizeDelta: { title: WebInspector.UIString("\xb1 Size"), width: "72px", sortable: true }
+ };
+
+ this.dataGrid = new WebInspector.DataGrid(columns);
+ this.dataGrid.addEventListener("sorting changed", this._sortData, this);
+ this.dataGrid.element.addEventListener("mousedown", this._mouseDownInDataGrid.bind(this), true);
+ this.element.appendChild(this.dataGrid.element);
+
+ this.profile = profile;
+
+ this.baseSelectElement = document.createElement("select");
+ this.baseSelectElement.className = "status-bar-item";
+ this.baseSelectElement.addEventListener("change", this._changeBase.bind(this), false);
+ this._updateBaseOptions();
+
+ this.percentButton = new WebInspector.StatusBarButton("", "percent-time-status-bar-item status-bar-item");
+ this.percentButton.addEventListener("click", this._percentClicked.bind(this), false);
+
+ this._loadProfile(this.profile, profileCallback.bind(this));
+
+ function profileCallback(profile)
+ {
+ var list = this._getProfiles();
+ var profileIndex;
+ for (var i = 0; i < list.length; ++i)
+ if (list[i].uid === profile.uid) {
+ profileIndex = i;
+ break;
+ }
+ if (profileIndex > 0)
+ this.baseSelectElement.selectedIndex = profileIndex - 1;
+ else
+ this.baseSelectElement.selectedIndex = profileIndex;
+ this._resetDataGridList(resetCompleted.bind(this));
+ }
+
+ function resetCompleted()
+ {
+ this.refresh();
+ this._updatePercentButton();
+ }
+}
+
+WebInspector.HeapSnapshotView.prototype = {
+ get statusBarItems()
+ {
+ return [this.baseSelectElement, this.percentButton.element];
+ },
+
+ get profile()
+ {
+ return this._profile;
+ },
+
+ set profile(profile)
+ {
+ this._profile = profile;
+ },
+
+ show: function(parentElement)
+ {
+ WebInspector.View.prototype.show.call(this, parentElement);
+ this.dataGrid.updateWidths();
+ },
+
+ hide: function()
+ {
+ WebInspector.View.prototype.hide.call(this);
+ this._currentSearchResultIndex = -1;
+ },
+
+ resize: function()
+ {
+ if (this.dataGrid)
+ this.dataGrid.updateWidths();
+ },
+
+ refresh: function()
+ {
+ this.dataGrid.removeChildren();
+
+ var children = this.snapshotDataGridList.children;
+ var count = children.length;
+ for (var index = 0; index < count; ++index)
+ this.dataGrid.appendChild(children[index]);
+
+ this._updateSummaryGraph();
+ },
+
+ refreshShowAsPercents: function()
+ {
+ this._updatePercentButton();
+ this.refreshVisibleData();
+ },
+
+ _deleteSearchMatchedFlags: function(node)
+ {
+ delete node._searchMatchedConsColumn;
+ delete node._searchMatchedCountColumn;
+ delete node._searchMatchedSizeColumn;
+ delete node._searchMatchedCountDeltaColumn;
+ delete node._searchMatchedSizeDeltaColumn;
+ },
+
+ searchCanceled: function()
+ {
+ if (this._searchResults) {
+ for (var i = 0; i < this._searchResults.length; ++i) {
+ var profileNode = this._searchResults[i].profileNode;
+ this._deleteSearchMatchedFlags(profileNode);
+ profileNode.refresh();
+ }
+ }
+
+ delete this._searchFinishedCallback;
+ this._currentSearchResultIndex = -1;
+ this._searchResults = [];
+ },
+
+ performSearch: function(query, finishedCallback)
+ {
+ // Call searchCanceled since it will reset everything we need before doing a new search.
+ this.searchCanceled();
+
+ query = query.trim();
+
+ if (!query.length)
+ return;
+
+ this._searchFinishedCallback = finishedCallback;
+
+ var helper = WebInspector.HeapSnapshotView.SearchHelper;
+
+ var operationAndNumber = helper.parseOperationAndNumber(query);
+ var operation = operationAndNumber[0];
+ var queryNumber = operationAndNumber[1];
+
+ var percentUnits = helper.percents.test(query);
+ var megaBytesUnits = helper.megaBytes.test(query);
+ var kiloBytesUnits = helper.kiloBytes.test(query);
+ var bytesUnits = helper.bytes.test(query);
+
+ var queryNumberBytes = (megaBytesUnits ? (queryNumber * 1024 * 1024) : (kiloBytesUnits ? (queryNumber * 1024) : queryNumber));
+
+ function matchesQuery(heapSnapshotDataGridNode)
+ {
+ WebInspector.HeapSnapshotView.prototype._deleteSearchMatchedFlags(heapSnapshotDataGridNode);
+
+ if (percentUnits) {
+ heapSnapshotDataGridNode._searchMatchedCountColumn = operation(heapSnapshotDataGridNode.countPercent, queryNumber);
+ heapSnapshotDataGridNode._searchMatchedSizeColumn = operation(heapSnapshotDataGridNode.sizePercent, queryNumber);
+ heapSnapshotDataGridNode._searchMatchedCountDeltaColumn = operation(heapSnapshotDataGridNode.countDeltaPercent, queryNumber);
+ heapSnapshotDataGridNode._searchMatchedSizeDeltaColumn = operation(heapSnapshotDataGridNode.sizeDeltaPercent, queryNumber);
+ } else if (megaBytesUnits || kiloBytesUnits || bytesUnits) {
+ heapSnapshotDataGridNode._searchMatchedSizeColumn = operation(heapSnapshotDataGridNode.size, queryNumberBytes);
+ heapSnapshotDataGridNode._searchMatchedSizeDeltaColumn = operation(heapSnapshotDataGridNode.sizeDelta, queryNumberBytes);
+ } else {
+ heapSnapshotDataGridNode._searchMatchedCountColumn = operation(heapSnapshotDataGridNode.count, queryNumber);
+ heapSnapshotDataGridNode._searchMatchedCountDeltaColumn = operation(heapSnapshotDataGridNode.countDelta, queryNumber);
+ }
+
+ if (heapSnapshotDataGridNode.constructorName.hasSubstring(query, true))
+ heapSnapshotDataGridNode._searchMatchedConsColumn = true;
+
+ if (heapSnapshotDataGridNode._searchMatchedConsColumn ||
+ heapSnapshotDataGridNode._searchMatchedCountColumn ||
+ heapSnapshotDataGridNode._searchMatchedSizeColumn ||
+ heapSnapshotDataGridNode._searchMatchedCountDeltaColumn ||
+ heapSnapshotDataGridNode._searchMatchedSizeDeltaColumn) {
+ heapSnapshotDataGridNode.refresh();
+ return true;
+ }
+
+ return false;
+ }
+
+ var current = this.snapshotDataGridList.children[0];
+ var depth = 0;
+ var info = {};
+
+ // The second and subsequent levels of heap snapshot nodes represent retainers,
+ // so recursive expansion will be infinite, since a graph is being traversed.
+ // So default to a recursion cap of 2 levels.
+ const maxDepth = 2;
+
+ while (current) {
+ if (matchesQuery(current))
+ this._searchResults.push({ profileNode: current });
+ current = current.traverseNextNode(false, null, (depth >= maxDepth), info);
+ depth += info.depthChange;
+ }
+
+ finishedCallback(this, this._searchResults.length);
+ },
+
+ // FIXME: move these methods to a superclass, inherit both views from it.
+ jumpToFirstSearchResult: WebInspector.CPUProfileView.prototype.jumpToFirstSearchResult,
+ jumpToLastSearchResult: WebInspector.CPUProfileView.prototype.jumpToLastSearchResult,
+ jumpToNextSearchResult: WebInspector.CPUProfileView.prototype.jumpToNextSearchResult,
+ jumpToPreviousSearchResult: WebInspector.CPUProfileView.prototype.jumpToPreviousSearchResult,
+ showingFirstSearchResult: WebInspector.CPUProfileView.prototype.showingFirstSearchResult,
+ showingLastSearchResult: WebInspector.CPUProfileView.prototype.showingLastSearchResult,
+ _jumpToSearchResult: WebInspector.CPUProfileView.prototype._jumpToSearchResult,
+
+ refreshVisibleData: function()
+ {
+ var child = this.dataGrid.children[0];
+ while (child) {
+ child.refresh();
+ child = child.traverseNextNode(false, null, true);
+ }
+ this._updateSummaryGraph();
+ },
+
+ _changeBase: function()
+ {
+ if (this.baseSnapshot.uid === this._getProfiles()[this.baseSelectElement.selectedIndex].uid)
+ return;
+
+ this._resetDataGridList(resetCompleted.bind(this));
+
+ function resetCompleted() {
+ this.refresh();
+
+ if (!this.currentQuery || !this._searchFinishedCallback || !this._searchResults)
+ return;
+
+ // The current search needs to be performed again. First negate out previous match
+ // count by calling the search finished callback with a negative number of matches.
+ // Then perform the search again with the same query and callback.
+ this._searchFinishedCallback(this, -this._searchResults.length);
+ this.performSearch(this.currentQuery, this._searchFinishedCallback);
+ }
+ },
+
+ _createSnapshotDataGridList: function()
+ {
+ if (this._snapshotDataGridList)
+ delete this._snapshotDataGridList;
+
+ this._snapshotDataGridList = new WebInspector.HeapSnapshotDataGridList(this, this.baseSnapshot.entries, this.profile.entries);
+ return this._snapshotDataGridList;
+ },
+
+ _getProfiles: function()
+ {
+ return WebInspector.panels.profiles.getProfiles(WebInspector.HeapSnapshotProfileType.TypeId);
+ },
+
+ _loadProfile: function(profile, callback)
+ {
+ if (profile._loaded) {
+ callback(profile);
+ return;
+ }
+
+ InspectorBackend.getProfile(profile.typeId, profile.uid, loadedCallback.bind(this));
+
+ function loadedCallback(loadedSnapshot) {
+ profile.children = loadedSnapshot.head.children;
+ profile.entries = loadedSnapshot.head.entries;
+ profile.lowlevels = loadedSnapshot.head.lowlevels;
+ this._prepareProfile(profile);
+ profile._loaded = true;
+ this.parent.updateProfile(profile);
+ callback(profile);
+ }
+ },
+
+ _mouseDownInDataGrid: function(event)
+ {
+ if (event.detail < 2)
+ return;
+
+ var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
+ if (!cell || (!cell.hasStyleClass("count-column") && !cell.hasStyleClass("size-column") && !cell.hasStyleClass("countDelta-column") && !cell.hasStyleClass("sizeDelta-column")))
+ return;
+
+ if (cell.hasStyleClass("count-column"))
+ this.showCountAsPercent = !this.showCountAsPercent;
+ else if (cell.hasStyleClass("size-column"))
+ this.showSizeAsPercent = !this.showSizeAsPercent;
+ else if (cell.hasStyleClass("countDelta-column"))
+ this.showCountDeltaAsPercent = !this.showCountDeltaAsPercent;
+ else if (cell.hasStyleClass("sizeDelta-column"))
+ this.showSizeDeltaAsPercent = !this.showSizeDeltaAsPercent;
+
+ this.refreshShowAsPercents();
+
+ event.preventDefault();
+ event.stopPropagation();
+ },
+
+ get _isShowingAsPercent()
+ {
+ return this.showCountAsPercent && this.showSizeAsPercent && this.showCountDeltaAsPercent && this.showSizeDeltaAsPercent;
+ },
+
+ _percentClicked: function(event)
+ {
+ var currentState = this._isShowingAsPercent;
+ this.showCountAsPercent = !currentState;
+ this.showSizeAsPercent = !currentState;
+ this.showCountDeltaAsPercent = !currentState;
+ this.showSizeDeltaAsPercent = !currentState;
+ this.refreshShowAsPercents();
+ },
+
+ _prepareProfile: function(profile)
+ {
+ for (var profileEntry in profile.entries)
+ profile.entries[profileEntry].retainers = {};
+ profile.clusters = {};
+
+ for (var addr in profile.children) {
+ var retainer = profile.children[addr];
+ var retainerId = retainer.constructorName + ':' + addr;
+ for (var childAddr in retainer) {
+ if (childAddr === 'constructorName') continue;
+ var item = retainer[childAddr];
+ var itemId = item.constructorName + ':' + childAddr;
+ if ((item.constructorName === 'Object' || item.constructorName === 'Array')) {
+ if (!(itemId in profile.clusters))
+ profile.clusters[itemId] = { constructorName: itemId, retainers: {} };
+ mergeRetainers(profile.clusters[itemId], item);
+ }
+ mergeRetainers(profile.entries[item.constructorName], item);
+ }
+ }
+
+ function mergeRetainers(entry, item)
+ {
+ if (!(retainer.constructorName in entry.retainers))
+ entry.retainers[retainer.constructorName] = { constructorName: retainer.constructorName, count: 0, clusters: {} };
+ var retainerEntry = entry.retainers[retainer.constructorName];
+ retainerEntry.count += item.count;
+ if (retainer.constructorName === 'Object' || retainer.constructorName === 'Array')
+ retainerEntry.clusters[retainerId] = true;
+ }
+ },
+
+ _resetDataGridList: function(callback)
+ {
+ this._loadProfile(this._getProfiles()[this.baseSelectElement.selectedIndex], profileLoaded.bind(this));
+
+ function profileLoaded(profile)
+ {
+ this.baseSnapshot = profile;
+ var lastComparator = WebInspector.HeapSnapshotDataGridList.propertyComparator("size", false);
+ if (this.snapshotDataGridList)
+ lastComparator = this.snapshotDataGridList.lastComparator;
+ this.snapshotDataGridList = this._createSnapshotDataGridList();
+ this.snapshotDataGridList.sort(lastComparator, true);
+ callback();
+ }
+ },
+
+ _sortData: function()
+ {
+ var sortAscending = this.dataGrid.sortOrder === "ascending";
+ var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
+ var sortProperty = {
+ cons: ["cons", null],
+ count: ["count", null],
+ size: ["size", "count"],
+ countDelta: this.showCountDeltaAsPercent ? ["countDeltaPercent", null] : ["countDelta", null],
+ sizeDelta: this.showSizeDeltaAsPercent ? ["sizeDeltaPercent", "countDeltaPercent"] : ["sizeDelta", "sizeDeltaPercent"]
+ }[sortColumnIdentifier];
+
+ this.snapshotDataGridList.sort(WebInspector.HeapSnapshotDataGridList.propertyComparator(sortProperty[0], sortProperty[1], sortAscending));
+
+ this.refresh();
+ },
+
+ _updateBaseOptions: function()
+ {
+ var list = this._getProfiles();
+ // We're assuming that snapshots can only be added.
+ if (this.baseSelectElement.length === list.length)
+ return;
+
+ for (var i = this.baseSelectElement.length, n = list.length; i < n; ++i) {
+ var baseOption = document.createElement("option");
+ var title = list[i].title;
+ if (!title.indexOf(UserInitiatedProfileName))
+ title = WebInspector.UIString("Snapshot %d", title.substring(UserInitiatedProfileName.length + 1));
+ baseOption.label = WebInspector.UIString("Compared to %s", title);
+ this.baseSelectElement.appendChild(baseOption);
+ }
+ },
+
+ _updatePercentButton: function()
+ {
+ if (this._isShowingAsPercent) {
+ this.percentButton.title = WebInspector.UIString("Show absolute counts and sizes.");
+ this.percentButton.toggled = true;
+ } else {
+ this.percentButton.title = WebInspector.UIString("Show counts and sizes as percentages.");
+ this.percentButton.toggled = false;
+ }
+ },
+
+ _updateSummaryGraph: function()
+ {
+ this.countsSummaryBar.calculator.showAsPercent = this._isShowingAsPercent;
+ this.countsSummaryBar.update(this.profile.lowlevels);
+
+ this.sizesSummaryBar.calculator.showAsPercent = this._isShowingAsPercent;
+ this.sizesSummaryBar.update(this.profile.lowlevels);
+ }
+};
+
+WebInspector.HeapSnapshotView.prototype.__proto__ = WebInspector.View.prototype;
+
+WebInspector.HeapSnapshotView.SearchHelper = {
+ // In comparators, we assume that a value from a node is passed as the first parameter.
+ operations: {
+ LESS: function (a, b) { return a !== null && a < b; },
+ LESS_OR_EQUAL: function (a, b) { return a !== null && a <= b; },
+ EQUAL: function (a, b) { return a !== null && a === b; },
+ GREATER_OR_EQUAL: function (a, b) { return a !== null && a >= b; },
+ GREATER: function (a, b) { return a !== null && a > b; }
+ },
+
+ operationParsers: {
+ LESS: /^<(\d+)/,
+ LESS_OR_EQUAL: /^<=(\d+)/,
+ GREATER_OR_EQUAL: /^>=(\d+)/,
+ GREATER: /^>(\d+)/
+ },
+
+ parseOperationAndNumber: function(query)
+ {
+ var operations = WebInspector.HeapSnapshotView.SearchHelper.operations;
+ var parsers = WebInspector.HeapSnapshotView.SearchHelper.operationParsers;
+ for (var operation in parsers) {
+ var match = query.match(parsers[operation]);
+ if (match !== null)
+ return [operations[operation], parseFloat(match[1])];
+ }
+ return [operations.EQUAL, parseFloat(query)];
+ },
+
+ percents: /%$/,
+
+ megaBytes: /MB$/i,
+
+ kiloBytes: /KB$/i,
+
+ bytes: /B$/i
+}
+
+WebInspector.HeapSummaryCalculator = function(lowLevelField)
+{
+ this.total = 1;
+ this.lowLevelField = lowLevelField;
+}
+
+WebInspector.HeapSummaryCalculator.prototype = {
+ computeSummaryValues: function(lowLevels)
+ {
+ var highLevels = { data: 0, code: 0 };
+ this.total = 0;
+ for (var item in lowLevels) {
+ var highItem = this._highFromLow(item);
+ if (highItem) {
+ var value = lowLevels[item][this.lowLevelField];
+ highLevels[highItem] += value;
+ this.total += value;
+ }
+ }
+ var result = { categoryValues: highLevels };
+ if (!this.showAsPercent)
+ result.total = this.total;
+ return result;
+ },
+
+ formatValue: function(value)
+ {
+ if (this.showAsPercent)
+ return WebInspector.UIString("%.2f%%", value / this.total * 100.0);
+ else
+ return this._valueToString(value);
+ },
+
+ get showAsPercent()
+ {
+ return this._showAsPercent;
+ },
+
+ set showAsPercent(x)
+ {
+ this._showAsPercent = x;
+ }
+}
+
+WebInspector.HeapSummaryCountCalculator = function()
+{
+ WebInspector.HeapSummaryCalculator.call(this, "count");
+}
+
+WebInspector.HeapSummaryCountCalculator.prototype = {
+ _highFromLow: function(type)
+ {
+ if (type === "CODE_TYPE" || type === "SHARED_FUNCTION_INFO_TYPE" || type === "SCRIPT_TYPE") return "code";
+ if (type === "STRING_TYPE" || type === "HEAP_NUMBER_TYPE" || type.match(/^JS_/)) return "data";
+ return null;
+ },
+
+ _valueToString: function(value)
+ {
+ return value.toString();
+ }
+}
+
+WebInspector.HeapSummaryCountCalculator.prototype.__proto__ = WebInspector.HeapSummaryCalculator.prototype;
+
+WebInspector.HeapSummarySizeCalculator = function()
+{
+ WebInspector.HeapSummaryCalculator.call(this, "size");
+}
+
+WebInspector.HeapSummarySizeCalculator.prototype = {
+ _highFromLow: function(type)
+ {
+ if (type === "CODE_TYPE" || type === "SHARED_FUNCTION_INFO_TYPE" || type === "SCRIPT_TYPE")
+ return "code";
+ if (type === "STRING_TYPE" || type === "HEAP_NUMBER_TYPE" || type.match(/^JS_/) || type.match(/_ARRAY_TYPE$/))
+ return "data";
+ return null;
+ },
+
+ _valueToString: Number.bytesToString
+}
+
+WebInspector.HeapSummarySizeCalculator.prototype.__proto__ = WebInspector.HeapSummaryCalculator.prototype;
+
+WebInspector.HeapSnapshotDataGridNodeWithRetainers = function(owningTree)
+{
+ this.tree = owningTree;
+
+ WebInspector.DataGridNode.call(this, null, this._hasRetainers);
+
+ this.addEventListener("populate", this._populate, this);
+};
+
+WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype = {
+ isEmptySet: function(set)
+ {
+ for (var x in set)
+ return false;
+ return true;
+ },
+
+ get _hasRetainers()
+ {
+ return !this.isEmptySet(this.retainers);
+ },
+
+ get _parent()
+ {
+ // For top-level nodes, return owning tree as a parent, not data grid.
+ return this.parent !== this.dataGrid ? this.parent : this.tree;
+ },
+
+ _populate: function(event)
+ {
+ function appendDiffEntry(baseItem, snapshotItem)
+ {
+ this.appendChild(new WebInspector.HeapSnapshotDataGridRetainerNode(this.snapshotView, baseItem, snapshotItem, this.tree));
+ }
+
+ this.produceDiff(this.baseRetainers, this.retainers, appendDiffEntry.bind(this));
+
+ if (this._parent) {
+ var currentComparator = this._parent.lastComparator;
+ if (currentComparator)
+ this.sort(currentComparator, true);
+ }
+
+ this.removeEventListener("populate", this._populate, this);
+ },
+
+ produceDiff: function(baseEntries, currentEntries, callback)
+ {
+ for (var item in currentEntries)
+ callback(baseEntries[item], currentEntries[item]);
+
+ for (item in baseEntries) {
+ if (!(item in currentEntries))
+ callback(baseEntries[item], null);
+ }
+ },
+
+ sort: function(comparator, force) {
+ if (!force && this.lastComparator === comparator)
+ return;
+
+ this.children.sort(comparator);
+ var childCount = this.children.length;
+ for (var childIndex = 0; childIndex < childCount; ++childIndex)
+ this.children[childIndex]._recalculateSiblings(childIndex);
+ for (var i = 0; i < this.children.length; ++i) {
+ var child = this.children[i];
+ if (!force && (!child.expanded || child.lastComparator === comparator))
+ continue;
+ child.sort(comparator, force);
+ }
+ this.lastComparator = comparator;
+ },
+
+ signForDelta: function(delta) {
+ if (delta === 0)
+ return "";
+ if (delta > 0)
+ return "+";
+ else
+ return "\u2212"; // Math minus sign, same width as plus.
+ },
+
+ showDeltaAsPercent: function(value)
+ {
+ if (value === Number.POSITIVE_INFINITY)
+ return WebInspector.UIString("new");
+ else if (value === Number.NEGATIVE_INFINITY)
+ return WebInspector.UIString("deleted");
+ if (value > 1000.0)
+ return WebInspector.UIString("%s >1000%%", this.signForDelta(value));
+ return WebInspector.UIString("%s%.2f%%", this.signForDelta(value), Math.abs(value));
+ },
+
+ getTotalCount: function()
+ {
+ if (!this._count) {
+ this._count = 0;
+ for (var i = 0, n = this.children.length; i < n; ++i)
+ this._count += this.children[i].count;
+ }
+ return this._count;
+ },
+
+ getTotalSize: function()
+ {
+ if (!this._size) {
+ this._size = 0;
+ for (var i = 0, n = this.children.length; i < n; ++i)
+ this._size += this.children[i].size;
+ }
+ return this._size;
+ },
+
+ get countPercent()
+ {
+ return this.count / this._parent.getTotalCount() * 100.0;
+ },
+
+ get sizePercent()
+ {
+ return this.size / this._parent.getTotalSize() * 100.0;
+ },
+
+ get countDeltaPercent()
+ {
+ if (this.baseCount > 0) {
+ if (this.count > 0)
+ return this.countDelta / this.baseCount * 100.0;
+ else
+ return Number.NEGATIVE_INFINITY;
+ } else
+ return Number.POSITIVE_INFINITY;
+ },
+
+ get sizeDeltaPercent()
+ {
+ if (this.baseSize > 0) {
+ if (this.size > 0)
+ return this.sizeDelta / this.baseSize * 100.0;
+ else
+ return Number.NEGATIVE_INFINITY;
+ } else
+ return Number.POSITIVE_INFINITY;
+ },
+
+ get data()
+ {
+ var data = {};
+
+ data["cons"] = this.constructorName;
+
+ if (this.snapshotView.showCountAsPercent)
+ data["count"] = WebInspector.UIString("%.2f%%", this.countPercent);
+ else
+ data["count"] = this.count;
+
+ if (this.size !== null) {
+ if (this.snapshotView.showSizeAsPercent)
+ data["size"] = WebInspector.UIString("%.2f%%", this.sizePercent);
+ else
+ data["size"] = Number.bytesToString(this.size);
+ } else
+ data["size"] = "";
+
+ if (this.snapshotView.showCountDeltaAsPercent)
+ data["countDelta"] = this.showDeltaAsPercent(this.countDeltaPercent);
+ else
+ data["countDelta"] = WebInspector.UIString("%s%d", this.signForDelta(this.countDelta), Math.abs(this.countDelta));
+
+ if (this.sizeDelta !== null) {
+ if (this.snapshotView.showSizeDeltaAsPercent)
+ data["sizeDelta"] = this.showDeltaAsPercent(this.sizeDeltaPercent);
+ else
+ data["sizeDelta"] = WebInspector.UIString("%s%s", this.signForDelta(this.sizeDelta), Number.bytesToString(Math.abs(this.sizeDelta)));
+ } else
+ data["sizeDelta"] = "";
+
+ return data;
+ },
+
+ createCell: function(columnIdentifier)
+ {
+ var cell = WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier);
+
+ if ((columnIdentifier === "cons" && this._searchMatchedConsColumn) ||
+ (columnIdentifier === "count" && this._searchMatchedCountColumn) ||
+ (columnIdentifier === "size" && this._searchMatchedSizeColumn) ||
+ (columnIdentifier === "countDelta" && this._searchMatchedCountDeltaColumn) ||
+ (columnIdentifier === "sizeDelta" && this._searchMatchedSizeDeltaColumn))
+ cell.addStyleClass("highlight");
+
+ return cell;
+ }
+};
+
+WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.__proto__ = WebInspector.DataGridNode.prototype;
+
+WebInspector.HeapSnapshotDataGridNode = function(snapshotView, baseEntry, snapshotEntry, owningTree)
+{
+ this.snapshotView = snapshotView;
+
+ if (!snapshotEntry)
+ snapshotEntry = { constructorName: baseEntry.constructorName, count: 0, size: 0, retainers: {} };
+ this.constructorName = snapshotEntry.constructorName;
+ this.count = snapshotEntry.count;
+ this.size = snapshotEntry.size;
+ this.retainers = snapshotEntry.retainers;
+
+ if (!baseEntry)
+ baseEntry = { count: 0, size: 0, retainers: {} };
+ this.baseCount = baseEntry.count;
+ this.countDelta = this.count - this.baseCount;
+ this.baseSize = baseEntry.size;
+ this.sizeDelta = this.size - this.baseSize;
+ this.baseRetainers = baseEntry.retainers;
+
+ WebInspector.HeapSnapshotDataGridNodeWithRetainers.call(this, owningTree);
+};
+
+WebInspector.HeapSnapshotDataGridNode.prototype.__proto__ = WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype;
+
+WebInspector.HeapSnapshotDataGridList = function(snapshotView, baseEntries, snapshotEntries)
+{
+ this.tree = this;
+ this.snapshotView = snapshotView;
+ this.children = [];
+ this.lastComparator = null;
+ this.populateChildren(baseEntries, snapshotEntries);
+};
+
+WebInspector.HeapSnapshotDataGridList.prototype = {
+ appendChild: function(child)
+ {
+ this.insertChild(child, this.children.length);
+ },
+
+ insertChild: function(child, index)
+ {
+ this.children.splice(index, 0, child);
+ },
+
+ removeChildren: function()
+ {
+ this.children = [];
+ },
+
+ populateChildren: function(baseEntries, snapshotEntries)
+ {
+ function appendListEntry(baseItem, snapshotItem)
+ {
+ this.appendChild(new WebInspector.HeapSnapshotDataGridNode(this.snapshotView, baseItem, snapshotItem, this));
+ }
+ this.produceDiff(baseEntries, snapshotEntries, appendListEntry.bind(this));
+ },
+
+ produceDiff: WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.produceDiff,
+ sort: WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.sort,
+ getTotalCount: WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.getTotalCount,
+ getTotalSize: WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.getTotalSize
+};
+
+WebInspector.HeapSnapshotDataGridList.propertyComparators = [{}, {}];
+
+WebInspector.HeapSnapshotDataGridList.propertyComparator = function(property, property2, isAscending)
+{
+ var propertyHash = property + "#" + property2;
+ var comparator = this.propertyComparators[(isAscending ? 1 : 0)][propertyHash];
+ if (!comparator) {
+ comparator = function(lhs, rhs) {
+ var l = lhs[property], r = rhs[property];
+ if ((l === null || r === null) && property2 !== null)
+ l = lhs[property2], r = rhs[property2];
+ var result = l < r ? -1 : (l > r ? 1 : 0);
+ return isAscending ? result : -result;
+ };
+ this.propertyComparators[(isAscending ? 1 : 0)][propertyHash] = comparator;
+ }
+ return comparator;
+};
+
+WebInspector.HeapSnapshotDataGridRetainerNode = function(snapshotView, baseEntry, snapshotEntry, owningTree)
+{
+ this.snapshotView = snapshotView;
+
+ if (!snapshotEntry)
+ snapshotEntry = { constructorName: baseEntry.constructorName, count: 0, clusters: {} };
+ this.constructorName = snapshotEntry.constructorName;
+ this.count = snapshotEntry.count;
+ this.retainers = this._calculateRetainers(this.snapshotView.profile, snapshotEntry.clusters);
+
+ if (!baseEntry)
+ baseEntry = { count: 0, clusters: {} };
+ this.baseCount = baseEntry.count;
+ this.countDelta = this.count - this.baseCount;
+ this.baseRetainers = this._calculateRetainers(this.snapshotView.baseSnapshot, baseEntry.clusters);
+
+ this.size = null;
+ this.sizeDelta = null;
+
+ WebInspector.HeapSnapshotDataGridNodeWithRetainers.call(this, owningTree);
+}
+
+WebInspector.HeapSnapshotDataGridRetainerNode.prototype = {
+ get sizePercent()
+ {
+ return null;
+ },
+
+ get sizeDeltaPercent()
+ {
+ return null;
+ },
+
+ _calculateRetainers: function(snapshot, clusters)
+ {
+ var retainers = {};
+ if (this.isEmptySet(clusters)) {
+ if (this.constructorName in snapshot.entries)
+ return snapshot.entries[this.constructorName].retainers;
+ } else {
+ // In case when an entry is retained by clusters, we need to gather up the list
+ // of retainers by merging retainers of every cluster.
+ // E.g. having such a tree:
+ // A
+ // Object:1 10
+ // X 3
+ // Y 4
+ // Object:2 5
+ // X 6
+ //
+ // will result in a following retainers list: X 9, Y 4.
+ for (var clusterName in clusters) {
+ if (clusterName in snapshot.clusters) {
+ var clusterRetainers = snapshot.clusters[clusterName].retainers;
+ for (var clusterRetainer in clusterRetainers) {
+ var clusterRetainerEntry = clusterRetainers[clusterRetainer];
+ if (!(clusterRetainer in retainers))
+ retainers[clusterRetainer] = { constructorName: clusterRetainerEntry.constructorName, count: 0, clusters: {} };
+ retainers[clusterRetainer].count += clusterRetainerEntry.count;
+ for (var clusterRetainerCluster in clusterRetainerEntry.clusters)
+ retainers[clusterRetainer].clusters[clusterRetainerCluster] = true;
+ }
+ }
+ }
+ }
+ return retainers;
+ }
+};
+
+WebInspector.HeapSnapshotDataGridRetainerNode.prototype.__proto__ = WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype;
+
+
+WebInspector.HeapSnapshotProfileType = function()
+{
+ WebInspector.ProfileType.call(this, WebInspector.HeapSnapshotProfileType.TypeId, WebInspector.UIString("HEAP SNAPSHOTS"));
+}
+
+WebInspector.HeapSnapshotProfileType.TypeId = "HEAP";
+
+WebInspector.HeapSnapshotProfileType.prototype = {
+ get buttonTooltip()
+ {
+ return WebInspector.UIString("Take heap snapshot.");
+ },
+
+ get buttonStyle()
+ {
+ return "heap-snapshot-status-bar-item status-bar-item";
+ },
+
+ buttonClicked: function()
+ {
+ InspectorBackend.takeHeapSnapshot();
+ },
+
+ get welcomeMessage()
+ {
+ return WebInspector.UIString("Get a heap snapshot by pressing the %s button on the status bar.");
+ },
+
+ createSidebarTreeElementForProfile: function(profile)
+ {
+ return new WebInspector.ProfileSidebarTreeElement(profile, WebInspector.UIString("Snapshot %d"), "heap-snapshot-sidebar-tree-item");
+ },
+
+ createView: function(profile)
+ {
+ return new WebInspector.HeapSnapshotView(WebInspector.panels.profiles, profile);
+ }
+}
+
+WebInspector.HeapSnapshotProfileType.prototype.__proto__ = WebInspector.ProfileType.prototype;
diff --git a/WebCore/inspector/front-end/InjectedScriptAccess.js b/WebCore/inspector/front-end/InjectedScriptAccess.js
index ce264dd..cb3c2b8 100644
--- a/WebCore/inspector/front-end/InjectedScriptAccess.js
+++ b/WebCore/inspector/front-end/InjectedScriptAccess.js
@@ -76,9 +76,7 @@ InjectedScriptAccess._installHandler = function(methodName, async)
else
WebInspector.console.addMessage(WebInspector.ConsoleMessage.createTextMessage("Error dispatching: " + methodName));
}
- var callId = WebInspector.Callback.wrap(myCallback);
-
- InspectorBackend.dispatchOnInjectedScript(callId, this._worldId, methodName, argsString);
+ InspectorBackend.dispatchOnInjectedScript(this._worldId, methodName, argsString, myCallback);
};
}
diff --git a/WebCore/inspector/front-end/MetricsSidebarPane.js b/WebCore/inspector/front-end/MetricsSidebarPane.js
index ed5a7ec..18bc240 100644
--- a/WebCore/inspector/front-end/MetricsSidebarPane.js
+++ b/WebCore/inspector/front-end/MetricsSidebarPane.js
@@ -52,14 +52,14 @@ WebInspector.MetricsSidebarPane.prototype = {
var style = WebInspector.CSSStyleDeclaration.parseStyle(stylePayload);
self._update(style);
};
- InspectorBackend.getComputedStyle(WebInspector.Callback.wrap(callback), node.id);
+ InspectorBackend.getComputedStyle(node.id, callback);
var inlineStyleCallback = function(stylePayload) {
if (!stylePayload)
return;
self._inlineStyleId = stylePayload.id;
};
- InspectorBackend.getInlineStyle(WebInspector.Callback.wrap(inlineStyleCallback), node.id);
+ InspectorBackend.getInlineStyle(node.id, inlineStyleCallback);
},
_update: function(style)
@@ -210,7 +210,7 @@ WebInspector.MetricsSidebarPane.prototype = {
self.update();
};
- InspectorBackend.setStyleProperty(WebInspector.Callback.wrap(callback), this._inlineStyleId, context.styleProperty, userInput);
+ InspectorBackend.setStyleProperty(this._inlineStyleId, context.styleProperty, userInput, callback);
}
}
diff --git a/WebCore/inspector/front-end/ObjectPropertiesSection.js b/WebCore/inspector/front-end/ObjectPropertiesSection.js
index aab9546..015039c 100644
--- a/WebCore/inspector/front-end/ObjectPropertiesSection.js
+++ b/WebCore/inspector/front-end/ObjectPropertiesSection.js
@@ -184,6 +184,8 @@ WebInspector.ObjectPropertyTreeElement.prototype = {
this.valueElement.addStyleClass("dimmed");
if (this.property.value.isError())
this.valueElement.addStyleClass("error");
+ if (this.property.value.type)
+ this.valueElement.addStyleClass("console-formatted-" + this.property.value.type);
this.listItemElement.removeChildren();
diff --git a/WebCore/inspector/front-end/Panel.js b/WebCore/inspector/front-end/Panel.js
index 8cbdebb..2a4104f 100644
--- a/WebCore/inspector/front-end/Panel.js
+++ b/WebCore/inspector/front-end/Panel.js
@@ -72,6 +72,11 @@ WebInspector.Panel.prototype = {
return this._toolbarItem;
},
+ get name()
+ {
+ return this._panelName;
+ },
+
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 817f1f5..c325bf7 100644
--- a/WebCore/inspector/front-end/ProfileView.js
+++ b/WebCore/inspector/front-end/ProfileView.js
@@ -94,8 +94,7 @@ WebInspector.CPUProfileView = function(profile)
self._updatePercentButton();
}
- var callId = WebInspector.Callback.wrap(profileCallback);
- InspectorBackend.getProfile(callId, this.profile.uid);
+ InspectorBackend.getProfile(this.profile.typeId, this.profile.uid, profileCallback);
}
WebInspector.CPUProfileView.prototype = {
@@ -611,7 +610,7 @@ WebInspector.CPUProfileType.prototype = {
createSidebarTreeElementForProfile: function(profile)
{
- return new WebInspector.ProfileSidebarTreeElement(profile);
+ return new WebInspector.ProfileSidebarTreeElement(profile, WebInspector.UIString("Profile %d"), "profile-sidebar-tree-item");
},
createView: function(profile)
diff --git a/WebCore/inspector/front-end/ProfilesPanel.js b/WebCore/inspector/front-end/ProfilesPanel.js
index e18274c..2bd76f9 100644
--- a/WebCore/inspector/front-end/ProfilesPanel.js
+++ b/WebCore/inspector/front-end/ProfilesPanel.js
@@ -158,8 +158,7 @@ WebInspector.ProfilesPanel.prototype = {
show: function()
{
WebInspector.Panel.prototype.show.call(this);
- if (!this._profilesWereRequested)
- this._populateProfiles();
+ this._populateProfiles();
},
profilerWasEnabled: function()
@@ -321,6 +320,7 @@ WebInspector.ProfilesPanel.prototype = {
this.welcomeView.hide();
if (!this.visibleView)
this.showProfile(profile);
+ this.dispatchEventToListeners("profile added");
}
},
@@ -345,7 +345,7 @@ WebInspector.ProfilesPanel.prototype = {
sidebarParent.removeChild(profile._profilesTreeElement);
if (!profile.isTemporary)
- InspectorBackend.removeProfile(profile.uid);
+ InspectorBackend.removeProfile(profile.typeId, profile.uid);
// No other item will be selected if there aren't any other profiles, so
// make sure that view gets cleared when the last profile is removed.
@@ -376,6 +376,27 @@ WebInspector.ProfilesPanel.prototype = {
this.profileViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
},
+ getProfiles: function(typeId)
+ {
+ var result = [];
+ var profilesCount = this._profiles.length;
+ for (var i = 0; i < profilesCount; ++i)
+ if (this._profiles[i].typeId === typeId)
+ result.push(this._profiles[i]);
+ return result;
+ },
+
+ updateProfile: function(profile)
+ {
+ var profilesCount = this._profiles.length;
+ for (var i = 0; i < profilesCount; ++i)
+ if (this._profiles[i].typeId === profile.typeId
+ && this._profiles[i].uid === profile.uid) {
+ this._profiles[i] = profile;
+ break;
+ }
+ },
+
showView: function(view)
{
this.showProfile(view.profile);
@@ -510,12 +531,8 @@ WebInspector.ProfilesPanel.prototype = {
_populateProfiles: function()
{
- var sidebarTreeChildrenCount = this.sidebarTree.children.length;
- for (var i = 0; i < sidebarTreeChildrenCount; ++i) {
- var treeElement = this.sidebarTree.children[i];
- if (treeElement.children.length)
- return;
- }
+ if (!this._profilerEnabled || this._profilesWereRequested)
+ return;
function populateCallback(profileHeaders) {
profileHeaders.sort(function(a, b) { return a.uid - b.uid; });
@@ -524,8 +541,7 @@ WebInspector.ProfilesPanel.prototype = {
WebInspector.addProfileHeader(profileHeaders[i]);
}
- var callId = WebInspector.Callback.wrap(populateCallback);
- InspectorBackend.getProfileHeaders(callId);
+ InspectorBackend.getProfileHeaders(populateCallback);
this._profilesWereRequested = true;
},
@@ -541,14 +557,15 @@ WebInspector.ProfilesPanel.prototype = {
WebInspector.ProfilesPanel.prototype.__proto__ = WebInspector.Panel.prototype;
-WebInspector.ProfileSidebarTreeElement = function(profile)
+WebInspector.ProfileSidebarTreeElement = function(profile, titleFormat, className)
{
this.profile = profile;
+ this._titleFormat = titleFormat;
if (this.profile.title.indexOf(UserInitiatedProfileName) === 0)
this._profileNumber = this.profile.title.substring(UserInitiatedProfileName.length + 1);
- WebInspector.SidebarTreeElement.call(this, "profile-sidebar-tree-item", "", "", profile, false);
+ WebInspector.SidebarTreeElement.call(this, className, "", "", profile, false);
this.refreshTitles();
}
@@ -570,7 +587,7 @@ WebInspector.ProfileSidebarTreeElement.prototype = {
if (this._mainTitle)
return this._mainTitle;
if (this.profile.title.indexOf(UserInitiatedProfileName) === 0)
- return WebInspector.UIString("Profile %d", this._profileNumber);
+ return WebInspector.UIString(this._titleFormat, this._profileNumber);
return this.profile.title;
},
diff --git a/WebCore/inspector/front-end/ResourcesPanel.js b/WebCore/inspector/front-end/ResourcesPanel.js
index ff0d1ab..27df5cf 100644
--- a/WebCore/inspector/front-end/ResourcesPanel.js
+++ b/WebCore/inspector/front-end/ResourcesPanel.js
@@ -883,7 +883,7 @@ WebInspector.ResourcesPanel.prototype.__proto__ = WebInspector.AbstractTimelineP
WebInspector.getResourceContent = function(identifier, callback)
{
- InspectorBackend.getResourceContent(WebInspector.Callback.wrap(callback), identifier);
+ InspectorBackend.getResourceContent(identifier, callback);
}
WebInspector.ResourceTimeCalculator = function(startAtZero)
diff --git a/WebCore/inspector/front-end/ScriptView.js b/WebCore/inspector/front-end/ScriptView.js
index 74dc30a..d878e9b 100644
--- a/WebCore/inspector/front-end/ScriptView.js
+++ b/WebCore/inspector/front-end/ScriptView.js
@@ -56,10 +56,8 @@ WebInspector.ScriptView.prototype = {
if (this.script.source)
this._sourceFrameSetupFinished();
- else {
- var callbackId = WebInspector.Callback.wrap(this._didGetScriptSource.bind(this))
- InspectorBackend.getScriptSource(callbackId, this.script.sourceID);
- }
+ else
+ InspectorBackend.getScriptSource(this.script.sourceID, this._didGetScriptSource.bind(this));
},
_didGetScriptSource: function(source)
diff --git a/WebCore/inspector/front-end/ScriptsPanel.js b/WebCore/inspector/front-end/ScriptsPanel.js
index 7521ea9..75fd6f7 100644
--- a/WebCore/inspector/front-end/ScriptsPanel.js
+++ b/WebCore/inspector/front-end/ScriptsPanel.js
@@ -343,8 +343,7 @@ WebInspector.ScriptsPanel.prototype = {
WebInspector.breakpointManager.setBreakpoint(sourceID, breakpoint.url, newLine, breakpoint.enabled, breakpoint.condition);
}
};
- var callbackId = WebInspector.Callback.wrap(mycallback.bind(this))
- InspectorBackend.editScriptSource(callbackId, sourceID, newContent);
+ InspectorBackend.editScriptSource(sourceID, newContent, mycallback.bind(this));
},
selectedCallFrameId: function()
diff --git a/WebCore/inspector/front-end/Settings.js b/WebCore/inspector/front-end/Settings.js
index 33a1b91..41d82f9 100644
--- a/WebCore/inspector/front-end/Settings.js
+++ b/WebCore/inspector/front-end/Settings.js
@@ -81,10 +81,10 @@ WebInspector.Settings.initialize = function()
WebInspector.sessionSettings.dispatchEventToListeners("loaded");
}
- InspectorBackend.getSettings(WebInspector.Callback.wrap(function(settings) {
+ InspectorBackend.getSettings(function(settings) {
populateApplicationSettings(settings.application);
populateSessionSettings(settings.session);
- }));
+ });
}
WebInspector.Settings.prototype = {
diff --git a/WebCore/inspector/front-end/SourceCSSTokenizer.re2js b/WebCore/inspector/front-end/SourceCSSTokenizer.re2js
index b4d3eef..f4628d2 100644
--- a/WebCore/inspector/front-end/SourceCSSTokenizer.re2js
+++ b/WebCore/inspector/front-end/SourceCSSTokenizer.re2js
@@ -48,7 +48,7 @@ WebInspector.SourceCSSTokenizer = function()
this._valueKeywords = [
"above", "absolute", "activeborder", "activecaption", "afar", "after-white-space", "ahead", "alias", "all", "all-scroll",
- "alternate", "always","amharic", "amharic-abegede", "antialiased", "appworkspace", "aqua", "arabic-indic", "armenian",
+ "alternate", "always","amharic", "amharic-abegede", "antialiased", "appworkspace", "aqua", "arabic-indic", "armenian", "asterisks",
"auto", "avoid", "background", "backwards", "baseline", "below", "bidi-override", "binary", "bengali", "black", "blink",
"block", "block-axis", "blue", "bold", "bolder", "border", "border-box", "both", "bottom", "break-all", "break-word", "button",
"button-bevel", "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "cambodian", "capitalize", "caps-lock-indicator",
@@ -61,7 +61,7 @@ WebInspector.SourceCSSTokenizer = function()
"ethiopic-abegede-ti-er", "ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er", "ethiopic-halehame-aa-et",
"ethiopic-halehame-am-et", "ethiopic-halehame-gez", "ethiopic-halehame-om-et", "ethiopic-halehame-sid-et",
"ethiopic-halehame-so-et", "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig", "ew-resize", "expanded",
- "extra-condensed", "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "forwards", "from", "fuchsia", "geometricPrecision",
+ "extra-condensed", "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "footnotes", "forwards", "from", "fuchsia", "geometricPrecision",
"georgian", "gray", "graytext", "green", "grey", "groove", "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew", "help",
"hidden", "hide", "higher", "highlight", "highlighttext", "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore",
"inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite", "infobackground", "infotext", "inherit", "initial", "inline",
diff --git a/WebCore/inspector/front-end/WebKit.qrc b/WebCore/inspector/front-end/WebKit.qrc
index 4901857..b640936 100644
--- a/WebCore/inspector/front-end/WebKit.qrc
+++ b/WebCore/inspector/front-end/WebKit.qrc
@@ -4,6 +4,7 @@
<file>AbstractTimelinePanel.js</file>
<file>ApplicationCacheItemsView.js</file>
<file>AuditCategories.js</file>
+ <file>AuditFormatters.js</file>
<file>AuditLauncherView.js</file>
<file>AuditResultView.js</file>
<file>AuditRules.js</file>
@@ -35,11 +36,14 @@
<file>ElementsTreeOutline.js</file>
<file>EventListenersSidebarPane.js</file>
<file>ExtensionAPI.js</file>
+ <file>ExtensionAuditCategory.js</file>
+ <file>ExtensionCommon.js</file>
<file>ExtensionPanel.js</file>
<file>ExtensionRegistryStub.js</file>
<file>ExtensionServer.js</file>
<file>FontView.js</file>
<file>HAREntry.js</file>
+ <file>HeapSnapshotView.js</file>
<file>HelpScreen.js</file>
<file>ImageView.js</file>
<file>InjectedFakeWorker.js</file>
diff --git a/WebCore/inspector/front-end/inspector.css b/WebCore/inspector/front-end/inspector.css
index 4319816..a3ffa44 100644
--- a/WebCore/inspector/front-end/inspector.css
+++ b/WebCore/inspector/front-end/inspector.css
@@ -3910,6 +3910,115 @@ button.enable-toggle-status-bar-item .glyph {
-webkit-mask-image: url(Images/reloadButtonGlyph.png);
}
+/* Heap Snapshot View Styles */
+
+/* FIXME: move to a separate css file */
+.heap-snapshot-sidebar-tree-item .icon {
+ content: url(Images/profileIcon.png);
+}
+
+.heap-snapshot-sidebar-tree-item.small .icon {
+ content: url(Images/profileSmallIcon.png);
+}
+
+.heap-snapshot-view {
+ display: none;
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+}
+
+.heap-snapshot-view.visible {
+ display: block;
+}
+
+.heap-snapshot-view .data-grid {
+ border: none;
+ max-height: 100%;
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 93px;
+}
+
+.heap-snapshot-view .data-grid th.count-column {
+ text-align: center;
+}
+
+.heap-snapshot-view .data-grid td.count-column {
+ text-align: right;
+}
+
+.heap-snapshot-view .data-grid th.size-column {
+ text-align: center;
+}
+
+.heap-snapshot-view .data-grid td.size-column {
+ text-align: right;
+}
+
+.heap-snapshot-view .data-grid th.countDelta-column {
+ text-align: center;
+}
+
+.heap-snapshot-view .data-grid td.countDelta-column {
+ text-align: right;
+}
+
+.heap-snapshot-view .data-grid th.sizeDelta-column {
+ text-align: center;
+}
+
+.heap-snapshot-view .data-grid td.sizeDelta-column {
+ text-align: right;
+}
+
+#heap-snapshot-summary-container {
+ position: absolute;
+ padding-top: 20px;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 93px;
+ margin-left: -1px;
+ border-left: 1px solid rgb(102, 102, 102);
+ background-color: rgb(101, 111, 130);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0)));
+ background-repeat: repeat-x;
+ background-position: top;
+ text-align: center;
+ text-shadow: black 0 1px 1px;
+ white-space: nowrap;
+ color: white;
+ -webkit-background-size: 1px 6px;
+ -webkit-background-origin: padding;
+ -webkit-background-clip: padding;
+}
+
+.heap-snapshot-summary {
+ display: inline-block;
+ width: 50%;
+ min-width: 300px;
+ position: relative;
+}
+
+.heap-snapshot-summary canvas.summary-graph {
+ width: 225px;
+}
+
+.heap-snapshot-summary-label {
+ font-size: 12px;
+ font-weight: bold;
+ position: absolute;
+ top: 1px;
+ width: 50%;
+ left: 25%;
+}
+
.delete-storage-status-bar-item .glyph {
-webkit-mask-image: url(Images/excludeButtonGlyph.png);
}
diff --git a/WebCore/inspector/front-end/inspector.html b/WebCore/inspector/front-end/inspector.html
index 14e2cdc..3e4b6c1 100644
--- a/WebCore/inspector/front-end/inspector.html
+++ b/WebCore/inspector/front-end/inspector.html
@@ -98,6 +98,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<script type="text/javascript" src="ProfilesPanel.js"></script>
<script type="text/javascript" src="ConsolePanel.js"></script>
<script type="text/javascript" src="ExtensionAPI.js"></script>
+ <script type="text/javascript" src="ExtensionAuditCategory.js"></script>
+ <script type="text/javascript" src="ExtensionCommon.js"></script>
<script type="text/javascript" src="ExtensionServer.js"></script>
<script type="text/javascript" src="ExtensionPanel.js"></script>
<script type="text/javascript" src="AuditsPanel.js"></script>
@@ -105,6 +107,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<script type="text/javascript" src="AuditLauncherView.js"></script>
<script type="text/javascript" src="AuditRules.js"></script>
<script type="text/javascript" src="AuditCategories.js"></script>
+ <script type="text/javascript" src="AuditFormatters.js"></script>
<script type="text/javascript" src="ResourceView.js"></script>
<script type="text/javascript" src="SourceFrame.js"></script>
<script type="text/javascript" src="DOMSyntaxHighlighter.js"></script>
@@ -125,6 +128,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<script type="text/javascript" src="BottomUpProfileDataGridTree.js"></script>
<script type="text/javascript" src="TopDownProfileDataGridTree.js"></script>
<script type="text/javascript" src="ProfileView.js"></script>
+ <script type="text/javascript" src="HeapSnapshotView.js"></script>
<script type="text/javascript" src="DOMAgent.js"></script>
<script type="text/javascript" src="InjectedScript.js"></script>
<script type="text/javascript" src="InjectedScriptAccess.js"></script>
diff --git a/WebCore/inspector/front-end/inspector.js b/WebCore/inspector/front-end/inspector.js
index db89e20..0bff335 100644
--- a/WebCore/inspector/front-end/inspector.js
+++ b/WebCore/inspector/front-end/inspector.js
@@ -233,6 +233,8 @@ var WebInspector = {
if (hiddenPanels.indexOf("profiles") === -1) {
this.panels.profiles = new WebInspector.ProfilesPanel();
this.panels.profiles.registerProfileType(new WebInspector.CPUProfileType());
+ if (Preferences.heapProfilerPresent)
+ this.panels.profiles.registerProfileType(new WebInspector.HeapSnapshotProfileType());
}
if (hiddenPanels.indexOf("storage") === -1 && hiddenPanels.indexOf("databases") === -1)
this.panels.storage = new WebInspector.StoragePanel();
@@ -583,7 +585,7 @@ WebInspector.doLoadedDone = function()
InspectorBackend.populateScriptObjects();
// As a DOMAgent method, this needs to happen after the frontend has loaded and the agent is available.
- InspectorBackend.getSupportedCSSProperties(WebInspector.Callback.wrap(WebInspector.CSSCompletions._load));
+ InspectorBackend.getSupportedCSSProperties(WebInspector.CSSCompletions._load);
}
WebInspector.addPanelToolbarIcon = function(toolbarElement, panel, previousToolbarItem)
@@ -632,27 +634,29 @@ WebInspector.dispatch = function(message) {
WebInspector_syncDispatch = function(message)
{
var messageObject = (typeof message === "string") ? JSON.parse(message) : message;
- if (messageObject.type === "response" && !messageObject.success) {
- WebInspector.removeResponseCallbackEntry(messageObject.seq)
- WebInspector.reportProtocolError(messageObject);
- return;
- }
var arguments = [];
if (messageObject.data)
for (var key in messageObject.data)
arguments.push(messageObject.data[key]);
+ if ("seq" in messageObject) { // just a response for some request
+ if (messageObject.success)
+ WebInspector.processResponse(messageObject.seq, arguments);
+ else {
+ WebInspector.removeResponseCallbackEntry(messageObject.seq)
+ WebInspector.reportProtocolError(messageObject);
+ }
+ return;
+ }
+
if (messageObject.type === "event") {
- if (!messageObject.event in WebInspector) {
- console.error("Attempted to dispatch unimplemented WebInspector method: %s", messageObject.event);
+ if (!(messageObject.event in WebInspector)) {
+ console.error("Protocol Error: Attempted to dispatch an unimplemented WebInspector method '%s'", messageObject.event);
return;
}
WebInspector[messageObject.event].apply(WebInspector, arguments);
}
-
- if (messageObject.type === "response")
- WebInspector.processResponse(messageObject.seq, arguments);
}
WebInspector.dispatchMessageFromBackend = function(messageObject)
@@ -662,7 +666,7 @@ WebInspector.dispatchMessageFromBackend = function(messageObject)
WebInspector.reportProtocolError = function(messageObject)
{
- console.error("Error: InspectorBackend." + messageObject.command + " failed.");
+ console.error("Protocol Error: InspectorBackend request with seq = %d failed.", messageObject.seq);
for (var error in messageObject.errors)
console.error(" " + error);
WebInspector.removeResponseCallbackEntry(messageObject.seq);
@@ -1444,6 +1448,7 @@ WebInspector.failedToParseScriptSource = function(sourceURL, source, startingLin
WebInspector.pausedScript = function(callFrames)
{
this.panels.scripts.debuggerPaused(callFrames);
+ InspectorFrontendHost.bringToFront();
}
WebInspector.resumedScript = function()
diff --git a/WebCore/inspector/front-end/utilities.js b/WebCore/inspector/front-end/utilities.js
index 66cf284..e8adff6 100644
--- a/WebCore/inspector/front-end/utilities.js
+++ b/WebCore/inspector/front-end/utilities.js
@@ -732,12 +732,6 @@ Array.convert = function(list)
function insertionIndexForObjectInListSortedByFunction(anObject, aList, aFunction)
{
- // indexOf returns (-lowerBound - 1). Taking (-result - 1) works out to lowerBound.
- return (-indexOfObjectInListSortedByFunction(anObject, aList, aFunction) - 1);
-}
-
-function indexOfObjectInListSortedByFunction(anObject, aList, aFunction)
-{
var first = 0;
var last = aList.length - 1;
var floor = Math.floor;
@@ -760,9 +754,7 @@ function indexOfObjectInListSortedByFunction(anObject, aList, aFunction)
}
}
- // By returning 1 less than the negative lower search bound, we can reuse this function
- // for both indexOf and insertionIndexFor, with some simple arithmetic.
- return (-first - 1);
+ return first;
}
String.sprintf = function(format)