summaryrefslogtreecommitdiffstats
path: root/WebCore/inspector/front-end
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/inspector/front-end')
-rw-r--r--WebCore/inspector/front-end/Breakpoint.js21
-rw-r--r--WebCore/inspector/front-end/BreakpointsSidebarPane.js4
-rw-r--r--WebCore/inspector/front-end/CallStackSidebarPane.js11
-rw-r--r--WebCore/inspector/front-end/Color.js118
-rw-r--r--WebCore/inspector/front-end/ConsoleView.js318
-rw-r--r--WebCore/inspector/front-end/CookieItemsView.js275
-rw-r--r--WebCore/inspector/front-end/DOMAgent.js299
-rw-r--r--WebCore/inspector/front-end/DOMStorage.js46
-rw-r--r--WebCore/inspector/front-end/DOMStorageDataGrid.js42
-rw-r--r--WebCore/inspector/front-end/DOMStorageItemsView.js100
-rw-r--r--WebCore/inspector/front-end/DataGrid.js11
-rw-r--r--WebCore/inspector/front-end/Database.js51
-rw-r--r--WebCore/inspector/front-end/DatabaseQueryView.js32
-rw-r--r--WebCore/inspector/front-end/DatabaseTableView.js17
-rw-r--r--WebCore/inspector/front-end/Drawer.js6
-rw-r--r--WebCore/inspector/front-end/ElementsPanel.js475
-rw-r--r--WebCore/inspector/front-end/ElementsTreeOutline.js190
-rw-r--r--WebCore/inspector/front-end/EventListenersSidebarPane.js221
-rw-r--r--WebCore/inspector/front-end/ImageView.js1
-rw-r--r--WebCore/inspector/front-end/Images/cookie.pngbin0 -> 2246 bytes
-rw-r--r--WebCore/inspector/front-end/Images/domStorage.pngbin442 -> 0 bytes
-rw-r--r--WebCore/inspector/front-end/Images/errorRedDot.pngbin0 -> 549 bytes
-rw-r--r--WebCore/inspector/front-end/Images/grayConnectorPoint.pngbin0 -> 236 bytes
-rw-r--r--WebCore/inspector/front-end/Images/localStorage.pngbin0 -> 1081 bytes
-rw-r--r--WebCore/inspector/front-end/Images/paneSettingsButtons.pngbin0 -> 1422 bytes
-rw-r--r--WebCore/inspector/front-end/Images/sessionStorage.pngbin0 -> 1097 bytes
-rw-r--r--WebCore/inspector/front-end/Images/storageIcon.png (renamed from WebCore/inspector/front-end/Images/databasesIcon.png)bin7148 -> 7148 bytes
-rw-r--r--WebCore/inspector/front-end/Images/successGreenDot.pngbin0 -> 585 bytes
-rw-r--r--WebCore/inspector/front-end/Images/warningOrangeDot.pngbin0 -> 580 bytes
-rw-r--r--WebCore/inspector/front-end/Images/whiteConnectorPoint.pngbin0 -> 225 bytes
-rw-r--r--WebCore/inspector/front-end/InjectedScript.js784
-rw-r--r--WebCore/inspector/front-end/InjectedScriptAccess.js83
-rw-r--r--WebCore/inspector/front-end/MetricsSidebarPane.js6
-rw-r--r--WebCore/inspector/front-end/Object.js6
-rw-r--r--WebCore/inspector/front-end/ObjectPropertiesSection.js140
-rw-r--r--WebCore/inspector/front-end/ObjectProxy.js19
-rw-r--r--WebCore/inspector/front-end/Panel.js12
-rw-r--r--WebCore/inspector/front-end/Popup.js168
-rw-r--r--WebCore/inspector/front-end/ProfileDataGridTree.js7
-rw-r--r--WebCore/inspector/front-end/ProfileView.js33
-rw-r--r--WebCore/inspector/front-end/ProfilesPanel.js58
-rw-r--r--WebCore/inspector/front-end/PropertiesSidebarPane.js8
-rw-r--r--WebCore/inspector/front-end/Resource.js68
-rw-r--r--WebCore/inspector/front-end/ResourceView.js187
-rw-r--r--WebCore/inspector/front-end/ResourcesPanel.js435
-rw-r--r--WebCore/inspector/front-end/ScopeChainSidebarPane.js48
-rw-r--r--WebCore/inspector/front-end/ScriptsPanel.js80
-rw-r--r--WebCore/inspector/front-end/SourceFrame.js679
-rw-r--r--WebCore/inspector/front-end/SourceView.js9
-rw-r--r--WebCore/inspector/front-end/StatusBarButton.js118
-rw-r--r--WebCore/inspector/front-end/StoragePanel.js (renamed from WebCore/inspector/front-end/DatabasesPanel.js)269
-rw-r--r--WebCore/inspector/front-end/StylesSidebarPane.js501
-rw-r--r--WebCore/inspector/front-end/SummaryBar.js364
-rw-r--r--WebCore/inspector/front-end/TextPrompt.js2
-rw-r--r--WebCore/inspector/front-end/TimelineAgent.js54
-rw-r--r--WebCore/inspector/front-end/WatchExpressionsSidebarPane.js285
-rw-r--r--WebCore/inspector/front-end/WebKit.qrc23
-rw-r--r--WebCore/inspector/front-end/inspector.css351
-rw-r--r--WebCore/inspector/front-end/inspector.html22
-rw-r--r--WebCore/inspector/front-end/inspector.js275
-rw-r--r--WebCore/inspector/front-end/inspectorSyntaxHighlight.css71
-rw-r--r--WebCore/inspector/front-end/treeoutline.js29
-rw-r--r--WebCore/inspector/front-end/utilities.js396
63 files changed, 5335 insertions, 2493 deletions
diff --git a/WebCore/inspector/front-end/Breakpoint.js b/WebCore/inspector/front-end/Breakpoint.js
index 347df60..292975a 100644
--- a/WebCore/inspector/front-end/Breakpoint.js
+++ b/WebCore/inspector/front-end/Breakpoint.js
@@ -23,13 +23,14 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-WebInspector.Breakpoint = function(url, line, sourceID)
+WebInspector.Breakpoint = function(url, line, sourceID, condition)
{
this.url = url;
this.line = line;
this.sourceID = sourceID;
this._enabled = true;
this._sourceText = "";
+ this._condition = condition || "";
}
WebInspector.Breakpoint.prototype = {
@@ -71,6 +72,24 @@ WebInspector.Breakpoint.prototype = {
get id()
{
return this.sourceID + ":" + this.line;
+ },
+
+ get condition()
+ {
+ return this._condition;
+ },
+
+ set condition(c)
+ {
+ c = c || "";
+ if (this._condition === c)
+ return;
+
+ this._condition = c;
+ this.dispatchEventToListeners("condition-changed");
+
+ if (this.enabled)
+ InspectorController.updateBreakpoint(this.sourceID, this.line, c);
}
}
diff --git a/WebCore/inspector/front-end/BreakpointsSidebarPane.js b/WebCore/inspector/front-end/BreakpointsSidebarPane.js
index 14f8c06..e6edece 100644
--- a/WebCore/inspector/front-end/BreakpointsSidebarPane.js
+++ b/WebCore/inspector/front-end/BreakpointsSidebarPane.js
@@ -62,7 +62,7 @@ WebInspector.BreakpointsSidebarPane.prototype = {
return;
if (breakpoint.enabled)
- InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line);
+ InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line, breakpoint.condition);
},
_appendBreakpointElement: function(breakpoint)
@@ -150,7 +150,7 @@ WebInspector.BreakpointsSidebarPane.prototype = {
return;
if (breakpoint.enabled)
- InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line);
+ InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line, breakpoint.condition);
else
InspectorController.removeBreakpoint(breakpoint.sourceID, breakpoint.line);
},
diff --git a/WebCore/inspector/front-end/CallStackSidebarPane.js b/WebCore/inspector/front-end/CallStackSidebarPane.js
index c08cc7a..2fe4315 100644
--- a/WebCore/inspector/front-end/CallStackSidebarPane.js
+++ b/WebCore/inspector/front-end/CallStackSidebarPane.js
@@ -39,14 +39,14 @@ WebInspector.CallStackSidebarPane = function()
}
WebInspector.CallStackSidebarPane.prototype = {
- update: function(callFrame, sourceIDMap)
+ update: function(callFrames, sourceIDMap)
{
this.bodyElement.removeChildren();
this.placards = [];
delete this._selectedCallFrame;
- if (!callFrame) {
+ if (!callFrames) {
var infoElement = document.createElement("div");
infoElement.className = "info";
infoElement.textContent = WebInspector.UIString("Not Paused");
@@ -58,7 +58,8 @@ WebInspector.CallStackSidebarPane.prototype = {
var subtitle;
var scriptOrResource;
- do {
+ for (var i = 0; i < callFrames.length; ++i) {
+ var callFrame = callFrames[i];
switch (callFrame.type) {
case "function":
title = callFrame.functionName || WebInspector.UIString("(anonymous function)");
@@ -85,9 +86,7 @@ WebInspector.CallStackSidebarPane.prototype = {
this.placards.push(placard);
this.bodyElement.appendChild(placard.element);
-
- callFrame = callFrame.caller;
- } while (callFrame);
+ }
},
get selectedCallFrame()
diff --git a/WebCore/inspector/front-end/Color.js b/WebCore/inspector/front-end/Color.js
index 7968ee4..9d9cd76 100644
--- a/WebCore/inspector/front-end/Color.js
+++ b/WebCore/inspector/front-end/Color.js
@@ -30,7 +30,7 @@
WebInspector.Color = function(str)
{
this.value = str;
- this.parse();
+ this._parse();
}
WebInspector.Color.prototype = {
@@ -70,7 +70,7 @@ WebInspector.Color.prototype = {
return this._rgb;
if (this.simple)
- this._rgb = this.hexToRgb(this.hex);
+ this._rgb = this._hexToRGB(this.hex);
else {
var rgba = this.rgba;
this._rgb = [rgba[0], rgba[1], rgba[2]];
@@ -89,7 +89,7 @@ WebInspector.Color.prototype = {
if ("_hsl" in this)
return this._hsl;
- this._hsl = this.rgbToHsl(this.rgb);
+ this._hsl = this._rgbToHSL(this.rgb);
return this._hsl;
},
@@ -137,44 +137,34 @@ WebInspector.Color.prototype = {
return (shorthex && shorthex.length === 3);
},
- toRgb: function()
+ toString: function(format)
{
- return "rgb(" + this.rgb.join(", ") + ")";
- },
-
- toHsl: function()
- {
- var hsl = this.hsl;
- return "hsl(" + hsl[0] + ", " + hsl[1] + "%, " + hsl[2] + "%)";
- },
-
- toShortHex: function()
- {
- return "#" + this.shorthex;
- },
-
- toHex: function()
- {
- return "#" + this.hex;
- },
-
- toRgba: function()
- {
- return "rgba(" + this.rgba.join(", ") + ")";
- },
-
- toHsla: function()
- {
- var hsla = this.hsla;
- return "hsla(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%, " + hsla[3] + ")";
- },
+ if (!format)
+ format = this.format;
+
+ switch (format) {
+ case "rgb":
+ return "rgb(" + this.rgb.join(", ") + ")";
+ case "rgba":
+ return "rgba(" + this.rgba.join(", ") + ")";
+ case "hsl":
+ var hsl = this.hsl;
+ return "hsl(" + hsl[0] + ", " + hsl[1] + "%, " + hsl[2] + "%)";
+ case "hsla":
+ var hsla = this.hsla;
+ return "hsla(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%, " + hsla[3] + ")";
+ case "hex":
+ return "#" + this.hex;
+ case "shorthex":
+ return "#" + this.shorthex;
+ case "nickname":
+ return this.nickname;
+ }
- toNickname: function()
- {
- return this.nickname;
+ throw "invalid color format";
},
- rgbToHex: function(rgb)
+ _rgbToHex: function(rgb)
{
var r = parseInt(rgb[0]).toString(16);
var g = parseInt(rgb[1]).toString(16);
@@ -189,7 +179,7 @@ WebInspector.Color.prototype = {
return (r + g + b).toUpperCase();
},
- hexToRgb: function(hex)
+ _hexToRGB: function(hex)
{
var r = parseInt(hex.substring(0,2), 16);
var g = parseInt(hex.substring(2,4), 16);
@@ -198,7 +188,7 @@ WebInspector.Color.prototype = {
return [r, g, b];
},
- rgbToHsl: function(rgb)
+ _rgbToHSL: function(rgb)
{
var r = parseInt(rgb[0]) / 255;
var g = parseInt(rgb[1]) / 255;
@@ -235,7 +225,7 @@ WebInspector.Color.prototype = {
return [h, s, l];
},
- hslToRgb: function(hsl)
+ _hslToRGB: function(hsl)
{
var h = parseFloat(hsl[0]) / 360;
var s = parseFloat(hsl[1]) / 100;
@@ -252,12 +242,12 @@ WebInspector.Color.prototype = {
var tg = h;
var tb = h - (1 / 3);
- var r = Math.round(hueToRgb(p, q, tr) * 255);
- var g = Math.round(hueToRgb(p, q, tg) * 255);
- var b = Math.round(hueToRgb(p, q, tb) * 255);
+ var r = Math.round(hueToRGB(p, q, tr) * 255);
+ var g = Math.round(hueToRGB(p, q, tg) * 255);
+ var b = Math.round(hueToRGB(p, q, tb) * 255);
return [r, g, b];
- function hueToRgb(p, q, h) {
+ function hueToRGB(p, q, h) {
if (h < 0)
h += 1;
else if (h > 1)
@@ -274,28 +264,28 @@ WebInspector.Color.prototype = {
}
},
- rgbaToHsla: function(rgba)
+ _rgbaToHSLA: function(rgba)
{
var alpha = rgba[3];
- var hsl = this.rgbToHsl(rgba)
+ var hsl = this._rgbToHSL(rgba)
hsl.push(alpha);
return hsl;
},
- hslaToRgba: function(hsla)
+ _hslaToRGBA: function(hsla)
{
var alpha = hsla[3];
- var rgb = this.hslToRgb(hsla);
+ var rgb = this._hslToRGB(hsla);
rgb.push(alpha);
return rgb;
},
- parse: function()
+ _parse: function()
{
// Special Values - Advanced but Must Be Parsed First - transparent
var value = this.value.toLowerCase().replace(/%|\s+/g, "");
if (value in WebInspector.Color.AdvancedNickNames) {
- this.mode = "nickname";
+ this.format = "nickname";
var set = WebInspector.Color.AdvancedNickNames[value];
this.simple = false;
this.rgba = set[0];
@@ -314,30 +304,30 @@ WebInspector.Color.prototype = {
if (match[1]) { // hex
var hex = match[1].toUpperCase();
if (hex.length === 3) {
- this.mode = "shorthex";
+ this.format = "shorthex";
this.hex = hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2);
} else {
- this.mode = "hex";
+ this.format = "hex";
this.hex = hex;
}
} else if (match[2]) { // rgb
- this.mode = "rgb";
+ this.format = "rgb";
var rgb = match[2].split(/\s*,\s*/);
this.rgb = rgb;
- this.hex = this.rgbToHex(rgb);
+ this.hex = this._rgbToHex(rgb);
} else if (match[3]) { // nickname
var nickname = match[3].toLowerCase();
if (nickname in WebInspector.Color.Nicknames) {
- this.mode = "nickname";
+ this.format = "nickname";
this.hex = WebInspector.Color.Nicknames[nickname];
} else // unknown name
- throw("unknown color name");
+ throw "unknown color name";
} else if (match[4]) { // hsl
- this.mode = "hsl";
+ this.format = "hsl";
var hsl = match[4].replace(/%g/, "").split(/\s*,\s*/);
this.hsl = hsl;
- this.rgb = this.hslToRgb(hsl);
- this.hex = this.rgbToHex(this.rgb);
+ this.rgb = this._hslToRGB(hsl);
+ this.hex = this._rgbToHex(this.rgb);
}
// Fill in the values if this is a known hex color
@@ -358,14 +348,14 @@ WebInspector.Color.prototype = {
if (match) {
this.simple = false;
if (match[1]) { // rgba
- this.mode = "rgba";
+ this.format = "rgba";
this.rgba = match[1].split(/\s*,\s*/);
- this.hsla = this.rgbaToHsla(this.rgba);
+ this.hsla = this._rgbaToHSLA(this.rgba);
this.alpha = this.rgba[3];
} else if (match[2]) { // hsla
- this.mode = "hsla";
+ this.format = "hsla";
this.hsla = match[2].replace(/%/g, "").split(/\s*,\s*/);
- this.rgba = this.hslaToRgba(this.hsla);
+ this.rgba = this._hslaToRGBA(this.hsla);
this.alpha = this.hsla[3];
}
@@ -373,7 +363,7 @@ WebInspector.Color.prototype = {
}
// Could not parse as a valid color
- throw("could not parse color");
+ throw "could not parse color";
}
}
diff --git a/WebCore/inspector/front-end/ConsoleView.js b/WebCore/inspector/front-end/ConsoleView.js
index 6851eea..3782d32 100644
--- a/WebCore/inspector/front-end/ConsoleView.js
+++ b/WebCore/inspector/front-end/ConsoleView.js
@@ -57,10 +57,87 @@ WebInspector.ConsoleView = function(drawer)
var anchoredStatusBar = document.getElementById("anchored-status-bar-items");
anchoredStatusBar.appendChild(this.toggleConsoleButton);
-
+
+ // Will hold the list of filter elements
+ this.filterBarElement = document.getElementById("console-filter");
+
+ function createDividerElement() {
+ var dividerElement = document.createElement("div");
+
+ dividerElement.addStyleClass("divider");
+
+ this.filterBarElement.appendChild(dividerElement);
+ }
+
+ function createFilterElement(category) {
+ var categoryElement = document.createElement("li");
+ categoryElement.category = category;
+
+ categoryElement.addStyleClass(categoryElement.category);
+
+ var label = category.toString();
+ categoryElement.appendChild(document.createTextNode(label));
+
+ categoryElement.addEventListener("click", this._updateFilter.bind(this), false);
+
+ this.filterBarElement.appendChild(categoryElement);
+ return categoryElement;
+ }
+
+ this.allElement = createFilterElement.call(this, "All");
+
+ createDividerElement.call(this);
+
+ this.errorElement = createFilterElement.call(this, "Errors");
+ this.warningElement = createFilterElement.call(this, "Warnings");
+ this.logElement = createFilterElement.call(this, "Logs");
+
+ this.filter(this.allElement);
}
WebInspector.ConsoleView.prototype = {
+
+ _updateFilter: function(e)
+ {
+ this.filter(e.target);
+ },
+
+ filter: function(target)
+ {
+ if (target.category == "All") {
+ if (target.hasStyleClass("selected")) {
+ // We can't unselect all, so we break early here
+ return;
+ }
+
+ this.errorElement.removeStyleClass("selected");
+ this.warningElement.removeStyleClass("selected");
+ this.logElement.removeStyleClass("selected");
+
+ document.getElementById("console-messages").removeStyleClass("filter-errors");
+ document.getElementById("console-messages").removeStyleClass("filter-warnings");
+ document.getElementById("console-messages").removeStyleClass("filter-logs");
+ } else {
+ // Something other than all is being selected, so we want to unselect all
+ if (this.allElement.hasStyleClass("selected")) {
+ this.allElement.removeStyleClass("selected");
+ document.getElementById("console-messages").removeStyleClass("filter-all");
+ }
+ }
+
+ if (target.hasStyleClass("selected")) {
+ target.removeStyleClass("selected");
+ var newClass = "filter-" + target.category.toLowerCase();
+ var filterElement = document.getElementById("console-messages");
+ filterElement.removeStyleClass(newClass);
+ } else {
+ target.addStyleClass("selected");
+ var newClass = "filter-" + target.category.toLowerCase();
+ var filterElement = document.getElementById("console-messages");
+ filterElement.addStyleClass(newClass);
+ }
+ },
+
_toggleConsoleButtonClicked: function()
{
this.drawer.visibleView = this;
@@ -70,6 +147,7 @@ WebInspector.ConsoleView.prototype = {
{
mainElement.appendChild(this.element);
statusBarElement.appendChild(this.clearButton);
+ statusBarElement.appendChild(this.filterBarElement);
},
show: function()
@@ -175,7 +253,7 @@ WebInspector.ConsoleView.prototype = {
clearMessages: function(clearInspectorController)
{
if (clearInspectorController)
- InspectorController.clearMessages();
+ InspectorController.clearMessages(false);
if (WebInspector.panels.resources)
WebInspector.panels.resources.clearMessages();
@@ -212,10 +290,28 @@ WebInspector.ConsoleView.prototype = {
return;
var reportCompletions = this._reportCompletions.bind(this, bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix);
- this._evalInInspectedWindow(expressionString, reportCompletions);
+ // Collect comma separated object properties for the completion.
+
+ if (!expressionString) {
+ if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused) {
+ // Evaluate into properties in scope of the selected call frame.
+ reportCompletions(WebInspector.panels.scripts.variablesInSelectedCallFrame());
+ return;
+ } else {
+ expressionString = "this";
+ }
+ }
+
+ var includeInspectorCommandLineAPI = (!dotNotation && !bracketNotation);
+ if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused)
+ var callFrameId = WebInspector.panels.scripts.selectedCallFrameId();
+ InjectedScriptAccess.getCompletions(expressionString, includeInspectorCommandLineAPI, callFrameId, reportCompletions);
},
- _reportCompletions: function(bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix, result) {
+ _reportCompletions: function(bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix, result, isException) {
+ if (isException)
+ return;
+
if (bracketNotation) {
if (prefix.length && prefix[0] === "'")
var quoteUsed = "'";
@@ -224,16 +320,7 @@ WebInspector.ConsoleView.prototype = {
}
var results = [];
- var properties = Object.properties(result);
- if (!dotNotation && !bracketNotation && result._inspectorCommandLineAPI) {
- var commandLineAPI = Object.properties(result._inspectorCommandLineAPI);
- for (var i = 0; i < commandLineAPI.length; ++i) {
- var property = commandLineAPI[i];
- if (property.charAt(0) !== "_")
- properties.push(property);
- }
- }
- properties.sort();
+ var properties = Object.sortedProperties(result);
for (var i = 0; i < properties.length; ++i) {
var property = properties[i];
@@ -288,7 +375,7 @@ WebInspector.ConsoleView.prototype = {
if (!link || !link.representedNode)
return;
- WebInspector.updateFocusedNode(link.representedNode);
+ WebInspector.updateFocusedNode(link.representedNode.id);
event.stopPropagation();
event.preventDefault();
},
@@ -304,106 +391,27 @@ WebInspector.ConsoleView.prototype = {
this.prompt.handleKeyEvent(event);
},
- _evalInInspectedWindow: function(expression, callback)
+ evalInInspectedWindow: function(expression, objectGroup, callback)
{
if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused) {
- WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, false, callback);
+ WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, false, objectGroup, callback);
return;
}
- this.doEvalInWindow(expression, callback);
- },
-
- _ensureCommandLineAPIInstalled: function(inspectedWindow)
- {
- if (!inspectedWindow._inspectorCommandLineAPI) {
- inspectedWindow.eval("window._inspectorCommandLineAPI = { \
- $: function() { return document.getElementById.apply(document, arguments) }, \
- $$: function() { return document.querySelectorAll.apply(document, arguments) }, \
- $x: function(xpath, context) { \
- var nodes = []; \
- try { \
- var doc = context || document; \
- var results = doc.evaluate(xpath, doc, null, XPathResult.ANY_TYPE, null); \
- var node; \
- while (node = results.iterateNext()) nodes.push(node); \
- } catch (e) {} \
- return nodes; \
- }, \
- dir: function() { return console.dir.apply(console, arguments) }, \
- dirxml: function() { return console.dirxml.apply(console, arguments) }, \
- keys: function(o) { var a = []; for (var k in o) a.push(k); return a; }, \
- values: function(o) { var a = []; for (var k in o) a.push(o[k]); return a; }, \
- profile: function() { return console.profile.apply(console, arguments) }, \
- profileEnd: function() { return console.profileEnd.apply(console, arguments) }, \
- _inspectedNodes: [], \
- get $0() { return _inspectorCommandLineAPI._inspectedNodes[0] }, \
- get $1() { return _inspectorCommandLineAPI._inspectedNodes[1] }, \
- get $2() { return _inspectorCommandLineAPI._inspectedNodes[2] }, \
- get $3() { return _inspectorCommandLineAPI._inspectedNodes[3] }, \
- get $4() { return _inspectorCommandLineAPI._inspectedNodes[4] } \
- };");
-
- inspectedWindow._inspectorCommandLineAPI.clear = InspectorController.wrapCallback(this.clearMessages.bind(this));
- inspectedWindow._inspectorCommandLineAPI.inspect = InspectorController.wrapCallback(inspectObject.bind(this));
-
- function inspectObject(o)
- {
- if (arguments.length === 0)
- return;
-
- InspectorController.inspectedWindow().console.log(o);
- if (Object.type(o, InspectorController.inspectedWindow()) === "node") {
- WebInspector.showElementsPanel();
- WebInspector.panels.elements.treeOutline.revealAndSelectNode(o);
- } else {
- switch (Object.describe(o)) {
- case "Database":
- WebInspector.showDatabasesPanel();
- WebInspector.panels.databases.selectDatabase(o);
- break;
- case "Storage":
- WebInspector.showDatabasesPanel();
- WebInspector.panels.databases.selectDOMStorage(o);
- break;
- }
- }
- }
- }
+ this.doEvalInWindow(expression, objectGroup, callback);
},
- addInspectedNode: function(node)
- {
- var inspectedWindow = InspectorController.inspectedWindow();
- this._ensureCommandLineAPIInstalled(inspectedWindow);
- var inspectedNodes = inspectedWindow._inspectorCommandLineAPI._inspectedNodes;
- inspectedNodes.unshift(node);
- if (inspectedNodes.length >= 5)
- inspectedNodes.pop();
- },
-
- doEvalInWindow: function(expression, callback)
+ doEvalInWindow: function(expression, objectGroup, callback)
{
if (!expression) {
// There is no expression, so the completion should happen against global properties.
expression = "this";
}
- // Surround the expression in with statements to inject our command line API so that
- // the window object properties still take more precedent than our API functions.
- expression = "with (window._inspectorCommandLineAPI) { with (window) { " + expression + " } }";
-
- var self = this;
- function delayedEvaluation()
+ function evalCallback(result)
{
- var inspectedWindow = InspectorController.inspectedWindow();
- self._ensureCommandLineAPIInstalled(inspectedWindow);
- try {
- callback(inspectedWindow.eval(expression));
- } catch (e) {
- callback(e, true);
- }
- }
- setTimeout(delayedEvaluation, 0);
+ callback(result.value, result.isException);
+ };
+ InjectedScriptAccess.evaluate(expression, objectGroup, evalCallback);
},
_enterKeyPressed: function(event)
@@ -431,18 +439,23 @@ WebInspector.ConsoleView.prototype = {
self.prompt.text = "";
self.addMessage(new WebInspector.ConsoleCommandResult(result, exception, commandMessage));
}
- this._evalInInspectedWindow(str, printResult);
+ this.evalInInspectedWindow(str, "console", printResult);
},
_format: function(output, forceObjectFormat)
{
- var inspectedWindow = InspectorController.inspectedWindow();
+ var isProxy = (output != null && typeof output === "object");
+
if (forceObjectFormat)
var type = "object";
- else if (output instanceof inspectedWindow.NodeList)
- var type = "array";
else
- var type = Object.type(output, inspectedWindow);
+ var type = Object.proxyType(output);
+
+ if (isProxy && type !== "object" && type !== "function" && type !== "array" && type !== "node") {
+ // Unwrap primitive value, skip decoration.
+ output = output.description;
+ type = "undecorated"
+ }
// We don't perform any special formatting on these types, so we just
// pass them through the simple _formatvalue function.
@@ -451,8 +464,7 @@ WebInspector.ConsoleView.prototype = {
"null": 1,
"boolean": 1,
"number": 1,
- "date": 1,
- "function": 1,
+ "undecorated": 1
};
var formatter;
@@ -479,6 +491,16 @@ WebInspector.ConsoleView.prototype = {
elem.appendChild(document.createTextNode(val));
},
+ _formatfunction: function(func, elem)
+ {
+ elem.appendChild(document.createTextNode(func.description));
+ },
+
+ _formatdate: function(date, elem)
+ {
+ elem.appendChild(document.createTextNode(date));
+ },
+
_formatstring: function(str, elem)
{
elem.appendChild(document.createTextNode("\"" + str + "\""));
@@ -486,34 +508,48 @@ WebInspector.ConsoleView.prototype = {
_formatregexp: function(re, elem)
{
- var formatted = String(re).replace(/([\\\/])/g, "\\$1").replace(/\\(\/[gim]*)$/, "$1").substring(1);
+ var formatted = String(re.description).replace(/([\\\/])/g, "\\$1").replace(/\\(\/[gim]*)$/, "$1").substring(1);
elem.appendChild(document.createTextNode(formatted));
},
_formatarray: function(arr, elem)
{
- elem.appendChild(document.createTextNode("["));
- for (var i = 0; i < arr.length; ++i) {
- elem.appendChild(this._format(arr[i]));
- if (i < arr.length - 1)
- elem.appendChild(document.createTextNode(", "));
+ var self = this;
+ function printResult(properties)
+ {
+ if (!properties)
+ return;
+ elem.appendChild(document.createTextNode("["));
+ for (var i = 0; i < properties.length; ++i) {
+ var property = properties[i].value;
+ elem.appendChild(self._format(property));
+ if (i < properties.length - 1)
+ elem.appendChild(document.createTextNode(", "));
+ }
+ elem.appendChild(document.createTextNode("]"));
}
- elem.appendChild(document.createTextNode("]"));
+ InjectedScriptAccess.getProperties(arr, false, printResult);
},
- _formatnode: function(node, elem)
+ _formatnode: function(object, elem)
{
- var treeOutline = new WebInspector.ElementsTreeOutline();
- treeOutline.rootDOMNode = node;
- treeOutline.element.addStyleClass("outline-disclosure");
- if (!treeOutline.children[0].hasChildren)
- treeOutline.element.addStyleClass("single-node");
- elem.appendChild(treeOutline.element);
+ function printNode(nodeId)
+ {
+ if (!nodeId)
+ return;
+ var treeOutline = new WebInspector.ElementsTreeOutline();
+ treeOutline.rootDOMNode = WebInspector.domAgent.nodeForId(nodeId);
+ treeOutline.element.addStyleClass("outline-disclosure");
+ if (!treeOutline.children[0].hasChildren)
+ treeOutline.element.addStyleClass("single-node");
+ elem.appendChild(treeOutline.element);
+ }
+ InjectedScriptAccess.pushNodeToFrontend(object, printNode);
},
_formatobject: function(obj, elem)
{
- elem.appendChild(new WebInspector.ObjectPropertiesSection(new WebInspector.ObjectProxy(obj), Object.describe(obj, true), null, null, true).element);
+ elem.appendChild(new WebInspector.ObjectPropertiesSection(obj, obj.description, null, true).element);
},
_formaterror: function(obj, elem)
@@ -595,6 +631,13 @@ WebInspector.ConsoleMessage.prototype = {
if (!parameters.length)
return formattedResult;
+ // Formatting code below assumes that parameters are all wrappers whereas frontend console
+ // API allows passing arbitrary values as messages (strings, numberts, etc.). Wrap them here.
+ for (var i = 0; i < parameters.length; ++i) {
+ if (typeof parameters[i] !== "object" && typeof parameters[i] !== "function")
+ parameters[i] = WebInspector.ObjectProxy.wrapPrimitiveValue(parameters[i]);
+ }
+
function formatForConsole(obj)
{
return WebInspector.console._format(obj);
@@ -605,7 +648,7 @@ WebInspector.ConsoleMessage.prototype = {
return WebInspector.console._format(obj, true);
}
- if (Object.type(parameters[0], InspectorController.inspectedWindow()) === "string") {
+ if (Object.proxyType(parameters[0]) === "string") {
var formatters = {}
for (var i in String.standardFormatters)
formatters[i] = String.standardFormatters[i];
@@ -626,7 +669,7 @@ WebInspector.ConsoleMessage.prototype = {
return a;
}
- var result = String.format(parameters[0], parameters.slice(1), formatters, formattedResult, append);
+ var result = String.format(parameters[0].description, parameters.slice(1), formatters, formattedResult, append);
formattedResult = result.formattedResult;
parameters = result.unusedSubstitutions;
if (parameters.length)
@@ -634,8 +677,8 @@ WebInspector.ConsoleMessage.prototype = {
}
for (var i = 0; i < parameters.length; ++i) {
- if (typeof parameters[i] === "string")
- formattedResult.appendChild(WebInspector.linkifyStringAsFragment(parameters[i]));
+ if (Object.proxyType(parameters[i]) === "string")
+ formattedResult.appendChild(WebInspector.linkifyStringAsFragment(parameters[i].description));
else
formattedResult.appendChild(formatForConsole(parameters[i]));
@@ -683,6 +726,9 @@ WebInspector.ConsoleMessage.prototype = {
case WebInspector.ConsoleMessage.MessageLevel.Log:
element.addStyleClass("console-log-level");
break;
+ case WebInspector.ConsoleMessage.MessageLevel.Debug:
+ element.addStyleClass("console-debug-level");
+ break;
case WebInspector.ConsoleMessage.MessageLevel.Warning:
element.addStyleClass("console-warning-level");
break;
@@ -789,6 +835,9 @@ WebInspector.ConsoleMessage.prototype = {
case WebInspector.ConsoleMessage.MessageLevel.Warning:
levelString = "Warning";
break;
+ case WebInspector.ConsoleMessage.MessageLevel.Debug:
+ levelString = "Debug";
+ break;
case WebInspector.ConsoleMessage.MessageLevel.Error:
levelString = "Error";
break;
@@ -835,7 +884,8 @@ WebInspector.ConsoleMessage.MessageLevel = {
Tip: 0,
Log: 1,
Warning: 2,
- Error: 3
+ Error: 3,
+ Debug: 4
}
WebInspector.ConsoleCommand = function(command)
@@ -859,10 +909,18 @@ WebInspector.ConsoleCommand.prototype = {
}
}
+WebInspector.ConsoleTextMessage = function(text, level)
+{
+ level = level || WebInspector.ConsoleMessage.MessageLevel.Log;
+ WebInspector.ConsoleMessage.call(this, WebInspector.ConsoleMessage.MessageSource.JS, WebInspector.ConsoleMessage.MessageType.Log, level, 0, null, null, 1, text);
+}
+
+WebInspector.ConsoleTextMessage.prototype.__proto__ = WebInspector.ConsoleMessage.prototype;
+
WebInspector.ConsoleCommandResult = function(result, exception, originatingCommand)
{
var level = (exception ? WebInspector.ConsoleMessage.MessageLevel.Error : WebInspector.ConsoleMessage.MessageLevel.Log);
- var message = (exception ? String(result) : result);
+ var message = result;
var line = (exception ? result.line : -1);
var url = (exception ? result.sourceURL : null);
diff --git a/WebCore/inspector/front-end/CookieItemsView.js b/WebCore/inspector/front-end/CookieItemsView.js
new file mode 100644
index 0000000..9397e7c
--- /dev/null
+++ b/WebCore/inspector/front-end/CookieItemsView.js
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.CookieItemsView = function(cookieDomain)
+{
+ WebInspector.View.call(this);
+
+ this.element.addStyleClass("storage-view");
+ this.element.addStyleClass("table");
+
+ this.deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item");
+ this.deleteButton.visible = false;
+ this.deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false);
+
+ this.refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item");
+ this.refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false);
+
+ this._cookieDomain = cookieDomain;
+}
+
+WebInspector.CookieItemsView.prototype = {
+ get statusBarItems()
+ {
+ return [this.refreshButton.element, this.deleteButton.element];
+ },
+
+ show: function(parentElement)
+ {
+ WebInspector.View.prototype.show.call(this, parentElement);
+ this.update();
+ },
+
+ hide: function()
+ {
+ WebInspector.View.prototype.hide.call(this);
+ this.deleteButton.visible = false;
+ },
+
+ update: function()
+ {
+ this.element.removeChildren();
+
+ var self = this;
+ function callback(cookies, isAdvanced) {
+ var dataGrid = (isAdvanced ? self.dataGridForCookies(cookies) : self.simpleDataGridForCookies(cookies));
+ if (dataGrid) {
+ self._dataGrid = dataGrid;
+ self.element.appendChild(dataGrid.element);
+ self._dataGrid.updateWidths();
+ if (isAdvanced)
+ self.deleteButton.visible = true;
+ } else {
+ var emptyMsgElement = document.createElement("div");
+ emptyMsgElement.className = "storage-table-empty";
+ emptyMsgElement.textContent = WebInspector.UIString("This site has no cookies.");
+ self.element.appendChild(emptyMsgElement);
+ self._dataGrid = null;
+ self.deleteButton.visible = false;
+ }
+ }
+
+ WebInspector.Cookies.getCookiesAsync(callback, this._cookieDomain);
+ },
+
+ dataGridForCookies: function(cookies)
+ {
+ if (!cookies.length)
+ return null;
+
+ for (var i = 0; i < cookies.length; ++i)
+ cookies[i].expires = new Date(cookies[i].expires);
+
+ var columns = { 0: {}, 1: {}, 2: {}, 3: {}, 4: {}, 5: {}, 6: {}, 7: {} };
+ columns[0].title = WebInspector.UIString("Name");
+ columns[0].width = columns[0].title.length;
+ columns[1].title = WebInspector.UIString("Value");
+ columns[1].width = columns[1].title.length;
+ columns[2].title = WebInspector.UIString("Domain");
+ columns[2].width = columns[2].title.length;
+ columns[3].title = WebInspector.UIString("Path");
+ columns[3].width = columns[3].title.length;
+ columns[4].title = WebInspector.UIString("Expires");
+ columns[4].width = columns[4].title.length;
+ columns[5].title = WebInspector.UIString("Size");
+ columns[5].width = columns[5].title.length;
+ columns[5].aligned = "right";
+ columns[6].title = WebInspector.UIString("HTTP");
+ columns[6].width = columns[6].title.length;
+ columns[6].aligned = "centered";
+ columns[7].title = WebInspector.UIString("Secure");
+ columns[7].width = columns[7].title.length;
+ columns[7].aligned = "centered";
+
+ function updateDataAndColumn(index, value) {
+ data[index] = value;
+ if (value.length > columns[index].width)
+ columns[index].width = value.length;
+ }
+
+ var data;
+ var nodes = [];
+ for (var i = 0; i < cookies.length; ++i) {
+ var cookie = cookies[i];
+ data = {};
+
+ updateDataAndColumn(0, cookie.name);
+ updateDataAndColumn(1, cookie.value);
+ updateDataAndColumn(2, cookie.domain);
+ updateDataAndColumn(3, cookie.path);
+ updateDataAndColumn(4, (cookie.session ? WebInspector.UIString("Session") : cookie.expires.toGMTString()));
+ updateDataAndColumn(5, Number.bytesToString(cookie.size, WebInspector.UIString));
+ updateDataAndColumn(6, (cookie.httpOnly ? "\u2713" : "")); // Checkmark
+ updateDataAndColumn(7, (cookie.secure ? "\u2713" : "")); // Checkmark
+
+ var node = new WebInspector.DataGridNode(data, false);
+ node.cookie = cookie;
+ node.selectable = true;
+ nodes.push(node);
+ }
+
+ var totalColumnWidths = 0;
+ for (var columnIdentifier in columns)
+ totalColumnWidths += columns[columnIdentifier].width;
+
+ // Enforce the Value column (the 2nd column) to be a max of 33%
+ // tweaking the raw total width because may massively outshadow the others
+ var valueColumnWidth = columns[1].width;
+ if (valueColumnWidth / totalColumnWidths > 0.33) {
+ totalColumnWidths -= valueColumnWidth;
+ totalColumnWidths *= 1.33;
+ columns[1].width = totalColumnWidths * 0.33;
+ }
+
+ // Calculate the percentage width for the columns.
+ const minimumPrecent = 6;
+ var recoupPercent = 0;
+ for (var columnIdentifier in columns) {
+ var width = columns[columnIdentifier].width;
+ width = Math.round((width / totalColumnWidths) * 100);
+ if (width < minimumPrecent) {
+ recoupPercent += (minimumPrecent - width);
+ width = minimumPrecent;
+ }
+ columns[columnIdentifier].width = width;
+ }
+
+ // Enforce the minimum percentage width. (need to narrow total percentage due to earlier additions)
+ while (recoupPercent > 0) {
+ for (var columnIdentifier in columns) {
+ if (columns[columnIdentifier].width > minimumPrecent) {
+ --columns[columnIdentifier].width;
+ --recoupPercent;
+ if (!recoupPercent)
+ break;
+ }
+ }
+ }
+
+ for (var columnIdentifier in columns)
+ columns[columnIdentifier].width += "%";
+
+ var dataGrid = new WebInspector.DataGrid(columns);
+ var length = nodes.length;
+ for (var i = 0; i < length; ++i)
+ dataGrid.appendChild(nodes[i]);
+ if (length > 0)
+ nodes[0].selected = true;
+
+ return dataGrid;
+ },
+
+ simpleDataGridForCookies: function(cookies)
+ {
+ if (!cookies.length)
+ return null;
+
+ var columns = {};
+ columns[0] = {};
+ columns[1] = {};
+ columns[0].title = WebInspector.UIString("Name");
+ columns[0].width = columns[0].title.length;
+ columns[1].title = WebInspector.UIString("Value");
+ columns[1].width = columns[1].title.length;
+
+ var nodes = [];
+ for (var i = 0; i < cookies.length; ++i) {
+ var cookie = cookies[i];
+ var data = {};
+
+ var name = cookie.name;
+ data[0] = name;
+ if (name.length > columns[0].width)
+ columns[0].width = name.length;
+
+ var value = cookie.value;
+ data[1] = value;
+ if (value.length > columns[1].width)
+ columns[1].width = value.length;
+
+ var node = new WebInspector.DataGridNode(data, false);
+ node.selectable = true;
+ nodes.push(node);
+ }
+
+ var totalColumnWidths = columns[0].width + columns[1].width;
+ var width = Math.round((columns[0].width * 100) / totalColumnWidths);
+ const minimumPrecent = 20;
+ if (width < minimumPrecent)
+ width = minimumPrecent;
+ if (width > 100 - minimumPrecent)
+ width = 100 - minimumPrecent;
+ columns[0].width = width;
+ columns[1].width = 100 - width;
+ columns[0].width += "%";
+ columns[1].width += "%";
+
+ var dataGrid = new WebInspector.DataGrid(columns);
+ var length = nodes.length;
+ for (var i = 0; i < length; ++i)
+ dataGrid.appendChild(nodes[i]);
+ if (length > 0)
+ nodes[0].selected = true;
+
+ return dataGrid;
+ },
+
+ resize: function()
+ {
+ if (this._datagrid)
+ this._dataGrid.updateWidths();
+ },
+
+ _deleteButtonClicked: function(event)
+ {
+ if (!this._dataGrid)
+ return;
+
+ var cookie = this._dataGrid.selectedNode.cookie;
+ InspectorController.deleteCookie(cookie.name, this._cookieDomain);
+ this.update();
+ },
+
+ _refreshButtonClicked: function(event)
+ {
+ this.update();
+ }
+}
+
+WebInspector.CookieItemsView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/WebCore/inspector/front-end/DOMAgent.js b/WebCore/inspector/front-end/DOMAgent.js
index 5aacd41..25ffafa 100644
--- a/WebCore/inspector/front-end/DOMAgent.js
+++ b/WebCore/inspector/front-end/DOMAgent.js
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -31,9 +32,10 @@
WebInspector.DOMNode = function(doc, payload) {
this.ownerDocument = doc;
- this._id = payload.id;
+ this.id = payload.id;
this.nodeType = payload.nodeType;
this.nodeName = payload.nodeName;
+ this.localName = payload.localName;
this._nodeValue = payload.nodeValue;
this.textContent = this.nodeValue;
@@ -48,14 +50,22 @@ WebInspector.DOMNode = function(doc, payload) {
this.nextSibling = null;
this.prevSibling = null;
this.firstChild = null;
+ this.lastChild = null;
this.parentNode = null;
- if (payload.childNodes)
- this._setChildrenPayload(payload.childNodes);
+ if (payload.children)
+ this._setChildrenPayload(payload.children);
this._computedStyle = null;
this.style = null;
this._matchedCSSRules = [];
+
+ if (this.nodeType == Node.ELEMENT_NODE) {
+ if (this.nodeName == "HTML")
+ this.ownerDocument.documentElement = this;
+ if (this.nodeName == "BODY")
+ this.ownerDocument.body = this;
+ }
}
WebInspector.DOMNode.prototype = {
@@ -161,9 +171,11 @@ WebInspector.DOMNode.prototype = {
this._childNodeCount = this.children.length;
if (this._childNodeCount == 0) {
this.firstChild = null;
+ this.lastChild = null;
return;
}
this.firstChild = this.children[0];
+ this.lastChild = this.children[this._childNodeCount - 1];
for (var i = 0; i < this._childNodeCount; ++i) {
var child = this.children[i];
child.nextSibling = i + 1 < this._childNodeCount ? this.children[i + 1] : null;
@@ -208,17 +220,9 @@ WebInspector.DOMNode.prototype = {
}
}
-WebInspector.DOMDocument = function(domAgent, defaultView)
+WebInspector.DOMDocument = function(domAgent, defaultView, payload)
{
- WebInspector.DOMNode.call(this, null,
- {
- id: 0,
- nodeType: Node.DOCUMENT_NODE,
- nodeName: "",
- nodeValue: "",
- attributes: [],
- childNodeCount: 0
- });
+ WebInspector.DOMNode.call(this, this, payload);
this._listeners = {};
this._domAgent = domAgent;
this.defaultView = defaultView;
@@ -226,7 +230,7 @@ WebInspector.DOMDocument = function(domAgent, defaultView)
WebInspector.DOMDocument.prototype = {
- addEventListener: function(name, callback, useCapture)
+ addEventListener: function(name, callback)
{
var listeners = this._listeners[name];
if (!listeners) {
@@ -236,7 +240,7 @@ WebInspector.DOMDocument.prototype = {
listeners.push(callback);
},
- removeEventListener: function(name, callback, useCapture)
+ removeEventListener: function(name, callback)
{
var listeners = this._listeners[name];
if (!listeners)
@@ -251,10 +255,12 @@ WebInspector.DOMDocument.prototype = {
{
var listeners = this._listeners[name];
if (!listeners)
- return;
+ return;
- for (var i = 0; i < listeners.length; ++i)
- listeners[i](event);
+ for (var i = 0; i < listeners.length; ++i) {
+ var listener = listeners[i];
+ listener.call(this, event);
+ }
}
}
@@ -301,68 +307,44 @@ WebInspector.DOMAgent = function() {
this._window = new WebInspector.DOMWindow(this);
this._idToDOMNode = null;
this.document = null;
-
- // Install onpopulate handler. This is a temporary measure.
- // TODO: add this code into the original updateChildren once domAgent
- // becomes primary source of DOM information.
- // TODO2: update ElementsPanel to not track embedded iframes - it is already being handled
- // in the agent backend.
- var domAgent = this;
- var originalUpdateChildren = WebInspector.ElementsTreeElement.prototype.updateChildren;
- WebInspector.ElementsTreeElement.prototype.updateChildren = function()
- {
- domAgent.getChildNodesAsync(this.representedObject, originalUpdateChildren.bind(this));
- };
-
- // Mute console handle to avoid crash on selection change.
- // TODO: Re-implement inspectorConsoleAPI to work in a serialized way and remove this workaround.
- WebInspector.Console.prototype.addInspectedNode = function()
- {
- };
-
- // Whitespace is ignored in InspectorDOMAgent already -> no need to filter.
- // TODO: Either remove all of its usages or push value into the agent backend.
- Preferences.ignoreWhitespace = false;
}
WebInspector.DOMAgent.prototype = {
- get inspectedWindow()
+ get domWindow()
{
return this._window;
},
- getChildNodesAsync: function(parent, opt_callback)
+ getChildNodesAsync: function(parent, callback)
{
var children = parent.children;
- if (children && opt_callback) {
- opt_callback(children);
- return;
+ if (children) {
+ callback(children);
+ return;
+ }
+ function mycallback() {
+ callback(parent.children);
}
- var mycallback = function() {
- if (opt_callback) {
- opt_callback(parent.children);
- }
- };
var callId = WebInspector.Callback.wrap(mycallback);
- InspectorController.getChildNodes(callId, parent._id);
+ InspectorController.getChildNodes(callId, parent.id);
},
setAttributeAsync: function(node, name, value, callback)
{
var mycallback = this._didApplyDomChange.bind(this, node, callback);
- InspectorController.setAttribute(WebInspector.Callback.wrap(mycallback), node._id, name, value);
+ InspectorController.setAttribute(WebInspector.Callback.wrap(mycallback), node.id, name, value);
},
removeAttributeAsync: function(node, name, callback)
{
var mycallback = this._didApplyDomChange.bind(this, node, callback);
- InspectorController.removeAttribute(WebInspector.Callback.wrap(mycallback), node._id, name);
+ InspectorController.removeAttribute(WebInspector.Callback.wrap(mycallback), node.id, name);
},
setTextNodeValueAsync: function(node, text, callback)
{
var mycallback = this._didApplyDomChange.bind(this, node, callback);
- InspectorController.setTextNodeValue(WebInspector.Callback.wrap(mycallback), node._id, text);
+ InspectorController.setTextNodeValue(WebInspector.Callback.wrap(mycallback), node.id, text);
},
_didApplyDomChange: function(node, callback, success)
@@ -383,26 +365,31 @@ WebInspector.DOMAgent.prototype = {
node._setAttributesPayload(attrsArray);
},
- getNodeForId: function(nodeId) {
+ nodeForId: function(nodeId) {
return this._idToDOMNode[nodeId];
},
- _setDocumentElement: function(payload)
+ _setDocument: function(payload)
{
- this.document = new WebInspector.DOMDocument(this, this._window);
- this._idToDOMNode = { 0 : this.document };
- this._setChildNodes(0, [payload]);
- this.document.documentElement = this.document.firstChild;
- this.document.documentElement.ownerDocument = this.document;
+ this._idToDOMNode = {};
+ if (payload) {
+ this.document = new WebInspector.DOMDocument(this, this._window, payload);
+ this._idToDOMNode[payload.id] = this.document;
+ this._bindNodes(this.document.children);
+ } else
+ this.document = null;
WebInspector.panels.elements.reset();
},
+ _setDetachedRoot: function(payload)
+ {
+ var root = new WebInspector.DOMNode(this.document, payload);
+ this._idToDOMNode[payload.id] = root;
+ },
+
_setChildNodes: function(parentId, payloads)
{
var parent = this._idToDOMNode[parentId];
- if (parent.children) {
- return;
- }
parent._setChildrenPayload(payloads);
this._bindNodes(parent.children);
},
@@ -411,21 +398,20 @@ WebInspector.DOMAgent.prototype = {
{
for (var i = 0; i < children.length; ++i) {
var child = children[i];
- this._idToDOMNode[child._id] = child;
+ this._idToDOMNode[child.id] = child;
if (child.children)
this._bindNodes(child.children);
}
},
- _hasChildrenUpdated: function(nodeId, newValue)
+ _childNodeCountUpdated: function(nodeId, newValue)
{
var node = this._idToDOMNode[nodeId];
+ node._childNodeCount = newValue;
var outline = WebInspector.panels.elements.treeOutline;
var treeElement = outline.findTreeElement(node);
- if (treeElement) {
+ if (treeElement)
treeElement.hasChildren = newValue;
- treeElement.whitespaceIgnored = Preferences.ignoreWhitespace;
- }
},
_childNodeInserted: function(parentId, prevId, payload)
@@ -433,7 +419,7 @@ WebInspector.DOMAgent.prototype = {
var parent = this._idToDOMNode[parentId];
var prev = this._idToDOMNode[prevId];
var node = parent._insertChild(prev, payload);
- this._idToDOMNode[node._id] = node;
+ this._idToDOMNode[node.id] = node;
var event = { target : node, relatedNode : parent };
this.document._fireDomEvent("DOMNodeInserted", event);
},
@@ -449,8 +435,53 @@ WebInspector.DOMAgent.prototype = {
}
}
-WebInspector.CSSStyleDeclaration = function(payload) {
- this._id = payload.id;
+WebInspector.Cookies = {}
+
+WebInspector.Cookies.getCookiesAsync = function(callback, cookieDomain)
+{
+ function mycallback(cookies, cookiesString) {
+ if (cookiesString)
+ callback(WebInspector.Cookies.buildCookiesFromString(cookiesString), false);
+ else
+ callback(cookies, true);
+ }
+ var callId = WebInspector.Callback.wrap(mycallback);
+ InspectorController.getCookies(callId, cookieDomain);
+}
+
+WebInspector.Cookies.buildCookiesFromString = function(rawCookieString)
+{
+ var rawCookies = rawCookieString.split(/;\s*/);
+ var cookies = [];
+
+ if (!(/^\s*$/.test(rawCookieString))) {
+ for (var i = 0; i < rawCookies.length; ++i) {
+ var cookie = rawCookies[i];
+ var delimIndex = cookie.indexOf("=");
+ var name = cookie.substring(0, delimIndex);
+ var value = cookie.substring(delimIndex + 1);
+ var size = name.length + value.length;
+ cookies.push({ name: name, value: value, size: size });
+ }
+ }
+
+ return cookies;
+}
+
+WebInspector.EventListeners = {}
+
+WebInspector.EventListeners.getEventListenersForNodeAsync = function(node, callback)
+{
+ if (!node)
+ return;
+
+ var callId = WebInspector.Callback.wrap(callback);
+ InspectorController.getEventListenersForNode(callId, node.id);
+}
+
+WebInspector.CSSStyleDeclaration = function(payload)
+{
+ this.id = payload.id;
this.width = payload.width;
this.height = payload.height;
this.__disabledProperties = payload.__disabledProperties;
@@ -492,12 +523,13 @@ WebInspector.CSSStyleDeclaration.parseStyle = function(payload)
WebInspector.CSSStyleDeclaration.parseRule = function(payload)
{
var rule = {};
- rule._id = payload.id;
+ rule.id = payload.id;
rule.selectorText = payload.selectorText;
rule.style = new WebInspector.CSSStyleDeclaration(payload.style);
rule.style.parentRule = rule;
rule.isUserAgent = payload.isUserAgent;
rule.isUser = payload.isUser;
+ rule.isViaInspector = payload.isViaInspector;
if (payload.parentStyleSheet)
rule.parentStyleSheet = { href: payload.parentStyleSheet.href };
@@ -586,9 +618,14 @@ WebInspector.attributesUpdated = function()
this.domAgent._attributesUpdated.apply(this.domAgent, arguments);
}
-WebInspector.setDocumentElement = function()
+WebInspector.setDocument = function()
{
- this.domAgent._setDocumentElement.apply(this.domAgent, arguments);
+ this.domAgent._setDocument.apply(this.domAgent, arguments);
+}
+
+WebInspector.setDetachedRoot = function()
+{
+ this.domAgent._setDetachedRoot.apply(this.domAgent, arguments);
}
WebInspector.setChildNodes = function()
@@ -596,129 +633,25 @@ WebInspector.setChildNodes = function()
this.domAgent._setChildNodes.apply(this.domAgent, arguments);
}
-WebInspector.hasChildrenUpdated = function()
+WebInspector.childNodeCountUpdated = function()
{
- this.domAgent._hasChildrenUpdated.apply(this.domAgent, arguments);
+ this.domAgent._childNodeCountUpdated.apply(this.domAgent, arguments);
}
WebInspector.childNodeInserted = function()
{
this.domAgent._childNodeInserted.apply(this.domAgent, arguments);
- this._childNodeInserted.bind(this);
}
WebInspector.childNodeRemoved = function()
{
this.domAgent._childNodeRemoved.apply(this.domAgent, arguments);
- this._childNodeRemoved.bind(this);
}
+WebInspector.didGetCookies = WebInspector.Callback.processCallback;
WebInspector.didGetChildNodes = WebInspector.Callback.processCallback;
WebInspector.didPerformSearch = WebInspector.Callback.processCallback;
WebInspector.didApplyDomChange = WebInspector.Callback.processCallback;
WebInspector.didRemoveAttribute = WebInspector.Callback.processCallback;
WebInspector.didSetTextNodeValue = WebInspector.Callback.processCallback;
-
-// Temporary methods for DOMAgent migration.
-WebInspector.wrapNodeWithStyles = function(node, styles)
-{
- var windowStub = new WebInspector.DOMWindow(null);
- var docStub = new WebInspector.DOMDocument(null, windowStub);
- var payload = {};
- payload.nodeType = node.nodeType;
- payload.nodeName = node.nodeName;
- payload.nodeValue = node.nodeValue;
- payload.attributes = [];
- payload.childNodeCount = 0;
-
- for (var i = 0; i < node.attributes.length; ++i) {
- var attr = node.attributes[i];
- payload.attributes.push(attr.name);
- payload.attributes.push(attr.value);
- }
- var nodeStub = new WebInspector.DOMNode(docStub, payload);
- nodeStub._setStyles(styles.computedStyle, styles.inlineStyle, styles.styleAttributes, styles.matchedCSSRules);
- return nodeStub;
-}
-
-// Temporary methods that will be dispatched via InspectorController into the injected context.
-InspectorController.getStyles = function(nodeId, authorOnly, callback)
-{
- setTimeout(function() {
- callback(InjectedScript.getStyles(nodeId, authorOnly));
- }, 0)
-}
-
-InspectorController.getComputedStyle = function(nodeId, callback)
-{
- setTimeout(function() {
- callback(InjectedScript.getComputedStyle(nodeId));
- }, 0)
-}
-
-InspectorController.getInlineStyle = function(nodeId, callback)
-{
- setTimeout(function() {
- callback(InjectedScript.getInlineStyle(nodeId));
- }, 0)
-}
-
-InspectorController.applyStyleText = function(styleId, styleText, propertyName, callback)
-{
- setTimeout(function() {
- callback(InjectedScript.applyStyleText(styleId, styleText, propertyName));
- }, 0)
-}
-
-InspectorController.setStyleText = function(style, cssText, callback)
-{
- setTimeout(function() {
- callback(InjectedScript.setStyleText(style, cssText));
- }, 0)
-}
-
-InspectorController.toggleStyleEnabled = function(styleId, propertyName, disabled, callback)
-{
- setTimeout(function() {
- callback(InjectedScript.toggleStyleEnabled(styleId, propertyName, disabled));
- }, 0)
-}
-
-InspectorController.applyStyleRuleText = function(ruleId, newContent, selectedNode, callback)
-{
- setTimeout(function() {
- callback(InjectedScript.applyStyleRuleText(ruleId, newContent, selectedNode));
- }, 0)
-}
-
-InspectorController.addStyleSelector = function(newContent, callback)
-{
- setTimeout(function() {
- callback(InjectedScript.addStyleSelector(newContent));
- }, 0)
-}
-
-InspectorController.setStyleProperty = function(styleId, name, value, callback) {
- setTimeout(function() {
- callback(InjectedScript.setStyleProperty(styleId, name, value));
- }, 0)
-}
-
-InspectorController.getPrototypes = function(objectProxy, callback) {
- setTimeout(function() {
- callback(InjectedScript.getPrototypes(objectProxy));
- }, 0)
-}
-
-InspectorController.getProperties = function(objectProxy, ignoreHasOwnProperty, callback) {
- setTimeout(function() {
- callback(InjectedScript.getProperties(objectProxy, ignoreHasOwnProperty));
- }, 0)
-}
-
-InspectorController.setPropertyValue = function(objectProxy, propertyName, expression, callback) {
- setTimeout(function() {
- callback(InjectedScript.setPropertyValue(objectProxy, propertyName, expression));
- }, 0)
-}
-
+WebInspector.didGetEventListenersForNode = WebInspector.Callback.processCallback;
diff --git a/WebCore/inspector/front-end/DOMStorage.js b/WebCore/inspector/front-end/DOMStorage.js
index 5207b69..03a10bf 100644
--- a/WebCore/inspector/front-end/DOMStorage.js
+++ b/WebCore/inspector/front-end/DOMStorage.js
@@ -26,24 +26,22 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-WebInspector.DOMStorage = function(domStorage, domain, isLocalStorage)
+WebInspector.DOMStorage = function(id, domain, isLocalStorage)
{
- this.domStorage = domStorage;
- this.domain = domain;
- this.isLocalStorage = isLocalStorage;
+ this._id = id;
+ this._domain = domain;
+ this._isLocalStorage = isLocalStorage;
}
WebInspector.DOMStorage.prototype = {
- get domStorage()
+ get id()
{
- return this._domStorage;
+ return this._id;
},
- set domStorage(x)
+ get domStorage()
{
- if (this._domStorage === x)
- return;
- this._domStorage = x;
+ return this._domStorage;
},
get domain()
@@ -51,22 +49,30 @@ WebInspector.DOMStorage.prototype = {
return this._domain;
},
- set domain(x)
+ get isLocalStorage()
+ {
+ return this._isLocalStorage;
+ },
+
+ getEntries: function(callback)
{
- if (this._domain === x)
- return;
- this._domain = x;
+ var callId = WebInspector.Callback.wrap(callback);
+ InspectorController.getDOMStorageEntries(callId, this._id);
},
- get isLocalStorage()
+ setItem: function(key, value, callback)
{
- return this._isLocalStorage;
+ var callId = WebInspector.Callback.wrap(callback);
+ InspectorController.setDOMStorageItem(callId, this._id, key, value);
},
- set isLocalStorage(x)
+ removeItem: function(key, callback)
{
- if (this._isLocalStorage === x)
- return;
- this._isLocalStorage = x;
+ var callId = WebInspector.Callback.wrap(callback);
+ InspectorController.removeDOMStorageItem(callId, this._id, key);
}
}
+
+WebInspector.didGetDOMStorageEntries = WebInspector.Callback.processCallback;
+WebInspector.didSetDOMStorageItem = WebInspector.Callback.processCallback;
+WebInspector.didRemoveDOMStorageItem = WebInspector.Callback.processCallback;
diff --git a/WebCore/inspector/front-end/DOMStorageDataGrid.js b/WebCore/inspector/front-end/DOMStorageDataGrid.js
index 0326bc7..45a9ba1 100644
--- a/WebCore/inspector/front-end/DOMStorageDataGrid.js
+++ b/WebCore/inspector/front-end/DOMStorageDataGrid.js
@@ -23,10 +23,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-WebInspector.DOMStorageDataGrid = function(columns)
+WebInspector.DOMStorageDataGrid = function(columns, domStorage, keys)
{
WebInspector.DataGrid.call(this, columns);
this.dataTableBody.addEventListener("dblclick", this._ondblclick.bind(this), false);
+ this._domStorage = domStorage;
+ this._keys = keys;
}
WebInspector.DOMStorageDataGrid.prototype = {
@@ -44,7 +46,6 @@ WebInspector.DOMStorageDataGrid.prototype = {
this._editing = true;
this._editingNode = node;
this._editingNode.select();
- WebInspector.panels.databases._unregisterStorageEventListener();
var element = this._editingNode._element.children[column];
WebInspector.startEditing(element, this._editingCommitted.bind(this), this._editingCancelled.bind(this), element.textContent);
@@ -69,7 +70,6 @@ WebInspector.DOMStorageDataGrid.prototype = {
return this._startEditingColumnOfDataGridNode(this._editingNode, 0);
this._editing = true;
- WebInspector.panels.databases._unregisterStorageEventListener();
WebInspector.startEditing(element, this._editingCommitted.bind(this), this._editingCancelled.bind(this), element.textContent);
window.getSelection().setBaseAndExtent(element, 0, element, 1);
},
@@ -118,22 +118,20 @@ WebInspector.DOMStorageDataGrid.prototype = {
return;
}
- var domStorage = WebInspector.panels.databases.visibleView.domStorage.domStorage;
- if (domStorage) {
- if (columnIdentifier == 0) {
- if (domStorage.getItem(newText) != null) {
- element.textContent = this._editingNode.data[0];
- this._editingCancelled(element);
- moveToNextIfNeeded.call(this, false);
- return;
- }
- domStorage.removeItem(this._editingNode.data[0]);
- domStorage.setItem(newText, this._editingNode.data[1]);
- this._editingNode.data[0] = newText;
- } else {
- domStorage.setItem(this._editingNode.data[0], newText);
- this._editingNode.data[1] = newText;
+ var domStorage = this._domStorage;
+ if (columnIdentifier === 0) {
+ if (this._keys.indexOf(newText) !== -1) {
+ element.textContent = this._editingNode.data[0];
+ this._editingCancelled(element);
+ moveToNextIfNeeded.call(this, false);
+ return;
}
+ domStorage.removeItem(this._editingNode.data[0]);
+ domStorage.setItem(newText, this._editingNode.data[1]);
+ this._editingNode.data[0] = newText;
+ } else {
+ domStorage.setItem(this._editingNode.data[0], newText);
+ this._editingNode.data[1] = newText;
}
if (this._editingNode.isCreationNode)
@@ -147,18 +145,16 @@ WebInspector.DOMStorageDataGrid.prototype = {
{
delete this._editing;
this._editingNode = null;
- WebInspector.panels.databases._registerStorageEventListener();
},
deleteSelectedRow: function()
{
var node = this.selectedNode;
- if (this.selectedNode.isCreationNode)
+ if (!node || node.isCreationNode)
return;
- var domStorage = WebInspector.panels.databases.visibleView.domStorage.domStorage;
- if (node && domStorage)
- domStorage.removeItem(node.data[0]);
+ if (this._domStorage)
+ this._domStorage.removeItem(node.data[0]);
}
}
diff --git a/WebCore/inspector/front-end/DOMStorageItemsView.js b/WebCore/inspector/front-end/DOMStorageItemsView.js
index fad6e3c..a7da370 100644
--- a/WebCore/inspector/front-end/DOMStorageItemsView.js
+++ b/WebCore/inspector/front-end/DOMStorageItemsView.js
@@ -32,21 +32,18 @@ WebInspector.DOMStorageItemsView = function(domStorage)
this.element.addStyleClass("storage-view");
this.element.addStyleClass("table");
- this.deleteButton = document.createElement("button");
- this.deleteButton.title = WebInspector.UIString("Delete");
- this.deleteButton.className = "delete-storage-status-bar-item status-bar-item hidden";
+ this.deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item");
+ this.deleteButton.visible = false;
this.deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false);
- this.refreshButton = document.createElement("button");
- this.refreshButton.title = WebInspector.UIString("Refresh");
- this.refreshButton.className = "refresh-storage-status-bar-item status-bar-item";
+ this.refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item");
this.refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false);
}
WebInspector.DOMStorageItemsView.prototype = {
get statusBarItems()
{
- return [this.refreshButton, this.deleteButton];
+ return [this.refreshButton.element, this.deleteButton.element];
},
show: function(parentElement)
@@ -58,45 +55,94 @@ WebInspector.DOMStorageItemsView.prototype = {
hide: function()
{
WebInspector.View.prototype.hide.call(this);
- this.deleteButton.addStyleClass("hidden");
+ this.deleteButton.visible = false;
},
update: function()
{
this.element.removeChildren();
- var hasDOMStorage = this.domStorage;
- if (hasDOMStorage)
- hasDOMStorage = this.domStorage.domStorage;
-
- if (hasDOMStorage) {
- var dataGrid = WebInspector.panels.databases.dataGridForDOMStorage(this.domStorage.domStorage);
- if (!dataGrid)
- hasDOMStorage = 0;
- else {
- this._dataGrid = dataGrid;
- this.element.appendChild(dataGrid.element);
- this._dataGrid.updateWidths();
- this.deleteButton.removeStyleClass("hidden");
- }
- }
+ var callback = this._showDOMStorageEntries.bind(this);
+ this.domStorage.getEntries(callback);
+ },
- if (!hasDOMStorage) {
+ _showDOMStorageEntries: function(entries)
+ {
+ if (entries.length > 0) {
+ this._dataGrid = this._dataGridForDOMStorageEntries(entries);
+ this.element.appendChild(this._dataGrid.element);
+ this._dataGrid.updateWidths();
+ this.deleteButton.visible = true;
+ } else {
var emptyMsgElement = document.createElement("div");
emptyMsgElement.className = "storage-table-empty";
if (this.domStorage)
- emptyMsgElement.textContent = WebInspector.UIString("This storage is empty.");
+ emptyMsgElement.textContent = WebInspector.UIString("This storage is empty.");
this.element.appendChild(emptyMsgElement);
this._dataGrid = null;
- this.deleteButton.addStyleClass("hidden");
+ this.deleteButton.visible = false;
}
},
-
+
resize: function()
{
if (this._dataGrid)
this._dataGrid.updateWidths();
},
+ _dataGridForDOMStorageEntries: function(entries)
+ {
+ var columns = {};
+ columns[0] = {};
+ columns[1] = {};
+ columns[0].title = WebInspector.UIString("Key");
+ columns[0].width = columns[0].title.length;
+ columns[1].title = WebInspector.UIString("Value");
+ columns[1].width = columns[1].title.length;
+
+ var nodes = [];
+
+ var keys = [];
+ var length = entries.length;
+ for (var i = 0; i < entries.length; i++) {
+ var data = {};
+
+ var key = entries[i][0];
+ data[0] = key;
+ if (key.length > columns[0].width)
+ columns[0].width = key.length;
+
+ var value = entries[i][1];
+ data[1] = value;
+ if (value.length > columns[1].width)
+ columns[1].width = value.length;
+ var node = new WebInspector.DataGridNode(data, false);
+ node.selectable = true;
+ nodes.push(node);
+ keys.push(key);
+ }
+
+ var totalColumnWidths = columns[0].width + columns[1].width;
+ var width = Math.round((columns[0].width * 100) / totalColumnWidths);
+ const minimumPrecent = 10;
+ if (width < minimumPrecent)
+ width = minimumPrecent;
+ if (width > 100 - minimumPrecent)
+ width = 100 - minimumPrecent;
+ columns[0].width = width;
+ columns[1].width = 100 - width;
+ columns[0].width += "%";
+ columns[1].width += "%";
+
+ var dataGrid = new WebInspector.DOMStorageDataGrid(columns, this.domStorage, keys);
+ var length = nodes.length;
+ for (var i = 0; i < length; ++i)
+ dataGrid.appendChild(nodes[i]);
+ dataGrid.addCreationNode(false);
+ if (length > 0)
+ nodes[0].selected = true;
+ return dataGrid;
+ },
+
_deleteButtonClicked: function(event)
{
if (this._dataGrid) {
diff --git a/WebCore/inspector/front-end/DataGrid.js b/WebCore/inspector/front-end/DataGrid.js
index 42e001c..ce61548 100644
--- a/WebCore/inspector/front-end/DataGrid.js
+++ b/WebCore/inspector/front-end/DataGrid.js
@@ -39,6 +39,8 @@ WebInspector.DataGrid = function(columns)
this._dataTable.addEventListener("mousedown", this._mouseDownInDataTable.bind(this), true);
this._dataTable.addEventListener("click", this._clickInDataTable.bind(this), true);
+ this.aligned = {};
+
var scrollContainer = document.createElement("div");
scrollContainer.className = "data-container";
scrollContainer.appendChild(this._dataTable);
@@ -78,6 +80,11 @@ WebInspector.DataGrid = function(columns)
cell.addStyleClass("sortable");
}
+ if (column.aligned) {
+ cell.addStyleClass(column.aligned);
+ this.aligned[columnIdentifier] = column.aligned;
+ }
+
headerRow.appendChild(cell);
++columnCount;
@@ -752,6 +759,10 @@ WebInspector.DataGridNode.prototype = {
var cell = document.createElement("td");
cell.className = columnIdentifier + "-column";
+ var alignment = this.dataGrid.aligned[columnIdentifier];
+ if (alignment)
+ cell.addStyleClass(alignment);
+
var div = document.createElement("div");
div.textContent = this.data[columnIdentifier];
cell.appendChild(div);
diff --git a/WebCore/inspector/front-end/Database.js b/WebCore/inspector/front-end/Database.js
index ef42e15..1a348fc 100644
--- a/WebCore/inspector/front-end/Database.js
+++ b/WebCore/inspector/front-end/Database.js
@@ -26,25 +26,18 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-WebInspector.Database = function(database, domain, name, version)
+WebInspector.Database = function(id, domain, name, version)
{
- this.database = database;
- this.domain = domain;
- this.name = name;
- this.version = version;
+ this._id = id;
+ this._domain = domain;
+ this._name = name;
+ this._version = version;
}
WebInspector.Database.prototype = {
- get database()
+ get id()
{
- return this._database;
- },
-
- set database(x)
- {
- if (this._database === x)
- return;
- this._database = x;
+ return this._id;
},
get name()
@@ -54,8 +47,6 @@ WebInspector.Database.prototype = {
set name(x)
{
- if (this._name === x)
- return;
this._name = x;
},
@@ -66,8 +57,6 @@ WebInspector.Database.prototype = {
set version(x)
{
- if (this._version === x)
- return;
this._version = x;
},
@@ -78,8 +67,6 @@ WebInspector.Database.prototype = {
set domain(x)
{
- if (this._domain === x)
- return;
this._domain = x;
},
@@ -88,8 +75,28 @@ WebInspector.Database.prototype = {
return WebInspector.Resource.prototype.__lookupGetter__("displayDomain").call(this);
},
- get tableNames()
+ getTableNames: function(callback)
{
- return InspectorController.databaseTableNames(this.database).sort();
+ function sortingCallback(names)
+ {
+ callback(names.sort());
+ }
+ var callId = WebInspector.Callback.wrap(sortingCallback);
+ InspectorController.getDatabaseTableNames(callId, this._id);
+ },
+
+ executeSql: function(query, onSuccess, onError)
+ {
+ function callback(result)
+ {
+ if (!(result instanceof Array)) {
+ onError(result);
+ return;
+ }
+ onSuccess(result);
+ }
+ InjectedScriptAccess.executeSql(this._id, query, callback);
}
}
+
+WebInspector.didGetDatabaseTableNames = WebInspector.Callback.processCallback;
diff --git a/WebCore/inspector/front-end/DatabaseQueryView.js b/WebCore/inspector/front-end/DatabaseQueryView.js
index 429c2c3..6c5fa02 100644
--- a/WebCore/inspector/front-end/DatabaseQueryView.js
+++ b/WebCore/inspector/front-end/DatabaseQueryView.js
@@ -81,11 +81,15 @@ WebInspector.DatabaseQueryView.prototype = {
return;
}
}
+
+ function tableNamesCallback(tableNames)
+ {
+ accumulateMatches(tableNames.map(function(name) { return name + " " }));
+ accumulateMatches(["SELECT ", "FROM ", "WHERE ", "LIMIT ", "DELETE FROM ", "CREATE ", "DROP ", "TABLE ", "INDEX ", "UPDATE ", "INSERT INTO ", "VALUES ("]);
- accumulateMatches(this.database.tableNames.map(function(name) { return name + " " }));
- accumulateMatches(["SELECT ", "FROM ", "WHERE ", "LIMIT ", "DELETE FROM ", "CREATE ", "DROP ", "TABLE ", "INDEX ", "UPDATE ", "INSERT INTO ", "VALUES ("]);
-
- completionsReadyCallback(results);
+ completionsReadyCallback(results);
+ }
+ this.database.getTableNames(tableNamesCallback);
},
_promptKeyDown: function(event)
@@ -132,22 +136,19 @@ WebInspector.DatabaseQueryView.prototype = {
this.prompt.historyOffset = 0;
this.prompt.text = "";
- function queryTransaction(tx)
- {
- tx.executeSql(query, null, InspectorController.wrapCallback(this._queryFinished.bind(this, query)), InspectorController.wrapCallback(this._executeSqlError.bind(this, query)));
- }
-
- this.database.database.transaction(InspectorController.wrapCallback(queryTransaction.bind(this)), InspectorController.wrapCallback(this._queryError.bind(this, query)));
+ this.database.executeSql(query, this._queryFinished.bind(this, query), this._queryError.bind(this, query));
},
- _queryFinished: function(query, tx, result)
+ _queryFinished: function(query, result)
{
- var dataGrid = WebInspector.panels.databases.dataGridForResult(result);
+ var dataGrid = WebInspector.panels.storage.dataGridForResult(result);
+ if (!dataGrid)
+ return;
dataGrid.element.addStyleClass("inline");
this._appendQueryResult(query, dataGrid.element);
if (query.match(/^create /i) || query.match(/^drop table /i))
- WebInspector.panels.databases.updateDatabaseTables(this.database);
+ WebInspector.panels.storage.updateDatabaseTables(this.database);
},
_queryError: function(query, error)
@@ -162,11 +163,6 @@ WebInspector.DatabaseQueryView.prototype = {
this._appendQueryResult(query, message, "error");
},
- _executeSqlError: function(query, tx, error)
- {
- this._queryError(query, error);
- },
-
_appendQueryResult: function(query, result, resultClassName)
{
var element = document.createElement("div");
diff --git a/WebCore/inspector/front-end/DatabaseTableView.js b/WebCore/inspector/front-end/DatabaseTableView.js
index bbca9d0..aa76794 100644
--- a/WebCore/inspector/front-end/DatabaseTableView.js
+++ b/WebCore/inspector/front-end/DatabaseTableView.js
@@ -33,9 +33,7 @@ WebInspector.DatabaseTableView = function(database, tableName)
this.element.addStyleClass("storage-view");
this.element.addStyleClass("table");
- this.refreshButton = document.createElement("button");
- this.refreshButton.title = WebInspector.UIString("Refresh");
- this.refreshButton.className = "refresh-storage-status-bar-item status-bar-item";
+ this.refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item");
this.refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false);
}
@@ -53,19 +51,14 @@ WebInspector.DatabaseTableView.prototype = {
update: function()
{
- function queryTransaction(tx)
- {
- tx.executeSql("SELECT * FROM " + this.tableName, null, InspectorController.wrapCallback(this._queryFinished.bind(this)), InspectorController.wrapCallback(this._queryError.bind(this)));
- }
-
- this.database.database.transaction(InspectorController.wrapCallback(queryTransaction.bind(this)), InspectorController.wrapCallback(this._queryError.bind(this)));
+ this.database.executeSql("SELECT * FROM " + this.tableName, this._queryFinished.bind(this), this._queryError.bind(this));
},
- _queryFinished: function(tx, result)
+ _queryFinished: function(result)
{
this.element.removeChildren();
- var dataGrid = WebInspector.panels.databases.dataGridForResult(result);
+ var dataGrid = WebInspector.panels.storage.dataGridForResult(result);
if (!dataGrid) {
var emptyMsgElement = document.createElement("div");
emptyMsgElement.className = "storage-table-empty";
@@ -77,7 +70,7 @@ WebInspector.DatabaseTableView.prototype = {
this.element.appendChild(dataGrid.element);
},
- _queryError: function(tx, error)
+ _queryError: function(error)
{
this.element.removeChildren();
diff --git a/WebCore/inspector/front-end/Drawer.js b/WebCore/inspector/front-end/Drawer.js
index 23dc483..1b50f91 100644
--- a/WebCore/inspector/front-end/Drawer.js
+++ b/WebCore/inspector/front-end/Drawer.js
@@ -64,6 +64,12 @@ WebInspector.Drawer.prototype = {
}
},
+ showView: function(view)
+ {
+ if (!this.visible || this.visibleView !== view)
+ this.visibleView = view;
+ },
+
show: function()
{
if (this._animating || this.visible)
diff --git a/WebCore/inspector/front-end/ElementsPanel.js b/WebCore/inspector/front-end/ElementsPanel.js
index ffa0000..fd0874a 100644
--- a/WebCore/inspector/front-end/ElementsPanel.js
+++ b/WebCore/inspector/front-end/ElementsPanel.js
@@ -56,12 +56,14 @@ WebInspector.ElementsPanel = function()
this.panel.updateStyles(true);
this.panel.updateMetrics();
this.panel.updateProperties();
+ this.panel.updateEventListeners();
if (InspectorController.searchingForNode()) {
InspectorController.toggleNodeSearch();
- this.panel.nodeSearchButton.removeStyleClass("toggled-on");
+ this.panel.nodeSearchButton.toggled = false;
}
- WebInspector.console.addInspectedNode(this._focusedDOMNode);
+ if (this._focusedDOMNode)
+ InjectedScriptAccess.addInspectedNode(this._focusedDOMNode.id, function() {});
};
this.contentElement.appendChild(this.treeOutline.element);
@@ -75,10 +77,12 @@ WebInspector.ElementsPanel = function()
this.sidebarPanes.styles = new WebInspector.StylesSidebarPane();
this.sidebarPanes.metrics = new WebInspector.MetricsSidebarPane();
this.sidebarPanes.properties = new WebInspector.PropertiesSidebarPane();
+ this.sidebarPanes.eventListeners = new WebInspector.EventListenersSidebarPane();
this.sidebarPanes.styles.onexpand = this.updateStyles.bind(this);
this.sidebarPanes.metrics.onexpand = this.updateMetrics.bind(this);
this.sidebarPanes.properties.onexpand = this.updateProperties.bind(this);
+ this.sidebarPanes.eventListeners.onexpand = this.updateEventListeners.bind(this);
this.sidebarPanes.styles.expanded = true;
@@ -92,15 +96,13 @@ WebInspector.ElementsPanel = function()
this.sidebarElement.appendChild(this.sidebarPanes.styles.element);
this.sidebarElement.appendChild(this.sidebarPanes.metrics.element);
this.sidebarElement.appendChild(this.sidebarPanes.properties.element);
+ this.sidebarElement.appendChild(this.sidebarPanes.eventListeners.element);
this.sidebarResizeElement = document.createElement("div");
this.sidebarResizeElement.className = "sidebar-resizer-vertical";
this.sidebarResizeElement.addEventListener("mousedown", this.rightSidebarResizerDragStart.bind(this), false);
- this.nodeSearchButton = this.createStatusBarButton();
- this.nodeSearchButton.title = WebInspector.UIString("Select an element in the page to inspect it.");
- this.nodeSearchButton.id = "node-search-status-bar-item";
- this.nodeSearchButton.className = "status-bar-item";
+ this.nodeSearchButton = new WebInspector.StatusBarButton(WebInspector.UIString("Select an element in the page to inspect it."), "node-search-status-bar-item");
this.nodeSearchButton.addEventListener("click", this._nodeSearchButtonClicked.bind(this), false);
this.searchingForNode = false;
@@ -109,13 +111,7 @@ WebInspector.ElementsPanel = function()
this.element.appendChild(this.sidebarElement);
this.element.appendChild(this.sidebarResizeElement);
- this._mutationMonitoredWindows = [];
- this._nodeInsertedEventListener = InspectorController.wrapCallback(this._nodeInserted.bind(this));
- this._nodeRemovedEventListener = InspectorController.wrapCallback(this._nodeRemoved.bind(this));
- this._contentLoadedEventListener = InspectorController.wrapCallback(this._contentLoaded.bind(this));
-
- this.stylesheet = null;
- this.styles = {};
+ this._changedStyles = {};
this.reset();
}
@@ -130,7 +126,7 @@ WebInspector.ElementsPanel.prototype = {
get statusBarItems()
{
- return [this.nodeSearchButton, this.crumbsElement];
+ return [this.nodeSearchButton.element, this.crumbsElement];
},
updateStatusBarItems: function()
@@ -156,7 +152,7 @@ WebInspector.ElementsPanel.prototype = {
if (InspectorController.searchingForNode()) {
InspectorController.toggleNodeSearch();
- this.nodeSearchButton.removeStyleClass("toggled-on");
+ this.nodeSearchButton.toggled = false;
}
},
@@ -175,40 +171,27 @@ WebInspector.ElementsPanel.prototype = {
if (InspectorController.searchingForNode()) {
InspectorController.toggleNodeSearch();
- this.nodeSearchButton.removeStyleClass("toggled-on");
+ this.nodeSearchButton.toggled = false;
}
this.recentlyModifiedNodes = [];
- this.unregisterAllMutationEventListeners();
delete this.currentQuery;
this.searchCanceled();
- var inspectedWindow = Preferences.useDOMAgent ? WebInspector.domAgent.inspectedWindow : InspectorController.inspectedWindow();
- if (!inspectedWindow || !inspectedWindow.document)
+ var domWindow = WebInspector.domAgent.domWindow;
+ if (!domWindow || !domWindow.document || !domWindow.document.firstChild)
return;
- if (!inspectedWindow.document.firstChild) {
- function contentLoaded()
- {
- inspectedWindow.document.removeEventListener("DOMContentLoaded", contentLoadedCallback, false);
-
- this.reset();
- }
-
- var contentLoadedCallback = InspectorController.wrapCallback(contentLoaded.bind(this));
- inspectedWindow.document.addEventListener("DOMContentLoaded", contentLoadedCallback, false);
- return;
- }
-
// If the window isn't visible, return early so the DOM tree isn't built
// and mutation event listeners are not added.
if (!InspectorController.isWindowVisible())
return;
- this.registerMutationEventListeners(inspectedWindow);
+ var inspectedRootDocument = domWindow.document;
+ inspectedRootDocument.addEventListener("DOMNodeInserted", this._nodeInserted.bind(this));
+ inspectedRootDocument.addEventListener("DOMNodeRemoved", this._nodeRemoved.bind(this));
- var inspectedRootDocument = inspectedWindow.document;
this.rootDOMNode = inspectedRootDocument;
var canidateFocusNode = inspectedRootDocument.body || inspectedRootDocument.documentElement;
@@ -222,19 +205,11 @@ WebInspector.ElementsPanel.prototype = {
}
},
- includedInSearchResultsPropertyName: "__includedInInspectorSearchResults",
-
searchCanceled: function()
{
if (this._searchResults) {
- const searchResultsProperty = this.includedInSearchResultsPropertyName;
for (var i = 0; i < this._searchResults.length; ++i) {
- var node = this._searchResults[i];
-
- // Remove the searchResultsProperty since there might be an unfinished search.
- delete node[searchResultsProperty];
-
- var treeElement = this.treeOutline.findTreeElement(node);
+ var treeElement = this.treeOutline.findTreeElement(this._searchResults[i]);
if (treeElement)
treeElement.highlighted = false;
}
@@ -242,13 +217,9 @@ WebInspector.ElementsPanel.prototype = {
WebInspector.updateSearchMatchesCount(0, this);
- if (this._currentSearchChunkIntervalIdentifier) {
- clearInterval(this._currentSearchChunkIntervalIdentifier);
- delete this._currentSearchChunkIntervalIdentifier;
- }
-
this._currentSearchResultIndex = 0;
this._searchResults = [];
+ InjectedScriptAccess.searchCanceled(function() {});
},
performSearch: function(query)
@@ -260,241 +231,56 @@ WebInspector.ElementsPanel.prototype = {
if (!whitespaceTrimmedQuery.length)
return;
- var tagNameQuery = whitespaceTrimmedQuery;
- var attributeNameQuery = whitespaceTrimmedQuery;
- var startTagFound = (tagNameQuery.indexOf("<") === 0);
- var endTagFound = (tagNameQuery.lastIndexOf(">") === (tagNameQuery.length - 1));
-
- if (startTagFound || endTagFound) {
- var tagNameQueryLength = tagNameQuery.length;
- tagNameQuery = tagNameQuery.substring((startTagFound ? 1 : 0), (endTagFound ? (tagNameQueryLength - 1) : tagNameQueryLength));
- }
-
- // Check the tagNameQuery is it is a possibly valid tag name.
- if (!/^[a-zA-Z0-9\-_:]+$/.test(tagNameQuery))
- tagNameQuery = null;
-
- // Check the attributeNameQuery is it is a possibly valid tag name.
- if (!/^[a-zA-Z0-9\-_:]+$/.test(attributeNameQuery))
- attributeNameQuery = null;
-
- const escapedQuery = query.escapeCharacters("'");
- const escapedTagNameQuery = (tagNameQuery ? tagNameQuery.escapeCharacters("'") : null);
- const escapedWhitespaceTrimmedQuery = whitespaceTrimmedQuery.escapeCharacters("'");
- const searchResultsProperty = this.includedInSearchResultsPropertyName;
-
- var updatedMatchCountOnce = false;
- var matchesCountUpdateTimeout = null;
-
- function updateMatchesCount()
- {
- WebInspector.updateSearchMatchesCount(this._searchResults.length, this);
- matchesCountUpdateTimeout = null;
- updatedMatchCountOnce = true;
- }
-
- function updateMatchesCountSoon()
- {
- if (!updatedMatchCountOnce)
- return updateMatchesCount.call(this);
- if (matchesCountUpdateTimeout)
- return;
- // Update the matches count every half-second so it doesn't feel twitchy.
- matchesCountUpdateTimeout = setTimeout(updateMatchesCount.bind(this), 500);
- }
-
- function addNodesToResults(nodes, length, getItem)
- {
- if (!length)
- return;
-
- for (var i = 0; i < length; ++i) {
- var node = getItem.call(nodes, i);
- // Skip this node if it already has the property.
- if (searchResultsProperty in node)
- continue;
-
- if (!this._searchResults.length) {
- this._currentSearchResultIndex = 0;
- this.focusedDOMNode = node;
- }
-
- node[searchResultsProperty] = true;
- this._searchResults.push(node);
-
- // Highlight the tree element to show it matched the search.
- // FIXME: highlight the substrings in text nodes and attributes.
- var treeElement = this.treeOutline.findTreeElement(node);
- if (treeElement)
- treeElement.highlighted = true;
- }
-
- updateMatchesCountSoon.call(this);
- }
-
- function matchExactItems(doc)
- {
- matchExactId.call(this, doc);
- matchExactClassNames.call(this, doc);
- matchExactTagNames.call(this, doc);
- matchExactAttributeNames.call(this, doc);
- }
-
- function matchExactId(doc)
- {
- const result = doc.__proto__.getElementById.call(doc, whitespaceTrimmedQuery);
- addNodesToResults.call(this, result, (result ? 1 : 0), function() { return this });
- }
-
- function matchExactClassNames(doc)
- {
- const result = doc.__proto__.getElementsByClassName.call(doc, whitespaceTrimmedQuery);
- addNodesToResults.call(this, result, result.length, result.item);
- }
-
- function matchExactTagNames(doc)
- {
- if (!tagNameQuery)
- return;
- const result = doc.__proto__.getElementsByTagName.call(doc, tagNameQuery);
- addNodesToResults.call(this, result, result.length, result.item);
- }
-
- function matchExactAttributeNames(doc)
- {
- if (!attributeNameQuery)
- return;
- const result = doc.__proto__.querySelectorAll.call(doc, "[" + attributeNameQuery + "]");
- addNodesToResults.call(this, result, result.length, result.item);
- }
-
- function matchPartialTagNames(doc)
- {
- if (!tagNameQuery)
- return;
- const result = doc.__proto__.evaluate.call(doc, "//*[contains(name(), '" + escapedTagNameQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
- addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
- }
-
- function matchStartOfTagNames(doc)
- {
- if (!tagNameQuery)
- return;
- const result = doc.__proto__.evaluate.call(doc, "//*[starts-with(name(), '" + escapedTagNameQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
- addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
- }
-
- function matchPartialTagNamesAndAttributeValues(doc)
- {
- if (!tagNameQuery) {
- matchPartialAttributeValues.call(this, doc);
- return;
- }
-
- const result = doc.__proto__.evaluate.call(doc, "//*[contains(name(), '" + escapedTagNameQuery + "') or contains(@*, '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
- addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
- }
-
- function matchPartialAttributeValues(doc)
- {
- const result = doc.__proto__.evaluate.call(doc, "//*[contains(@*, '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
- addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
- }
-
- function matchStyleSelector(doc)
- {
- const result = doc.__proto__.querySelectorAll.call(doc, whitespaceTrimmedQuery);
- addNodesToResults.call(this, result, result.length, result.item);
- }
-
- function matchPlainText(doc)
- {
- const result = doc.__proto__.evaluate.call(doc, "//text()[contains(., '" + escapedQuery + "')] | //comment()[contains(., '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
- addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
- }
-
- function matchXPathQuery(doc)
- {
- const result = doc.__proto__.evaluate.call(doc, whitespaceTrimmedQuery, doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
- addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
- }
+ this._updatedMatchCountOnce = false;
+ this._matchesCountUpdateTimeout = null;
- function finishedSearching()
- {
- // Remove the searchResultsProperty now that the search is finished.
- for (var i = 0; i < this._searchResults.length; ++i)
- delete this._searchResults[i][searchResultsProperty];
- }
+ InjectedScriptAccess.performSearch(whitespaceTrimmedQuery, function() {});
+ },
- const mainFrameDocument = InspectorController.inspectedWindow().document;
- const searchDocuments = [mainFrameDocument];
-
- if (tagNameQuery && startTagFound && endTagFound)
- const searchFunctions = [matchExactTagNames, matchPlainText];
- else if (tagNameQuery && startTagFound)
- const searchFunctions = [matchStartOfTagNames, matchPlainText];
- else if (tagNameQuery && endTagFound) {
- // FIXME: we should have a matchEndOfTagNames search function if endTagFound is true but not startTagFound.
- // This requires ends-with() support in XPath, WebKit only supports starts-with() and contains().
- const searchFunctions = [matchPartialTagNames, matchPlainText];
- } else if (whitespaceTrimmedQuery === "//*" || whitespaceTrimmedQuery === "*") {
- // These queries will match every node. Matching everything isn't useful and can be slow for large pages,
- // so limit the search functions list to plain text and attribute matching.
- const searchFunctions = [matchPartialAttributeValues, matchPlainText];
- } else
- const searchFunctions = [matchExactItems, matchStyleSelector, matchPartialTagNamesAndAttributeValues, matchPlainText, matchXPathQuery];
-
- // Find all frames, iframes and object elements to search their documents.
- const querySelectorAllFunction = InspectorController.inspectedWindow().Document.prototype.querySelectorAll;
- const subdocumentResult = querySelectorAllFunction.call(mainFrameDocument, "iframe, frame, object");
-
- for (var i = 0; i < subdocumentResult.length; ++i) {
- var element = subdocumentResult.item(i);
- if (element.contentDocument)
- searchDocuments.push(element.contentDocument);
- }
+ _updateMatchesCount: function()
+ {
+ WebInspector.updateSearchMatchesCount(this._searchResults.length, this);
+ this._matchesCountUpdateTimeout = null;
+ this._updatedMatchCountOnce = true;
+ },
- const panel = this;
- var documentIndex = 0;
- var searchFunctionIndex = 0;
- var chunkIntervalIdentifier = null;
+ _updateMatchesCountSoon: function()
+ {
+ if (!this._updatedMatchCountOnce)
+ return this._updateMatchesCount();
+ if (this._matchesCountUpdateTimeout)
+ return;
+ // Update the matches count every half-second so it doesn't feel twitchy.
+ this._matchesCountUpdateTimeout = setTimeout(this._updateMatchesCount.bind(this), 500);
+ },
- // Split up the work into chunks so we don't block the UI thread while processing.
+ addNodesToSearchResult: function(nodeIds)
+ {
+ if (!nodeIds)
+ return;
- function processChunk()
- {
- var searchDocument = searchDocuments[documentIndex];
- var searchFunction = searchFunctions[searchFunctionIndex];
-
- if (++searchFunctionIndex > searchFunctions.length) {
- searchFunction = searchFunctions[0];
- searchFunctionIndex = 0;
-
- if (++documentIndex > searchDocuments.length) {
- if (panel._currentSearchChunkIntervalIdentifier === chunkIntervalIdentifier)
- delete panel._currentSearchChunkIntervalIdentifier;
- clearInterval(chunkIntervalIdentifier);
- finishedSearching.call(panel);
- return;
- }
+ var nodeIdsArray = nodeIds.split(",");
+ for (var i = 0; i < nodeIdsArray.length; ++i) {
+ var nodeId = nodeIdsArray[i];
+ var node = WebInspector.domAgent.nodeForId(nodeId);
+ if (!node)
+ continue;
- searchDocument = searchDocuments[documentIndex];
+ if (!this._searchResults.length) {
+ this._currentSearchResultIndex = 0;
+ this.focusedDOMNode = node;
}
- if (!searchDocument || !searchFunction)
- return;
+ this._searchResults.push(node);
- try {
- searchFunction.call(panel, searchDocument);
- } catch(err) {
- // ignore any exceptions. the query might be malformed, but we allow that.
- }
+ // Highlight the tree element to show it matched the search.
+ // FIXME: highlight the substrings in text nodes and attributes.
+ var treeElement = this.treeOutline.findTreeElement(node);
+ if (treeElement)
+ treeElement.highlighted = true;
}
- processChunk();
-
- chunkIntervalIdentifier = setInterval(processChunk, 25);
- this._currentSearchChunkIntervalIdentifier = chunkIntervalIdentifier;
+ this._updateMatchesCountSoon();
},
jumpToNextSearchResult: function()
@@ -515,12 +301,6 @@ WebInspector.ElementsPanel.prototype = {
this.focusedDOMNode = this._searchResults[this._currentSearchResultIndex];
},
- inspectedWindowCleared: function(window)
- {
- if (InspectorController.isWindowVisible())
- this.updateMutationEventListeners(window);
- },
-
renameSelector: function(oldIdentifier, newIdentifier, oldSelector, newSelector)
{
// TODO: Implement Shifting the oldSelector, and its contents to a newSelector
@@ -532,16 +312,16 @@ WebInspector.ElementsPanel.prototype = {
return;
var selector = style.parentRule.selectorText;
- if (!this.styles[identifier])
- this.styles[identifier] = {};
+ if (!this._changedStyles[identifier])
+ this._changedStyles[identifier] = {};
- if (!this.styles[identifier][selector])
- this.styles[identifier][selector] = {};
+ if (!this._changedStyles[identifier][selector])
+ this._changedStyles[identifier][selector] = {};
- if (!this.styles[identifier][selector][property])
+ if (!this._changedStyles[identifier][selector][property])
WebInspector.styleChanges += 1;
- this.styles[identifier][selector][property] = style.getPropertyValue(property);
+ this._changedStyles[identifier][selector][property] = style.getPropertyValue(property);
},
removeStyleChange: function(identifier, style, property)
@@ -550,11 +330,11 @@ WebInspector.ElementsPanel.prototype = {
return;
var selector = style.parentRule.selectorText;
- if (!this.styles[identifier] || !this.styles[identifier][selector])
+ if (!this._changedStyles[identifier] || !this._changedStyles[identifier][selector])
return;
- if (this.styles[identifier][selector][property]) {
- delete this.styles[identifier][selector][property];
+ if (this._changedStyles[identifier][selector][property]) {
+ delete this._changedStyles[identifier][selector][property];
WebInspector.styleChanges -= 1;
}
},
@@ -566,24 +346,24 @@ WebInspector.ElementsPanel.prototype = {
// Merge Down to Just Selectors
var mergedSelectors = {};
- for (var identifier in this.styles) {
- for (var selector in this.styles[identifier]) {
+ for (var identifier in this._changedStyles) {
+ for (var selector in this._changedStyles[identifier]) {
if (!mergedSelectors[selector])
- mergedSelectors[selector] = this.styles[identifier][selector];
+ mergedSelectors[selector] = this._changedStyles[identifier][selector];
else { // merge on selector
var merge = {};
for (var property in mergedSelectors[selector])
merge[property] = mergedSelectors[selector][property];
- for (var property in this.styles[identifier][selector]) {
+ for (var property in this._changedStyles[identifier][selector]) {
if (!merge[property])
- merge[property] = this.styles[identifier][selector][property];
+ merge[property] = this._changedStyles[identifier][selector][property];
else { // merge on property within a selector, include comment to notify user
var value1 = merge[property];
- var value2 = this.styles[identifier][selector][property];
+ var value2 = this._changedStyles[identifier][selector][property];
if (value1 === value2)
merge[property] = [value1];
- else if (Object.type(value1) === "array")
+ else if (value1 instanceof Array)
merge[property].push(value2);
else
merge[property] = [value1, value2];
@@ -615,7 +395,7 @@ WebInspector.ElementsPanel.prototype = {
for (var i = 0; i < properties.length; ++i) {
var property = properties[i];
var value = psuedoStyle[property];
- if (Object.type(value) !== "array")
+ if (!(value instanceof Array))
builder.push(displayProperty(property, value));
else {
if (value.length === 1)
@@ -632,55 +412,7 @@ WebInspector.ElementsPanel.prototype = {
}
WebInspector.showConsole();
- var result = builder.join("\n");
- InspectorController.inspectedWindow().console.log(result);
- },
-
- _addMutationEventListeners: function(monitoredWindow)
- {
- monitoredWindow.document.addEventListener("DOMNodeInserted", this._nodeInsertedEventListener, true);
- monitoredWindow.document.addEventListener("DOMNodeRemoved", this._nodeRemovedEventListener, true);
- if (monitoredWindow.frameElement)
- monitoredWindow.addEventListener("DOMContentLoaded", this._contentLoadedEventListener, true);
- },
-
- _removeMutationEventListeners: function(monitoredWindow)
- {
- if (monitoredWindow.frameElement)
- monitoredWindow.removeEventListener("DOMContentLoaded", this._contentLoadedEventListener, true);
- if (!monitoredWindow.document)
- return;
- monitoredWindow.document.removeEventListener("DOMNodeInserted", this._nodeInsertedEventListener, true);
- monitoredWindow.document.removeEventListener("DOMNodeRemoved", this._nodeRemovedEventListener, true);
- },
-
- updateMutationEventListeners: function(monitoredWindow)
- {
- this._addMutationEventListeners(monitoredWindow);
- },
-
- registerMutationEventListeners: function(monitoredWindow)
- {
- if (!monitoredWindow || this._mutationMonitoredWindows.indexOf(monitoredWindow) !== -1)
- return;
- this._mutationMonitoredWindows.push(monitoredWindow);
- if (InspectorController.isWindowVisible())
- this._addMutationEventListeners(monitoredWindow);
- },
-
- unregisterMutationEventListeners: function(monitoredWindow)
- {
- if (!monitoredWindow || this._mutationMonitoredWindows.indexOf(monitoredWindow) === -1)
- return;
- this._mutationMonitoredWindows.remove(monitoredWindow);
- this._removeMutationEventListeners(monitoredWindow);
- },
-
- unregisterAllMutationEventListeners: function()
- {
- for (var i = 0; i < this._mutationMonitoredWindows.length; ++i)
- this._removeMutationEventListeners(this._mutationMonitoredWindows[i]);
- this._mutationMonitoredWindows = [];
+ WebInspector.console.addMessage(new WebInspector.ConsoleTextMessage(builder.join("\n")));
},
get rootDOMNode()
@@ -703,13 +435,6 @@ WebInspector.ElementsPanel.prototype = {
this.treeOutline.focusedDOMNode = x;
},
- _contentLoaded: function(event)
- {
- this.recentlyModifiedNodes.push({node: event.target, parent: event.target.defaultView.frameElement, replaced: true});
- if (this.visible)
- this._updateModifiedNodesSoon();
- },
-
_nodeInserted: function(event)
{
this.recentlyModifiedNodes.push({node: event.target, parent: event.relatedNode, inserted: true});
@@ -747,14 +472,14 @@ WebInspector.ElementsPanel.prototype = {
if (!parent)
continue;
- var parentNodeItem = this.treeOutline.findTreeElement(parent, null, null, objectsAreSame);
+ var parentNodeItem = this.treeOutline.findTreeElement(parent);
if (parentNodeItem && !parentNodeItem.alreadyUpdatedChildren) {
parentNodeItem.updateChildren(replaced);
parentNodeItem.alreadyUpdatedChildren = true;
updatedParentTreeElements.push(parentNodeItem);
}
- if (!updateBreadcrumbs && (objectsAreSame(this.focusedDOMNode, parent) || isAncestorIncludingParentFrames(this.focusedDOMNode, parent)))
+ if (!updateBreadcrumbs && (this.focusedDOMNode === parent || isAncestor(this.focusedDOMNode, parent)))
updateBreadcrumbs = true;
}
@@ -814,7 +539,7 @@ WebInspector.ElementsPanel.prototype = {
var foundRoot = false;
var crumb = crumbs.firstChild;
while (crumb) {
- if (objectsAreSame(crumb.representedObject, this.rootDOMNode))
+ if (crumb.representedObject === this.rootDOMNode)
foundRoot = true;
if (foundRoot)
@@ -822,7 +547,7 @@ WebInspector.ElementsPanel.prototype = {
else
crumb.removeStyleClass("dimmed");
- if (objectsAreSame(crumb.representedObject, this.focusedDOMNode)) {
+ if (crumb.representedObject === this.focusedDOMNode) {
crumb.addStyleClass("selected");
handled = true;
} else {
@@ -875,11 +600,11 @@ WebInspector.ElementsPanel.prototype = {
}
foundRoot = false;
- for (var current = this.focusedDOMNode; current; current = parentNodeOrFrameElement(current)) {
+ for (var current = this.focusedDOMNode; current; current = current.parentNode) {
if (current.nodeType === Node.DOCUMENT_NODE)
continue;
- if (objectsAreSame(current, this.rootDOMNode))
+ if (current === this.rootDOMNode)
foundRoot = true;
var crumb = document.createElement("span");
@@ -962,7 +687,7 @@ WebInspector.ElementsPanel.prototype = {
if (foundRoot)
crumb.addStyleClass("dimmed");
- if (objectsAreSame(current, this.focusedDOMNode))
+ if (current === this.focusedDOMNode)
crumb.addStyleClass("selected");
if (!crumbs.childNodes.length)
crumb.addStyleClass("end");
@@ -1256,6 +981,16 @@ WebInspector.ElementsPanel.prototype = {
propertiesSidebarPane.needsUpdate = false;
},
+ updateEventListeners: function()
+ {
+ var eventListenersSidebarPane = this.sidebarPanes.eventListeners;
+ if (!eventListenersSidebarPane.expanded || !eventListenersSidebarPane.needsUpdate)
+ return;
+
+ eventListenersSidebarPane.update(this.focusedDOMNode);
+ eventListenersSidebarPane.needsUpdate = false;
+ },
+
handleKeyEvent: function(event)
{
this.treeOutline.handleKeyEvent(event);
@@ -1266,26 +1001,9 @@ WebInspector.ElementsPanel.prototype = {
// Don't prevent the normal copy if the user has a selection.
if (!window.getSelection().isCollapsed)
return;
-
- switch (this.focusedDOMNode.nodeType) {
- case Node.ELEMENT_NODE:
- var data = this.focusedDOMNode.outerHTML;
- break;
-
- case Node.COMMENT_NODE:
- var data = "<!--" + this.focusedDOMNode.nodeValue + "-->";
- break;
-
- default:
- case Node.TEXT_NODE:
- var data = this.focusedDOMNode.nodeValue;
- }
-
event.clipboardData.clearData();
event.preventDefault();
-
- if (data)
- event.clipboardData.setData("text/plain", data);
+ InspectorController.copyNode(this.focusedDOMNode.id);
},
rightSidebarResizerDragStart: function(event)
@@ -1316,10 +1034,7 @@ WebInspector.ElementsPanel.prototype = {
{
InspectorController.toggleNodeSearch();
- if (InspectorController.searchingForNode())
- this.nodeSearchButton.addStyleClass("toggled-on");
- else
- this.nodeSearchButton.removeStyleClass("toggled-on");
+ this.nodeSearchButton.toggled = InspectorController.searchingForNode();
}
}
diff --git a/WebCore/inspector/front-end/ElementsTreeOutline.js b/WebCore/inspector/front-end/ElementsTreeOutline.js
index ef53209..9e13773 100644
--- a/WebCore/inspector/front-end/ElementsTreeOutline.js
+++ b/WebCore/inspector/front-end/ElementsTreeOutline.js
@@ -31,7 +31,6 @@
WebInspector.ElementsTreeOutline = function() {
this.element = document.createElement("ol");
this.element.addEventListener("mousedown", this._onmousedown.bind(this), false);
- this.element.addEventListener("dblclick", this._ondblclick.bind(this), false);
this.element.addEventListener("mousemove", this._onmousemove.bind(this), false);
this.element.addEventListener("mouseout", this._onmouseout.bind(this), false);
@@ -51,7 +50,7 @@ WebInspector.ElementsTreeOutline.prototype = {
set rootDOMNode(x)
{
- if (objectsAreSame(this._rootDOMNode, x))
+ if (this._rootDOMNode === x)
return;
this._rootDOMNode = x;
@@ -66,7 +65,7 @@ WebInspector.ElementsTreeOutline.prototype = {
set focusedDOMNode(x)
{
- if (objectsAreSame(this._focusedDOMNode, x)) {
+ if (this._focusedDOMNode === x) {
this.revealAndSelectNode(x);
return;
}
@@ -79,11 +78,11 @@ WebInspector.ElementsTreeOutline.prototype = {
// and the select() call would change the focusedDOMNode and reenter this setter. So to
// avoid calling focusedNodeChanged() twice, first check if _focusedDOMNode is the same
// node as the one passed in.
- if (objectsAreSame(this._focusedDOMNode, x)) {
+ if (this._focusedDOMNode === x) {
this.focusedNodeChanged();
if (x && !this.suppressSelectHighlight) {
- InspectorController.highlightDOMNode(x);
+ InspectorController.highlightDOMNode(x.id);
if ("_restorePreviousHighlightNodeTimeout" in this)
clearTimeout(this._restorePreviousHighlightNodeTimeout);
@@ -92,7 +91,7 @@ WebInspector.ElementsTreeOutline.prototype = {
{
var hoveredNode = WebInspector.hoveredDOMNode;
if (hoveredNode)
- InspectorController.highlightDOMNode(hoveredNode);
+ InspectorController.highlightDOMNode(hoveredNode.id);
else
InspectorController.hideDOMNodeHighlight();
}
@@ -116,12 +115,12 @@ WebInspector.ElementsTreeOutline.prototype = {
this.appendChild(treeElement);
} else {
// FIXME: this could use findTreeElement to reuse a tree element if it already exists
- var node = (Preferences.ignoreWhitespace ? firstChildSkippingWhitespace.call(this.rootDOMNode) : this.rootDOMNode.firstChild);
+ var node = this.rootDOMNode.firstChild;
while (node) {
treeElement = new WebInspector.ElementsTreeElement(node);
treeElement.selectable = this.selectEnabled;
this.appendChild(treeElement);
- node = Preferences.ignoreWhitespace ? nextSiblingSkippingWhitespace.call(node) : node.nextSibling;
+ node = node.nextSibling;
}
}
@@ -138,19 +137,12 @@ WebInspector.ElementsTreeOutline.prototype = {
focusedNodeChanged: function(forceUpdate) {},
- findTreeElement: function(node, isAncestor, getParent, equal)
+ findTreeElement: function(node)
{
- if (typeof isAncestor === "undefined")
- isAncestor = isAncestorIncludingParentFrames;
- if (typeof getParent === "undefined")
- getParent = parentNodeOrFrameElement;
- if (typeof equal === "undefined")
- equal = objectsAreSame;
-
- var treeElement = TreeOutline.prototype.findTreeElement.call(this, node, isAncestor, getParent, equal);
+ var treeElement = TreeOutline.prototype.findTreeElement.call(this, node, isAncestorNode, parentNode);
if (!treeElement && node.nodeType === Node.TEXT_NODE) {
// The text node might have been inlined if it was short, so try to find the parent element.
- treeElement = TreeOutline.prototype.findTreeElement.call(this, node.parentNode, isAncestor, getParent, equal);
+ treeElement = TreeOutline.prototype.findTreeElement.call(this, node.parentNode, isAncestorNode, parentNode);
}
return treeElement;
@@ -193,16 +185,6 @@ WebInspector.ElementsTreeOutline.prototype = {
return element;
},
- _ondblclick: function(event)
- {
- var element = this._treeElementFromEvent(event);
-
- if (!element || !element.ondblclick)
- return;
-
- element.ondblclick(element, event);
- },
-
_onmousedown: function(event)
{
var element = this._treeElementFromEvent(event);
@@ -232,7 +214,7 @@ WebInspector.ElementsTreeOutline.prototype = {
_onmouseout: function(event)
{
var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY);
- if (nodeUnderMouse.isDescendant(this.element))
+ if (nodeUnderMouse && nodeUnderMouse.isDescendant(this.element))
return;
if (this._previousHoveredElement) {
@@ -248,14 +230,10 @@ WebInspector.ElementsTreeOutline.prototype.__proto__ = TreeOutline.prototype;
WebInspector.ElementsTreeElement = function(node)
{
- var hasChildren = node.contentDocument || (Preferences.ignoreWhitespace ? (firstChildSkippingWhitespace.call(node) ? true : false) : node.hasChildNodes());
- var titleInfo = nodeTitleInfo.call(node, hasChildren, WebInspector.linkifyURL);
-
- if (titleInfo.hasChildren)
- this.whitespaceIgnored = Preferences.ignoreWhitespace;
+ var hasChildrenOverride = node.hasChildNodes() && !this._showInlineText(node);
// The title will be updated in onattach.
- TreeElement.call(this, "", node, titleInfo.hasChildren);
+ TreeElement.call(this, "", node, hasChildrenOverride);
if (this.representedObject.nodeType == Node.ELEMENT_NODE)
this._canAddAttributes = true;
@@ -380,16 +358,19 @@ WebInspector.ElementsTreeElement.prototype = {
onpopulate: function()
{
- if (this.children.length || this.whitespaceIgnored !== Preferences.ignoreWhitespace)
+ if (this.children.length || this._showInlineText(this.representedObject))
return;
- this.whitespaceIgnored = Preferences.ignoreWhitespace;
-
this.updateChildren();
},
-
+
updateChildren: function(fullRefresh)
{
+ WebInspector.domAgent.getChildNodesAsync(this.representedObject, this._updateChildren.bind(this, fullRefresh));
+ },
+
+ _updateChildren: function(fullRefresh)
+ {
if (fullRefresh) {
var selectedTreeElement = this.treeOutline.selectedTreeElement;
if (selectedTreeElement && selectedTreeElement.hasAncestor(this))
@@ -403,14 +384,14 @@ WebInspector.ElementsTreeElement.prototype = {
function updateChildrenOfNode(node)
{
var treeOutline = treeElement.treeOutline;
- var child = (Preferences.ignoreWhitespace ? firstChildSkippingWhitespace.call(node) : node.firstChild);
+ var child = node.firstChild;
while (child) {
var currentTreeElement = treeElement.children[treeChildIndex];
- if (!currentTreeElement || !objectsAreSame(currentTreeElement.representedObject, child)) {
+ if (!currentTreeElement || currentTreeElement.representedObject !== child) {
// Find any existing element that is later in the children list.
var existingTreeElement = null;
for (var i = (treeChildIndex + 1); i < treeElement.children.length; ++i) {
- if (objectsAreSame(treeElement.children[i].representedObject, child)) {
+ if (treeElement.children[i].representedObject === child) {
existingTreeElement = treeElement.children[i];
break;
}
@@ -431,7 +412,7 @@ WebInspector.ElementsTreeElement.prototype = {
}
}
- child = Preferences.ignoreWhitespace ? nextSiblingSkippingWhitespace.call(child) : child.nextSibling;
+ child = child.nextSibling;
++treeChildIndex;
}
}
@@ -445,9 +426,7 @@ WebInspector.ElementsTreeElement.prototype = {
var currentNode = currentChild.representedObject;
var currentParentNode = currentNode.parentNode;
- if (objectsAreSame(currentParentNode, this.representedObject))
- continue;
- if (this.representedObject.contentDocument && objectsAreSame(currentParentNode, this.representedObject.contentDocument))
+ if (currentParentNode === this.representedObject)
continue;
var selectedTreeElement = this.treeOutline.selectedTreeElement;
@@ -455,13 +434,8 @@ WebInspector.ElementsTreeElement.prototype = {
this.select();
this.removeChildAtIndex(i);
-
- if (this.treeOutline.panel && currentNode.contentDocument)
- this.treeOutline.panel.unregisterMutationEventListeners(currentNode.contentDocument.defaultView);
}
- if (this.representedObject.contentDocument)
- updateChildrenOfNode(this.representedObject.contentDocument);
updateChildrenOfNode(this.representedObject);
var lastChild = this.children[this.children.length - 1];
@@ -477,9 +451,6 @@ WebInspector.ElementsTreeElement.prototype = {
onexpand: function()
{
this.treeOutline.updateSelection();
-
- if (this.treeOutline.panel && this.representedObject.contentDocument)
- this.treeOutline.panel.registerMutationEventListeners(this.representedObject.contentDocument.defaultView);
},
oncollapse: function()
@@ -693,7 +664,7 @@ WebInspector.ElementsTreeElement.prototype = {
}
if (!parseElement.hasAttributes()) {
- InspectorController.inspectedWindow().Element.prototype.removeAttribute.call(this.representedObject, attributeName);
+ this.representedObject.removeAttribute(attributeName);
this._updateTitle();
moveToNextAttributeIfNeeded.call(this);
return;
@@ -704,12 +675,12 @@ WebInspector.ElementsTreeElement.prototype = {
var attr = parseElement.attributes[i];
foundOriginalAttribute = foundOriginalAttribute || attr.name === attributeName;
try {
- InspectorController.inspectedWindow().Element.prototype.setAttribute.call(this.representedObject, attr.name, attr.value);
+ this.representedObject.setAttribute(attr.name, attr.value);
} catch(e) {} // ignore invalid attribute (innerHTML doesn't throw errors, but this can)
}
if (!foundOriginalAttribute)
- InspectorController.inspectedWindow().Element.prototype.removeAttribute.call(this.representedObject, attributeName);
+ this.representedObject.removeAttribute(attributeName);
this._updateTitle();
@@ -743,12 +714,115 @@ WebInspector.ElementsTreeElement.prototype = {
_updateTitle: function()
{
- var title = nodeTitleInfo.call(this.representedObject, this.hasChildren, WebInspector.linkifyURL).title;
+ var title = this._nodeTitleInfo(this.representedObject, this.hasChildren, WebInspector.linkifyURL).title;
this.title = "<span class=\"highlight\">" + title + "</span>";
delete this.selectionElement;
this.updateSelection();
this._preventFollowingLinksOnDoubleClick();
},
+
+ _nodeTitleInfo: function(node, hasChildren, linkify)
+ {
+ var info = {title: "", hasChildren: hasChildren};
+
+ switch (node.nodeType) {
+ case Node.DOCUMENT_NODE:
+ info.title = "Document";
+ break;
+
+ case Node.ELEMENT_NODE:
+ info.title = "<span class=\"webkit-html-tag\">&lt;" + node.nodeName.toLowerCase().escapeHTML();
+
+ if (node.hasAttributes()) {
+ for (var i = 0; i < node.attributes.length; ++i) {
+ var attr = node.attributes[i];
+ info.title += " <span class=\"webkit-html-attribute\"><span class=\"webkit-html-attribute-name\">" + attr.name.escapeHTML() + "</span>=&#8203;\"";
+
+ var value = attr.value;
+ if (linkify && (attr.name === "src" || attr.name === "href")) {
+ var value = value.replace(/([\/;:\)\]\}])/g, "$1\u200B");
+ info.title += linkify(attr.value, value, "webkit-html-attribute-value", node.nodeName.toLowerCase() == "a");
+ } else {
+ var value = value.escapeHTML();
+ value = value.replace(/([\/;:\)\]\}])/g, "$1&#8203;");
+ info.title += "<span class=\"webkit-html-attribute-value\">" + value + "</span>";
+ }
+ info.title += "\"</span>";
+ }
+ }
+ info.title += "&gt;</span>&#8203;";
+
+ // If this element only has a single child that is a text node,
+ // just show that text and the closing tag inline rather than
+ // create a subtree for them
+
+ var textChild = onlyTextChild.call(node);
+ var showInlineText = textChild && textChild.textContent.length < Preferences.maxInlineTextChildLength;
+
+ if (showInlineText) {
+ info.title += "<span class=\"webkit-html-text-node\">" + textChild.nodeValue.escapeHTML() + "</span>&#8203;<span class=\"webkit-html-tag\">&lt;/" + node.nodeName.toLowerCase().escapeHTML() + "&gt;</span>";
+ info.hasChildren = false;
+ }
+ break;
+
+ case Node.TEXT_NODE:
+ if (isNodeWhitespace.call(node))
+ info.title = "(whitespace)";
+ else {
+ if (node.parentNode && node.parentNode.nodeName.toLowerCase() == "script") {
+ var newNode = document.createElement("span");
+ newNode.textContent = node.textContent;
+
+ var javascriptSyntaxHighlighter = new WebInspector.JavaScriptSourceSyntaxHighlighter(null, null);
+ javascriptSyntaxHighlighter.syntaxHighlightLine(newNode, null);
+
+ info.title = "<span class=\"webkit-html-text-node webkit-html-js-node\">" + newNode.innerHTML.replace(/^[\n\r]*/, "").replace(/\s*$/, "") + "</span>";
+ } else if (node.parentNode && node.parentNode.nodeName.toLowerCase() == "style") {
+ var newNode = document.createElement("span");
+ newNode.textContent = node.textContent;
+
+ var cssSyntaxHighlighter = new WebInspector.CSSSourceSyntaxHighligher(null, null);
+ cssSyntaxHighlighter.syntaxHighlightLine(newNode, null);
+
+ info.title = "<span class=\"webkit-html-text-node webkit-html-css-node\">" + newNode.innerHTML.replace(/^[\n\r]*/, "").replace(/\s*$/, "") + "</span>";
+ } else {
+ info.title = "\"<span class=\"webkit-html-text-node\">" + node.nodeValue.escapeHTML() + "</span>\"";
+ }
+ }
+ break;
+
+ case Node.COMMENT_NODE:
+ info.title = "<span class=\"webkit-html-comment\">&lt;!--" + node.nodeValue.escapeHTML() + "--&gt;</span>";
+ break;
+
+ case Node.DOCUMENT_TYPE_NODE:
+ info.title = "<span class=\"webkit-html-doctype\">&lt;!DOCTYPE " + node.nodeName;
+ if (node.publicId) {
+ info.title += " PUBLIC \"" + node.publicId + "\"";
+ if (node.systemId)
+ info.title += " \"" + node.systemId + "\"";
+ } else if (node.systemId)
+ info.title += " SYSTEM \"" + node.systemId + "\"";
+ if (node.internalSubset)
+ info.title += " [" + node.internalSubset + "]";
+ info.title += "&gt;</span>";
+ break;
+ default:
+ info.title = node.nodeName.toLowerCase().collapseWhitespace().escapeHTML();
+ }
+
+ return info;
+ },
+
+ _showInlineText: function(node)
+ {
+ if (node.nodeType === Node.ELEMENT_NODE) {
+ var textChild = onlyTextChild.call(node);
+ if (textChild && textChild.textContent.length < Preferences.maxInlineTextChildLength)
+ return true;
+ }
+ return false;
+ }
}
WebInspector.ElementsTreeElement.prototype.__proto__ = TreeElement.prototype;
diff --git a/WebCore/inspector/front-end/EventListenersSidebarPane.js b/WebCore/inspector/front-end/EventListenersSidebarPane.js
new file mode 100644
index 0000000..55b8e55
--- /dev/null
+++ b/WebCore/inspector/front-end/EventListenersSidebarPane.js
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.EventListenersSidebarPane = function()
+{
+ WebInspector.SidebarPane.call(this, WebInspector.UIString("Event Listeners"));
+ this.bodyElement.addStyleClass("events-pane");
+
+ this.sections = [];
+
+ this.settingsSelectElement = document.createElement("select");
+
+ var option = document.createElement("option");
+ option.value = "all";
+ if (Preferences.eventListenersFilter === "all")
+ option.selected = true;
+ option.label = WebInspector.UIString("All Nodes");
+ this.settingsSelectElement.appendChild(option);
+
+ option = document.createElement("option");
+ option.value = "selected";
+ if (Preferences.eventListenersFilter === "selected")
+ option.selected = true;
+ option.label = WebInspector.UIString("Selected Node Only");
+ this.settingsSelectElement.appendChild(option);
+
+ this.settingsSelectElement.addEventListener("click", function(event) { event.stopPropagation() }, false);
+ this.settingsSelectElement.addEventListener("change", this._changeSetting.bind(this), false);
+
+ this.titleElement.appendChild(this.settingsSelectElement);
+}
+
+WebInspector.EventListenersSidebarPane.prototype = {
+ update: function(node)
+ {
+ var body = this.bodyElement;
+ body.removeChildren();
+ this.sections = [];
+
+ var self = this;
+ function callback(nodeId, eventListeners) {
+ var sectionNames = [];
+ var sectionMap = {};
+ for (var i = 0; i < eventListeners.length; ++i) {
+ var eventListener = eventListeners[i];
+ eventListener.node = WebInspector.domAgent.nodeForId(eventListener.nodeId);
+ delete eventListener.nodeId; // no longer needed
+ var type = eventListener.type;
+ var section = sectionMap[type];
+ if (!section) {
+ section = new WebInspector.EventListenersSection(type, nodeId);
+ sectionMap[type] = section;
+ sectionNames.push(type);
+ self.sections.push(section);
+ }
+ section.addListener(eventListener);
+ }
+
+ if (sectionNames.length === 0) {
+ var div = document.createElement("div");
+ div.className = "info";
+ div.textContent = WebInspector.UIString("No Event Listeners");
+ body.appendChild(div);
+ return;
+ }
+
+ sectionNames.sort();
+ for (var i = 0; i < sectionNames.length; ++i) {
+ var section = sectionMap[sectionNames[i]];
+ section.update();
+ body.appendChild(section.element);
+ }
+ }
+
+ WebInspector.EventListeners.getEventListenersForNodeAsync(node, callback);
+ },
+
+ _changeSetting: function(event)
+ {
+ var selectedOption = this.settingsSelectElement[this.settingsSelectElement.selectedIndex];
+ Preferences.eventListenersFilter = selectedOption.value;
+
+ InspectorController.setSetting("event-listeners-filter", Preferences.eventListenersFilter);
+
+ for (var i = 0; i < this.sections.length; ++i)
+ this.sections[i].update();
+ }
+}
+
+WebInspector.EventListenersSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
+
+WebInspector.EventListenersSection = function(title, nodeId)
+{
+ this.eventListeners = [];
+ this._nodeId = nodeId;
+ WebInspector.PropertiesSection.call(this, title);
+
+ // Changed from a Properties List
+ this.propertiesElement.parentNode.removeChild(this.propertiesElement);
+ delete this.propertiesElement;
+ delete this.propertiesTreeOutline;
+
+ this.eventBars = document.createElement("div");
+ this.eventBars.className = "event-bars";
+ this.element.appendChild(this.eventBars);
+}
+
+WebInspector.EventListenersSection.prototype = {
+ update: function()
+ {
+ // A Filtered Array simplifies when to create connectors
+ var filteredEventListeners = this.eventListeners;
+ if (Preferences.eventListenersFilter === "selected") {
+ filteredEventListeners = [];
+ for (var i = 0; i < this.eventListeners.length; ++i) {
+ var eventListener = this.eventListeners[i];
+ if (eventListener.node.id === this._nodeId)
+ filteredEventListeners.push(eventListener);
+ }
+ }
+
+ this.eventBars.removeChildren();
+ var length = filteredEventListeners.length;
+ for (var i = 0; i < length; ++i) {
+ var eventListener = filteredEventListeners[i];
+ var eventListenerBar = new WebInspector.EventListenerBar(eventListener);
+ if (i < length - 1) {
+ var connector = document.createElement("div");
+ connector.className = "event-bar-connector";
+ eventListenerBar.element.appendChild(connector);
+ }
+
+ this.eventBars.appendChild(eventListenerBar.element);
+ }
+ },
+
+ addListener: function(eventListener)
+ {
+ this.eventListeners.push(eventListener);
+ }
+}
+
+WebInspector.EventListenersSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;
+
+WebInspector.EventListenerBar = function(eventListener)
+{
+ this.eventListener = eventListener;
+ WebInspector.ObjectPropertiesSection.call(this, null, this._getFunctionDisplayName(), this._getNodeDisplayName());
+ this.editable = false;
+ this.element.className = "event-bar"; /* Changed from "section" */
+ this.propertiesElement.className = "event-properties"; /* Changed from "properties" */
+}
+
+WebInspector.EventListenerBar.prototype = {
+ update: function()
+ {
+ var properties = [];
+ for (var propertyName in this.eventListener) {
+ // Just build properties in place - no need to reach out for injected script.
+ var value = this.eventListener[propertyName];
+ if (value instanceof WebInspector.DOMNode)
+ value = new WebInspector.ObjectProxy(value.id, [], 0, appropriateSelectorForNode(value), true);
+ else
+ value = WebInspector.ObjectProxy.wrapPrimitiveValue(value);
+ properties.push(new WebInspector.ObjectPropertyProxy(propertyName, value));
+ }
+ this.updateProperties(properties);
+ },
+
+ _getNodeDisplayName: function()
+ {
+ var node = this.eventListener.node;
+ if (!node)
+ return "";
+
+ if (node.nodeType === Node.DOCUMENT_NODE)
+ return "document";
+
+ return appropriateSelectorForNode(node);
+ },
+
+ _getFunctionDisplayName: function()
+ {
+ // TODO: v8 does not yet provide the raw function, this handles such a case with a placeholder
+ // I didn't make this a UIString because it should be implemented eventually.
+ if (!this.eventListener.listener)
+ return "(listener)";
+
+ // Requires that Function.toString() return at least the function's signature
+ var match = this.eventListener.listener.toString().match(/function ([^\(]+?)\(/);
+ return (match ? match[1] : WebInspector.UIString("(anonymous function)"));
+ }
+}
+
+WebInspector.EventListenerBar.prototype.__proto__ = WebInspector.ObjectPropertiesSection.prototype;
diff --git a/WebCore/inspector/front-end/ImageView.js b/WebCore/inspector/front-end/ImageView.js
index 001ffdd..96e1a6e 100644
--- a/WebCore/inspector/front-end/ImageView.js
+++ b/WebCore/inspector/front-end/ImageView.js
@@ -37,6 +37,7 @@ WebInspector.ImageView = function(resource)
this.contentElement.appendChild(container);
this.imagePreviewElement = document.createElement("img");
+ this.imagePreviewElement.addStyleClass("resource-image-view");
this.imagePreviewElement.setAttribute("src", this.resource.url);
container.appendChild(this.imagePreviewElement);
diff --git a/WebCore/inspector/front-end/Images/cookie.png b/WebCore/inspector/front-end/Images/cookie.png
new file mode 100644
index 0000000..90c3c15
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/cookie.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/domStorage.png b/WebCore/inspector/front-end/Images/domStorage.png
deleted file mode 100644
index 028550c..0000000
--- a/WebCore/inspector/front-end/Images/domStorage.png
+++ /dev/null
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/errorRedDot.png b/WebCore/inspector/front-end/Images/errorRedDot.png
new file mode 100644
index 0000000..6f0b164
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/errorRedDot.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/grayConnectorPoint.png b/WebCore/inspector/front-end/Images/grayConnectorPoint.png
new file mode 100644
index 0000000..fddc7ea
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/grayConnectorPoint.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/localStorage.png b/WebCore/inspector/front-end/Images/localStorage.png
new file mode 100644
index 0000000..44a3019
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/localStorage.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/paneSettingsButtons.png b/WebCore/inspector/front-end/Images/paneSettingsButtons.png
new file mode 100644
index 0000000..36a6244
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/paneSettingsButtons.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/sessionStorage.png b/WebCore/inspector/front-end/Images/sessionStorage.png
new file mode 100644
index 0000000..4d50e35
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/sessionStorage.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/databasesIcon.png b/WebCore/inspector/front-end/Images/storageIcon.png
index 79c7bb3..79c7bb3 100644
--- a/WebCore/inspector/front-end/Images/databasesIcon.png
+++ b/WebCore/inspector/front-end/Images/storageIcon.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/successGreenDot.png b/WebCore/inspector/front-end/Images/successGreenDot.png
new file mode 100644
index 0000000..8b9319c
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/successGreenDot.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/warningOrangeDot.png b/WebCore/inspector/front-end/Images/warningOrangeDot.png
new file mode 100644
index 0000000..8c8b635
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/warningOrangeDot.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/whiteConnectorPoint.png b/WebCore/inspector/front-end/Images/whiteConnectorPoint.png
new file mode 100644
index 0000000..c8fb1cf
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/whiteConnectorPoint.png
Binary files differ
diff --git a/WebCore/inspector/front-end/InjectedScript.js b/WebCore/inspector/front-end/InjectedScript.js
index 4611b48..75c8ced 100644
--- a/WebCore/inspector/front-end/InjectedScript.js
+++ b/WebCore/inspector/front-end/InjectedScript.js
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2007 Apple Inc. All rights reserved.
- * Copyright (C) 2009 Joseph Pecoraro
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,12 +26,33 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-var InjectedScript = {
- _styles: {},
- _styleRules: {},
- _lastStyleId: 0,
- _lastStyleRuleId: 0
-};
+var InjectedScript = {};
+
+// Called from within InspectorController on the 'inspected page' side.
+InjectedScript.reset = function()
+{
+ InjectedScript._styles = {};
+ InjectedScript._styleRules = {};
+ InjectedScript._lastStyleId = 0;
+ InjectedScript._lastStyleRuleId = 0;
+ InjectedScript._searchResults = [];
+ InjectedScript._includedInSearchResultsPropertyName = "__includedInInspectorSearchResults";
+}
+
+InjectedScript.reset();
+
+InjectedScript.dispatch = function(methodName, args, callId)
+{
+ var argsArray = JSON.parse(args);
+ if (callId)
+ argsArray.splice(0, 0, callId); // Methods that run asynchronously have a call back id parameter.
+ var result = InjectedScript[methodName].apply(InjectedScript, argsArray);
+ if (typeof result === "undefined") {
+ InjectedScript._window().console.error("Web Inspector error: InjectedScript.%s returns undefined", methodName);
+ result = null;
+ }
+ return JSON.stringify(result);
+}
InjectedScript.getStyles = function(nodeId, authorOnly)
{
@@ -99,6 +119,10 @@ InjectedScript.applyStyleText = function(styleId, styleText, propertyName)
style.removeProperty(propertyName);
}
+ // Notify caller that the property was successfully deleted.
+ if (!styleTextLength)
+ return [null, [propertyName]];
+
if (!tempStyle.length)
return false;
@@ -133,6 +157,7 @@ InjectedScript.applyStyleText = function(styleId, styleText, propertyName)
InjectedScript.setStyleText = function(style, cssText)
{
style.cssText = cssText;
+ return true;
}
InjectedScript.toggleStyleEnabled = function(styleId, propertyName, disabled)
@@ -174,12 +199,14 @@ InjectedScript.toggleStyleEnabled = function(styleId, propertyName, disabled)
return InjectedScript._serializeStyle(style, true);
}
-InjectedScript.applyStyleRuleText = function(ruleId, newContent, selectedNode)
+InjectedScript.applyStyleRuleText = function(ruleId, newContent, selectedNodeId)
{
var rule = InjectedScript._styleRules[ruleId];
if (!rule)
return false;
+ var selectedNode = InjectedScript._nodeForId(selectedNodeId);
+
try {
var stylesheet = rule.parentStyleSheet;
stylesheet.addRule(newContent);
@@ -194,20 +221,14 @@ InjectedScript.applyStyleRuleText = function(ruleId, newContent, selectedNode)
}
}
- var nodes = selectedNode.ownerDocument.querySelectorAll(newContent);
- for (var i = 0; i < nodes.length; ++i) {
- if (nodes[i] === selectedNode) {
- return [InjectedScript._serializeRule(newRule), true];
- }
- }
- return [InjectedScript._serializeRule(newRule), false];
+ return [InjectedScript._serializeRule(newRule), InjectedScript._doesSelectorAffectNode(newContent, selectedNode)];
} catch(e) {
// Report invalid syntax.
return false;
}
}
-InjectedScript.addStyleSelector = function(newContent)
+InjectedScript.addStyleSelector = function(newContent, selectedNodeId)
{
var stylesheet = InjectedScript.stylesheet;
if (!stylesheet) {
@@ -227,10 +248,28 @@ InjectedScript.addStyleSelector = function(newContent)
return false;
}
- return InjectedScript._serializeRule(stylesheet.cssRules[stylesheet.cssRules.length - 1]);
+ var selectedNode = InjectedScript._nodeForId(selectedNodeId);
+ var rule = stylesheet.cssRules[stylesheet.cssRules.length - 1];
+ rule.__isViaInspector = true;
+
+ return [ InjectedScript._serializeRule(rule), InjectedScript._doesSelectorAffectNode(newContent, selectedNode) ];
}
-InjectedScript.setStyleProperty = function(styleId, name, value) {
+InjectedScript._doesSelectorAffectNode = function(selectorText, node)
+{
+ if (!node)
+ return false;
+ var nodes = node.ownerDocument.querySelectorAll(selectorText);
+ for (var i = 0; i < nodes.length; ++i) {
+ if (nodes[i] === node) {
+ return true;
+ }
+ }
+ return false;
+}
+
+InjectedScript.setStyleProperty = function(styleId, name, value)
+{
var style = InjectedScript._styles[styleId];
if (!style)
return false;
@@ -251,17 +290,18 @@ InjectedScript._serializeRule = function(rule)
}
ruleValue.isUserAgent = parentStyleSheet && !parentStyleSheet.ownerNode && !parentStyleSheet.href;
ruleValue.isUser = parentStyleSheet && parentStyleSheet.ownerNode && parentStyleSheet.ownerNode.nodeName == "#document";
+ ruleValue.isViaInspector = !!rule.__isViaInspector;
// Bind editable scripts only.
var doBind = !ruleValue.isUserAgent && !ruleValue.isUser;
ruleValue.style = InjectedScript._serializeStyle(rule.style, doBind);
if (doBind) {
- if (!rule._id) {
- rule._id = InjectedScript._lastStyleRuleId++;
- InjectedScript._styleRules[rule._id] = rule;
+ if (!rule.id) {
+ rule.id = InjectedScript._lastStyleRuleId++;
+ InjectedScript._styleRules[rule.id] = rule;
}
- ruleValue.id = rule._id;
+ ruleValue.id = rule.id;
}
return ruleValue;
}
@@ -295,11 +335,11 @@ InjectedScript._serializeStyle = function(style, doBind)
result.uniqueStyleProperties = InjectedScript._getUniqueStyleProperties(style);
if (doBind) {
- if (!style._id) {
- style._id = InjectedScript._lastStyleId++;
- InjectedScript._styles[style._id] = style;
+ if (!style.id) {
+ style.id = InjectedScript._lastStyleId++;
+ InjectedScript._styles[style.id] = style;
}
- result.id = style._id;
+ result.id = style.id;
}
return result;
}
@@ -389,7 +429,7 @@ InjectedScript.getPrototypes = function(nodeId)
var result = [];
for (var prototype = node; prototype; prototype = prototype.__proto__) {
- var title = Object.describe(prototype);
+ var title = Object.describe(prototype, true);
if (title.match(/Prototype$/)) {
title = title.replace(/Prototype$/, "");
}
@@ -405,39 +445,26 @@ InjectedScript.getProperties = function(objectProxy, ignoreHasOwnProperty)
return false;
var properties = [];
+
// Go over properties, prepare results.
for (var propertyName in object) {
if (!ignoreHasOwnProperty && "hasOwnProperty" in object && !object.hasOwnProperty(propertyName))
continue;
- //TODO: remove this once object becomes really remote.
- if (propertyName === "__treeElementIdentifier")
- continue;
var property = {};
property.name = propertyName;
+ property.parentObjectProxy = objectProxy;
var isGetter = object["__lookupGetter__"] && object.__lookupGetter__(propertyName);
if (!property.isGetter) {
var childObject = object[propertyName];
- property.type = typeof childObject;
- property.textContent = Object.describe(childObject, true);
- property.parentObjectProxy = objectProxy;
- var parentPath = objectProxy.path.slice();
- property.childObjectProxy = {
- objectId : objectProxy.objectId,
- path : parentPath.splice(parentPath.length, 0, propertyName),
- protoDepth : objectProxy.protoDepth
- };
- if (childObject && (property.type === "object" || property.type === "function")) {
- for (var subPropertyName in childObject) {
- if (propertyName === "__treeElementIdentifier")
- continue;
- property.hasChildren = true;
- break;
- }
- }
+ var childObjectProxy = new InjectedScript.createProxyObject(childObject, objectProxy.objectId, true);
+ childObjectProxy.path = objectProxy.path ? objectProxy.path.slice() : [];
+ childObjectProxy.path.push(propertyName);
+ childObjectProxy.protoDepth = objectProxy.protoDepth || 0;
+ property.value = childObjectProxy;
} else {
// FIXME: this should show something like "getter" (bug 16734).
- property.textContent = "\u2014"; // em dash
+ property.value = { description: "\u2014" }; // em dash
property.isGetter = true;
}
properties.push(property);
@@ -479,6 +506,418 @@ InjectedScript.setPropertyValue = function(objectProxy, propertyName, expression
}
}
+
+InjectedScript.getCompletions = function(expression, includeInspectorCommandLineAPI, callFrameId)
+{
+ var props = {};
+ try {
+ var expressionResult;
+ // Evaluate on call frame if call frame id is available.
+ if (typeof callFrameId === "number") {
+ var callFrame = InjectedScript._callFrameForId(callFrameId);
+ if (!callFrame)
+ return props;
+ expressionResult = InjectedScript._evaluateOn(callFrame.evaluate, callFrame, expression);
+ } else {
+ expressionResult = InjectedScript._evaluateOn(InjectedScript._window().eval, InjectedScript._window(), expression);
+ }
+ for (var prop in expressionResult)
+ props[prop] = true;
+ if (includeInspectorCommandLineAPI)
+ for (var prop in InjectedScript._window()._inspectorCommandLineAPI)
+ if (prop.charAt(0) !== '_')
+ props[prop] = true;
+ } catch(e) {
+ }
+ return props;
+}
+
+InjectedScript.evaluate = function(expression, objectGroup)
+{
+ return InjectedScript._evaluateAndWrap(InjectedScript._window().eval, InjectedScript._window(), expression, objectGroup);
+}
+
+InjectedScript._evaluateAndWrap = function(evalFunction, object, expression, objectGroup)
+{
+ var result = {};
+ try {
+ result.value = InspectorController.wrapObject(InjectedScript._evaluateOn(evalFunction, object, expression), objectGroup);
+ // Handle error that might have happened while describing result.
+ if (result.value.errorText) {
+ result.value = result.value.errorText;
+ result.isException = true;
+ }
+ } catch (e) {
+ result.value = e.toString();
+ result.isException = true;
+ }
+ return result;
+}
+
+InjectedScript._evaluateOn = function(evalFunction, object, expression)
+{
+ InjectedScript._ensureCommandLineAPIInstalled(evalFunction, object);
+ // Surround the expression in with statements to inject our command line API so that
+ // the window object properties still take more precedent than our API functions.
+ expression = "with (window._inspectorCommandLineAPI) { with (window) { " + expression + " } }";
+ var value = evalFunction.call(object, expression);
+
+ // When evaluating on call frame error is not thrown, but returned as a value.
+ if (Object.type(value) === "error")
+ throw value.toString();
+
+ return value;
+}
+
+InjectedScript.addInspectedNode = function(nodeId)
+{
+ var node = InjectedScript._nodeForId(nodeId);
+ if (!node)
+ return false;
+
+ InjectedScript._ensureCommandLineAPIInstalled(InjectedScript._window().eval, InjectedScript._window());
+ var inspectedNodes = InjectedScript._window()._inspectorCommandLineAPI._inspectedNodes;
+ inspectedNodes.unshift(node);
+ if (inspectedNodes.length >= 5)
+ inspectedNodes.pop();
+ return true;
+}
+
+InjectedScript.performSearch = function(whitespaceTrimmedQuery)
+{
+ var tagNameQuery = whitespaceTrimmedQuery;
+ var attributeNameQuery = whitespaceTrimmedQuery;
+ var startTagFound = (tagNameQuery.indexOf("<") === 0);
+ var endTagFound = (tagNameQuery.lastIndexOf(">") === (tagNameQuery.length - 1));
+
+ if (startTagFound || endTagFound) {
+ var tagNameQueryLength = tagNameQuery.length;
+ tagNameQuery = tagNameQuery.substring((startTagFound ? 1 : 0), (endTagFound ? (tagNameQueryLength - 1) : tagNameQueryLength));
+ }
+
+ // Check the tagNameQuery is it is a possibly valid tag name.
+ if (!/^[a-zA-Z0-9\-_:]+$/.test(tagNameQuery))
+ tagNameQuery = null;
+
+ // Check the attributeNameQuery is it is a possibly valid tag name.
+ if (!/^[a-zA-Z0-9\-_:]+$/.test(attributeNameQuery))
+ attributeNameQuery = null;
+
+ const escapedQuery = whitespaceTrimmedQuery.escapeCharacters("'");
+ const escapedTagNameQuery = (tagNameQuery ? tagNameQuery.escapeCharacters("'") : null);
+ const escapedWhitespaceTrimmedQuery = whitespaceTrimmedQuery.escapeCharacters("'");
+ const searchResultsProperty = InjectedScript._includedInSearchResultsPropertyName;
+
+ function addNodesToResults(nodes, length, getItem)
+ {
+ if (!length)
+ return;
+
+ var nodeIds = [];
+ for (var i = 0; i < length; ++i) {
+ var node = getItem.call(nodes, i);
+ // Skip this node if it already has the property.
+ if (searchResultsProperty in node)
+ continue;
+
+ if (!InjectedScript._searchResults.length) {
+ InjectedScript._currentSearchResultIndex = 0;
+ }
+
+ node[searchResultsProperty] = true;
+ InjectedScript._searchResults.push(node);
+ var nodeId = InspectorController.pushNodePathToFrontend(node, false);
+ nodeIds.push(nodeId);
+ }
+ InspectorController.addNodesToSearchResult(nodeIds.join(","));
+ }
+
+ function matchExactItems(doc)
+ {
+ matchExactId.call(this, doc);
+ matchExactClassNames.call(this, doc);
+ matchExactTagNames.call(this, doc);
+ matchExactAttributeNames.call(this, doc);
+ }
+
+ function matchExactId(doc)
+ {
+ const result = doc.__proto__.getElementById.call(doc, whitespaceTrimmedQuery);
+ addNodesToResults.call(this, result, (result ? 1 : 0), function() { return this });
+ }
+
+ function matchExactClassNames(doc)
+ {
+ const result = doc.__proto__.getElementsByClassName.call(doc, whitespaceTrimmedQuery);
+ addNodesToResults.call(this, result, result.length, result.item);
+ }
+
+ function matchExactTagNames(doc)
+ {
+ if (!tagNameQuery)
+ return;
+ const result = doc.__proto__.getElementsByTagName.call(doc, tagNameQuery);
+ addNodesToResults.call(this, result, result.length, result.item);
+ }
+
+ function matchExactAttributeNames(doc)
+ {
+ if (!attributeNameQuery)
+ return;
+ const result = doc.__proto__.querySelectorAll.call(doc, "[" + attributeNameQuery + "]");
+ addNodesToResults.call(this, result, result.length, result.item);
+ }
+
+ function matchPartialTagNames(doc)
+ {
+ if (!tagNameQuery)
+ return;
+ const result = doc.__proto__.evaluate.call(doc, "//*[contains(name(), '" + escapedTagNameQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
+ addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
+ }
+
+ function matchStartOfTagNames(doc)
+ {
+ if (!tagNameQuery)
+ return;
+ const result = doc.__proto__.evaluate.call(doc, "//*[starts-with(name(), '" + escapedTagNameQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
+ addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
+ }
+
+ function matchPartialTagNamesAndAttributeValues(doc)
+ {
+ if (!tagNameQuery) {
+ matchPartialAttributeValues.call(this, doc);
+ return;
+ }
+
+ const result = doc.__proto__.evaluate.call(doc, "//*[contains(name(), '" + escapedTagNameQuery + "') or contains(@*, '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
+ addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
+ }
+
+ function matchPartialAttributeValues(doc)
+ {
+ const result = doc.__proto__.evaluate.call(doc, "//*[contains(@*, '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
+ addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
+ }
+
+ function matchStyleSelector(doc)
+ {
+ const result = doc.__proto__.querySelectorAll.call(doc, whitespaceTrimmedQuery);
+ addNodesToResults.call(this, result, result.length, result.item);
+ }
+
+ function matchPlainText(doc)
+ {
+ const result = doc.__proto__.evaluate.call(doc, "//text()[contains(., '" + escapedQuery + "')] | //comment()[contains(., '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
+ addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
+ }
+
+ function matchXPathQuery(doc)
+ {
+ const result = doc.__proto__.evaluate.call(doc, whitespaceTrimmedQuery, doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
+ addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
+ }
+
+ function finishedSearching()
+ {
+ // Remove the searchResultsProperty now that the search is finished.
+ for (var i = 0; i < InjectedScript._searchResults.length; ++i)
+ delete InjectedScript._searchResults[i][searchResultsProperty];
+ }
+
+ const mainFrameDocument = InjectedScript._window().document;
+ const searchDocuments = [mainFrameDocument];
+ var searchFunctions;
+ if (tagNameQuery && startTagFound && endTagFound)
+ searchFunctions = [matchExactTagNames, matchPlainText];
+ else if (tagNameQuery && startTagFound)
+ searchFunctions = [matchStartOfTagNames, matchPlainText];
+ else if (tagNameQuery && endTagFound) {
+ // FIXME: we should have a matchEndOfTagNames search function if endTagFound is true but not startTagFound.
+ // This requires ends-with() support in XPath, WebKit only supports starts-with() and contains().
+ searchFunctions = [matchPartialTagNames, matchPlainText];
+ } else if (whitespaceTrimmedQuery === "//*" || whitespaceTrimmedQuery === "*") {
+ // These queries will match every node. Matching everything isn't useful and can be slow for large pages,
+ // so limit the search functions list to plain text and attribute matching.
+ searchFunctions = [matchPartialAttributeValues, matchPlainText];
+ } else
+ searchFunctions = [matchExactItems, matchStyleSelector, matchPartialTagNamesAndAttributeValues, matchPlainText, matchXPathQuery];
+
+ // Find all frames, iframes and object elements to search their documents.
+ const querySelectorAllFunction = InjectedScript._window().Document.prototype.querySelectorAll;
+ const subdocumentResult = querySelectorAllFunction.call(mainFrameDocument, "iframe, frame, object");
+
+ for (var i = 0; i < subdocumentResult.length; ++i) {
+ var element = subdocumentResult.item(i);
+ if (element.contentDocument)
+ searchDocuments.push(element.contentDocument);
+ }
+
+ const panel = InjectedScript;
+ var documentIndex = 0;
+ var searchFunctionIndex = 0;
+ var chunkIntervalIdentifier = null;
+
+ // Split up the work into chunks so we don't block the UI thread while processing.
+
+ function processChunk()
+ {
+ var searchDocument = searchDocuments[documentIndex];
+ var searchFunction = searchFunctions[searchFunctionIndex];
+
+ if (++searchFunctionIndex > searchFunctions.length) {
+ searchFunction = searchFunctions[0];
+ searchFunctionIndex = 0;
+
+ if (++documentIndex > searchDocuments.length) {
+ if (panel._currentSearchChunkIntervalIdentifier === chunkIntervalIdentifier)
+ delete panel._currentSearchChunkIntervalIdentifier;
+ clearInterval(chunkIntervalIdentifier);
+ finishedSearching.call(panel);
+ return;
+ }
+
+ searchDocument = searchDocuments[documentIndex];
+ }
+
+ if (!searchDocument || !searchFunction)
+ return;
+
+ try {
+ searchFunction.call(panel, searchDocument);
+ } catch(err) {
+ // ignore any exceptions. the query might be malformed, but we allow that.
+ }
+ }
+
+ processChunk();
+
+ chunkIntervalIdentifier = setInterval(processChunk, 25);
+ InjectedScript._currentSearchChunkIntervalIdentifier = chunkIntervalIdentifier;
+ return true;
+}
+
+InjectedScript.searchCanceled = function()
+{
+ if (InjectedScript._searchResults) {
+ const searchResultsProperty = InjectedScript._includedInSearchResultsPropertyName;
+ for (var i = 0; i < this._searchResults.length; ++i) {
+ var node = this._searchResults[i];
+
+ // Remove the searchResultsProperty since there might be an unfinished search.
+ delete node[searchResultsProperty];
+ }
+ }
+
+ if (InjectedScript._currentSearchChunkIntervalIdentifier) {
+ clearInterval(InjectedScript._currentSearchChunkIntervalIdentifier);
+ delete InjectedScript._currentSearchChunkIntervalIdentifier;
+ }
+ InjectedScript._searchResults = [];
+ return true;
+}
+
+InjectedScript.openInInspectedWindow = function(url)
+{
+ // Don't call window.open on wrapper - popup blocker mutes it.
+ // URIs should have no double quotes.
+ InjectedScript._window().eval("window.open(\"" + url + "\")");
+ return true;
+}
+
+InjectedScript.getCallFrames = function()
+{
+ var callFrame = InspectorController.currentCallFrame();
+ if (!callFrame)
+ return false;
+
+ var result = [];
+ var depth = 0;
+ do {
+ result.push(new InjectedScript.CallFrameProxy(depth++, callFrame));
+ callFrame = callFrame.caller;
+ } while (callFrame);
+ return result;
+}
+
+InjectedScript.evaluateInCallFrame = function(callFrameId, code, objectGroup)
+{
+ var callFrame = InjectedScript._callFrameForId(callFrameId);
+ if (!callFrame)
+ return false;
+ return InjectedScript._evaluateAndWrap(callFrame.evaluate, callFrame, code, objectGroup);
+}
+
+InjectedScript._callFrameForId = function(id)
+{
+ var callFrame = InspectorController.currentCallFrame();
+ while (--id >= 0 && callFrame)
+ callFrame = callFrame.caller;
+ return callFrame;
+}
+
+InjectedScript._clearConsoleMessages = function()
+{
+ InspectorController.clearMessages(true);
+}
+
+InjectedScript._inspectObject = function(o)
+{
+ if (arguments.length === 0)
+ return;
+
+ var inspectedWindow = InjectedScript._window();
+ inspectedWindow.console.log(o);
+ if (Object.type(o) === "node") {
+ InspectorController.pushNodePathToFrontend(o, true);
+ } else {
+ switch (Object.describe(o)) {
+ case "Database":
+ InspectorController.selectDatabase(o);
+ break;
+ case "Storage":
+ InspectorController.selectDOMStorage(o);
+ break;
+ }
+ }
+}
+
+InjectedScript._ensureCommandLineAPIInstalled = function(evalFunction, evalObject)
+{
+ if (evalFunction.call(evalObject, "window._inspectorCommandLineAPI"))
+ return;
+ var inspectorCommandLineAPI = evalFunction.call(evalObject, "window._inspectorCommandLineAPI = { \
+ $: function() { return document.getElementById.apply(document, arguments) }, \
+ $$: function() { return document.querySelectorAll.apply(document, arguments) }, \
+ $x: function(xpath, context) { \
+ var nodes = []; \
+ try { \
+ var doc = context || document; \
+ var results = doc.evaluate(xpath, doc, null, XPathResult.ANY_TYPE, null); \
+ var node; \
+ while (node = results.iterateNext()) nodes.push(node); \
+ } catch (e) {} \
+ return nodes; \
+ }, \
+ dir: function() { return console.dir.apply(console, arguments) }, \
+ dirxml: function() { return console.dirxml.apply(console, arguments) }, \
+ keys: function(o) { var a = []; for (var k in o) a.push(k); return a; }, \
+ values: function(o) { var a = []; for (var k in o) a.push(o[k]); return a; }, \
+ profile: function() { return console.profile.apply(console, arguments) }, \
+ profileEnd: function() { return console.profileEnd.apply(console, arguments) }, \
+ _inspectedNodes: [], \
+ get $0() { return _inspectorCommandLineAPI._inspectedNodes[0] }, \
+ get $1() { return _inspectorCommandLineAPI._inspectedNodes[1] }, \
+ get $2() { return _inspectorCommandLineAPI._inspectedNodes[2] }, \
+ get $3() { return _inspectorCommandLineAPI._inspectedNodes[3] }, \
+ get $4() { return _inspectorCommandLineAPI._inspectedNodes[4] } \
+ };");
+
+ inspectorCommandLineAPI.clear = InspectorController.wrapCallback(InjectedScript._clearConsoleMessages);
+ inspectorCommandLineAPI.inspect = InspectorController.wrapCallback(InjectedScript._inspectObject);
+}
+
InjectedScript._resolveObject = function(objectProxy)
{
var object = InjectedScript._objectForId(objectProxy.objectId);
@@ -486,11 +925,11 @@ InjectedScript._resolveObject = function(objectProxy)
var protoDepth = objectProxy.protoDepth;
// Follow the property path.
- for (var i = 0; object && i < path.length; ++i)
+ for (var i = 0; object && path && i < path.length; ++i)
object = object[path[i]];
// Get to the necessary proto layer.
- for (var i = 0; object && i < protoDepth; ++i)
+ for (var i = 0; object && protoDepth && i < protoDepth; ++i)
object = object.__proto__;
return object;
@@ -505,12 +944,251 @@ InjectedScript._window = function()
InjectedScript._nodeForId = function(nodeId)
{
- // TODO: replace with node lookup in the InspectorDOMAgent once DOMAgent nodes are used.
- return nodeId;
+ if (!nodeId)
+ return null;
+ return InspectorController.nodeForId(nodeId);
}
InjectedScript._objectForId = function(objectId)
{
- // TODO: replace with node lookups for node ids and evaluation result lookups for the rest of ids.
+ // There are three types of object ids used:
+ // - numbers point to DOM Node via the InspectorDOMAgent mapping
+ // - strings point to console objects cached in InspectorController for lazy evaluation upon them
+ // - objects contain complex ids and are currently used for scoped objects
+ if (typeof objectId === "number") {
+ return InjectedScript._nodeForId(objectId);
+ } else if (typeof objectId === "string") {
+ return InspectorController.unwrapObject(objectId);
+ } else if (typeof objectId === "object") {
+ var callFrame = InjectedScript._callFrameForId(objectId.callFrame);
+ if (objectId.thisObject)
+ return callFrame.thisObject;
+ else
+ return callFrame.scopeChain[objectId.chainIndex];
+ }
return objectId;
}
+
+InjectedScript.pushNodeToFrontend = function(objectProxy)
+{
+ var object = InjectedScript._resolveObject(objectProxy);
+ if (!object || Object.type(object) !== "node")
+ return false;
+ return InspectorController.pushNodePathToFrontend(object, false);
+}
+
+// Called from within InspectorController on the 'inspected page' side.
+InjectedScript.createProxyObject = function(object, objectId, abbreviate)
+{
+ var result = {};
+ result.objectId = objectId;
+ result.type = Object.type(object);
+
+ var type = typeof object;
+ if ((type === "object" && object !== null) || type === "function") {
+ for (var subPropertyName in object) {
+ result.hasChildren = true;
+ break;
+ }
+ }
+ try {
+ result.description = Object.describe(object, abbreviate);
+ } catch (e) {
+ result.errorText = e.toString();
+ }
+ return result;
+}
+
+InjectedScript.CallFrameProxy = function(id, callFrame)
+{
+ this.id = id;
+ this.type = callFrame.type;
+ this.functionName = (this.type === "function" ? callFrame.functionName : "");
+ this.sourceID = callFrame.sourceID;
+ this.line = callFrame.line;
+ this.scopeChain = this._wrapScopeChain(callFrame);
+}
+
+InjectedScript.CallFrameProxy.prototype = {
+ _wrapScopeChain: function(callFrame)
+ {
+ var foundLocalScope = false;
+ var scopeChain = callFrame.scopeChain;
+ var scopeChainProxy = [];
+ for (var i = 0; i < scopeChain.length; ++i) {
+ var scopeObject = scopeChain[i];
+ var scopeObjectProxy = InjectedScript.createProxyObject(scopeObject, { callFrame: this.id, chainIndex: i }, true);
+
+ if (Object.prototype.toString.call(scopeObject) === "[object JSActivation]") {
+ if (!foundLocalScope)
+ scopeObjectProxy.thisObject = InjectedScript.createProxyObject(callFrame.thisObject, { callFrame: this.id, thisObject: true }, true);
+ else
+ scopeObjectProxy.isClosure = true;
+ foundLocalScope = true;
+ scopeObjectProxy.isLocal = true;
+ } else if (foundLocalScope && scopeObject instanceof InjectedScript._window().Element)
+ scopeObjectProxy.isElement = true;
+ else if (foundLocalScope && scopeObject instanceof InjectedScript._window().Document)
+ scopeObjectProxy.isDocument = true;
+ else if (!foundLocalScope)
+ scopeObjectProxy.isWithBlock = true;
+ scopeObjectProxy.properties = [];
+ try {
+ for (var propertyName in scopeObject)
+ scopeObjectProxy.properties.push(propertyName);
+ } catch (e) {
+ }
+ scopeChainProxy.push(scopeObjectProxy);
+ }
+ return scopeChainProxy;
+ }
+}
+
+InjectedScript.executeSql = function(callId, databaseId, query)
+{
+ function successCallback(tx, result)
+ {
+ var rows = result.rows;
+ var result = [];
+ var length = rows.length;
+ for (var i = 0; i < length; ++i) {
+ var data = {};
+ result.push(data);
+ var row = rows.item(i);
+ for (var columnIdentifier in row) {
+ // FIXME: (Bug 19439) We should specially format SQL NULL here
+ // (which is represented by JavaScript null here, and turned
+ // into the string "null" by the String() function).
+ var text = row[columnIdentifier];
+ data[columnIdentifier] = String(text);
+ }
+ }
+ InspectorController.reportDidDispatchOnInjectedScript(callId, JSON.stringify(result), false);
+ }
+
+ function errorCallback(tx, error)
+ {
+ InspectorController.reportDidDispatchOnInjectedScript(callId, JSON.stringify(error), false);
+ }
+
+ function queryTransaction(tx)
+ {
+ tx.executeSql(query, null, InspectorController.wrapCallback(successCallback), InspectorController.wrapCallback(errorCallback));
+ }
+
+ var database = InspectorController.databaseForId(databaseId);
+ if (!database)
+ errorCallback(null, { code : 2 }); // Return as unexpected version.
+ database.transaction(InspectorController.wrapCallback(queryTransaction), InspectorController.wrapCallback(errorCallback));
+ return true;
+}
+
+Object.type = function(obj)
+{
+ if (obj === null)
+ return "null";
+
+ var type = typeof obj;
+ if (type !== "object" && type !== "function")
+ return type;
+
+ var win = InjectedScript._window();
+
+ if (obj instanceof win.Node)
+ return (obj.nodeType === undefined ? type : "node");
+ if (obj instanceof win.String)
+ return "string";
+ if (obj instanceof win.Array)
+ return "array";
+ if (obj instanceof win.Boolean)
+ return "boolean";
+ if (obj instanceof win.Number)
+ return "number";
+ if (obj instanceof win.Date)
+ return "date";
+ if (obj instanceof win.RegExp)
+ return "regexp";
+ if (obj instanceof win.NodeList)
+ return "array";
+ if (obj instanceof win.Error)
+ return "error";
+ return type;
+}
+
+Object.hasProperties = function(obj)
+{
+ if (typeof obj === "undefined" || typeof obj === "null")
+ return false;
+ for (var name in obj)
+ return true;
+ return false;
+}
+
+Object.describe = function(obj, abbreviated)
+{
+ var type1 = Object.type(obj);
+ var type2 = Object.className(obj);
+
+ switch (type1) {
+ case "object":
+ case "node":
+ return type2;
+ case "array":
+ return "[" + obj.toString() + "]";
+ case "string":
+ if (!abbreviated)
+ return obj;
+ if (obj.length > 100)
+ return "\"" + obj.substring(0, 100) + "\u2026\"";
+ return "\"" + obj + "\"";
+ case "function":
+ var objectText = String(obj);
+ if (!/^function /.test(objectText))
+ objectText = (type2 == "object") ? type1 : type2;
+ else if (abbreviated)
+ objectText = /.*/.exec(obj)[0].replace(/ +$/g, "");
+ return objectText;
+ case "regexp":
+ return String(obj).replace(/([\\\/])/g, "\\$1").replace(/\\(\/[gim]*)$/, "$1").substring(1);
+ default:
+ return String(obj);
+ }
+}
+
+Object.className = function(obj)
+{
+ return Object.prototype.toString.call(obj).replace(/^\[object (.*)\]$/i, "$1")
+}
+
+// Although Function.prototype.bind and String.prototype.escapeCharacters are defined in utilities.js they will soon become
+// unavailable in the InjectedScript context. So we define them here for the local use.
+// TODO: remove this comment once InjectedScript runs in a separate context.
+Function.prototype.bind = function(thisObject)
+{
+ var func = this;
+ var args = Array.prototype.slice.call(arguments, 1);
+ return function() { return func.apply(thisObject, args.concat(Array.prototype.slice.call(arguments, 0))) };
+}
+
+String.prototype.escapeCharacters = function(chars)
+{
+ var foundChar = false;
+ for (var i = 0; i < chars.length; ++i) {
+ if (this.indexOf(chars.charAt(i)) !== -1) {
+ foundChar = true;
+ break;
+ }
+ }
+
+ if (!foundChar)
+ return this;
+
+ var result = "";
+ for (var i = 0; i < this.length; ++i) {
+ if (chars.indexOf(this.charAt(i)) !== -1)
+ result += "\\";
+ result += this.charAt(i);
+ }
+
+ return result;
+}
diff --git a/WebCore/inspector/front-end/InjectedScriptAccess.js b/WebCore/inspector/front-end/InjectedScriptAccess.js
new file mode 100644
index 0000000..c6d4b65
--- /dev/null
+++ b/WebCore/inspector/front-end/InjectedScriptAccess.js
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * 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.
+ */
+
+var InjectedScriptAccess = {};
+
+InjectedScriptAccess._installHandler = function(methodName, async)
+{
+ InjectedScriptAccess[methodName] = function()
+ {
+ var allArgs = Array.prototype.slice.call(arguments);
+ var callback = allArgs[allArgs.length - 1];
+ var argsString = JSON.stringify(Array.prototype.slice.call(allArgs, 0, allArgs.length - 1));
+
+ function myCallback(result, isException)
+ {
+ if (!isException)
+ callback(JSON.parse(result));
+ else
+ WebInspector.console.addMessage(new WebInspector.ConsoleTextMessage("Error dispatching: " + methodName));
+ }
+ var callId = WebInspector.Callback.wrap(myCallback);
+ InspectorController.dispatchOnInjectedScript(callId, methodName, argsString, !!async);
+ };
+}
+
+// InjectedScriptAccess message forwarding puts some constraints on the way methods are imlpemented and called:
+// - Make sure corresponding methods in InjectedScript return non-null and non-undefined values,
+// - Make sure last parameter of all the InjectedSriptAccess.* calls is a callback function.
+// We keep these sorted.
+InjectedScriptAccess._installHandler("addInspectedNode");
+InjectedScriptAccess._installHandler("addStyleSelector");
+InjectedScriptAccess._installHandler("applyStyleRuleText");
+InjectedScriptAccess._installHandler("applyStyleText");
+InjectedScriptAccess._installHandler("evaluate");
+InjectedScriptAccess._installHandler("evaluateInCallFrame");
+InjectedScriptAccess._installHandler("getCompletions");
+InjectedScriptAccess._installHandler("getComputedStyle");
+InjectedScriptAccess._installHandler("getInlineStyle");
+InjectedScriptAccess._installHandler("getProperties");
+InjectedScriptAccess._installHandler("getPrototypes");
+InjectedScriptAccess._installHandler("getStyles");
+InjectedScriptAccess._installHandler("openInInspectedWindow");
+InjectedScriptAccess._installHandler("performSearch");
+InjectedScriptAccess._installHandler("pushNodeToFrontend");
+InjectedScriptAccess._installHandler("searchCanceled");
+InjectedScriptAccess._installHandler("setPropertyValue");
+InjectedScriptAccess._installHandler("setStyleProperty");
+InjectedScriptAccess._installHandler("setStyleText");
+InjectedScriptAccess._installHandler("toggleStyleEnabled");
+
+// Some methods can't run synchronously even on the injected script side (such as DB transactions).
+// Mark them as asynchronous here.
+InjectedScriptAccess._installHandler("executeSql", true);
+
+WebInspector.didDispatchOnInjectedScript = WebInspector.Callback.processCallback;
diff --git a/WebCore/inspector/front-end/MetricsSidebarPane.js b/WebCore/inspector/front-end/MetricsSidebarPane.js
index 8712dcd..a33653b 100644
--- a/WebCore/inspector/front-end/MetricsSidebarPane.js
+++ b/WebCore/inspector/front-end/MetricsSidebarPane.js
@@ -57,14 +57,14 @@ WebInspector.MetricsSidebarPane.prototype = {
var style = WebInspector.CSSStyleDeclaration.parseStyle(stylePayload);
self._update(node, body, style);
};
- InspectorController.getComputedStyle(node, callback);
+ InjectedScriptAccess.getComputedStyle(node.id, callback);
var inlineStyleCallback = function(stylePayload) {
if (!stylePayload)
return;
self._inlineStyleId = stylePayload.id;
};
- InspectorController.getInlineStyle(node, inlineStyleCallback);
+ InjectedScriptAccess.getInlineStyle(node.id, inlineStyleCallback);
},
_update: function(node, body, style)
@@ -208,7 +208,7 @@ WebInspector.MetricsSidebarPane.prototype = {
self.dispatchEventToListeners("metrics edited");
self.update();
};
- InspectorController.setStyleProperty(this._inlineStyleId, context.styleProperty, userInput, callback);
+ InjectedScriptAccess.setStyleProperty(this._inlineStyleId, context.styleProperty, userInput, callback);
}
}
diff --git a/WebCore/inspector/front-end/Object.js b/WebCore/inspector/front-end/Object.js
index 80202b0..74fb56e 100644
--- a/WebCore/inspector/front-end/Object.js
+++ b/WebCore/inspector/front-end/Object.js
@@ -67,10 +67,10 @@ WebInspector.Object.prototype = {
}
var event = {target: this, type: eventType, defaultPrevented: false};
- event.stopPropagation = stopPropagation.bind(event);
- event.preventDefault = preventDefault.bind(event);
+ event.stopPropagation = stopPropagation;
+ event.preventDefault = preventDefault;
- var listeners = this._listeners[eventType];
+ var listeners = this._listeners[eventType].slice(0);
for (var i = 0; i < listeners.length; ++i) {
listeners[i].listener.call(listeners[i].thisObject, event);
if (stoppedPropagation)
diff --git a/WebCore/inspector/front-end/ObjectPropertiesSection.js b/WebCore/inspector/front-end/ObjectPropertiesSection.js
index 9b03940..8bb4e35 100644
--- a/WebCore/inspector/front-end/ObjectPropertiesSection.js
+++ b/WebCore/inspector/front-end/ObjectPropertiesSection.js
@@ -48,73 +48,81 @@ WebInspector.ObjectPropertiesSection.prototype = {
var callback = function(properties) {
if (!properties)
return;
- self._update(properties);
+ self.updateProperties(properties);
};
- InspectorController.getProperties(this.object, this.ignoreHasOwnProperty, callback);
+ InjectedScriptAccess.getProperties(this.object, this.ignoreHasOwnProperty, callback);
},
- _update: function(properties)
+ updateProperties: function(properties, rootTreeElementConstructor, rootPropertyComparer)
{
+ if (!rootTreeElementConstructor)
+ rootTreeElementConstructor = this.treeElementConstructor;
+
+ if (!rootPropertyComparer)
+ rootPropertyComparer = WebInspector.ObjectPropertiesSection.CompareProperties;
+
if (this.extraProperties)
- for (var prop in this.extraProperties)
- properties.push(new WebInspector.ObjectPropertyProxy(prop, this.extraProperties[prop]));
- properties.sort(this._displaySort);
+ for (var i = 0; i < this.extraProperties.length; ++i)
+ properties.push(this.extraProperties[i]);
+
+ properties.sort(rootPropertyComparer);
this.propertiesTreeOutline.removeChildren();
for (var i = 0; i < properties.length; ++i)
- this.propertiesTreeOutline.appendChild(new this.treeElementConstructor(properties[i]));
+ this.propertiesTreeOutline.appendChild(new rootTreeElementConstructor(properties[i]));
if (!this.propertiesTreeOutline.children.length) {
var title = "<div class=\"info\">" + this.emptyPlaceholder + "</div>";
var infoElement = new TreeElement(title, null, false);
this.propertiesTreeOutline.appendChild(infoElement);
}
- },
-
- _displaySort: function(propertyA, propertyB) {
- var a = propertyA.name;
- var b = propertyB.name;
-
- // if used elsewhere make sure to
- // - convert a and b to strings (not needed here, properties are all strings)
- // - check if a == b (not needed here, no two properties can be the same)
-
- var diff = 0;
- var chunk = /^\d+|^\D+/;
- var chunka, chunkb, anum, bnum;
- while (diff === 0) {
- if (!a && b)
- return -1;
- if (!b && a)
- return 1;
- chunka = a.match(chunk)[0];
- chunkb = b.match(chunk)[0];
- anum = !isNaN(chunka);
- bnum = !isNaN(chunkb);
- if (anum && !bnum)
- return -1;
- if (bnum && !anum)
- return 1;
- if (anum && bnum) {
- diff = chunka - chunkb;
- if (diff === 0 && chunka.length !== chunkb.length) {
- if (!+chunka && !+chunkb) // chunks are strings of all 0s (special case)
- return chunka.length - chunkb.length;
- else
- return chunkb.length - chunka.length;
- }
- } else if (chunka !== chunkb)
- return (chunka < chunkb) ? -1 : 1;
- a = a.substring(chunka.length);
- b = b.substring(chunkb.length);
- }
- return diff;
}
}
WebInspector.ObjectPropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;
+WebInspector.ObjectPropertiesSection.CompareProperties = function(propertyA, propertyB)
+{
+ var a = propertyA.name;
+ var b = propertyB.name;
+
+ // if used elsewhere make sure to
+ // - convert a and b to strings (not needed here, properties are all strings)
+ // - check if a == b (not needed here, no two properties can be the same)
+
+ var diff = 0;
+ var chunk = /^\d+|^\D+/;
+ var chunka, chunkb, anum, bnum;
+ while (diff === 0) {
+ if (!a && b)
+ return -1;
+ if (!b && a)
+ return 1;
+ chunka = a.match(chunk)[0];
+ chunkb = b.match(chunk)[0];
+ anum = !isNaN(chunka);
+ bnum = !isNaN(chunkb);
+ if (anum && !bnum)
+ return -1;
+ if (bnum && !anum)
+ return 1;
+ if (anum && bnum) {
+ diff = chunka - chunkb;
+ if (diff === 0 && chunka.length !== chunkb.length) {
+ if (!+chunka && !+chunkb) // chunks are strings of all 0s (special case)
+ return chunka.length - chunkb.length;
+ else
+ return chunkb.length - chunka.length;
+ }
+ } else if (chunka !== chunkb)
+ return (chunka < chunkb) ? -1 : 1;
+ a = a.substring(chunka.length);
+ b = b.substring(chunkb.length);
+ }
+ return diff;
+}
+
WebInspector.ObjectPropertyTreeElement = function(property)
{
this.property = property;
@@ -124,30 +132,22 @@ WebInspector.ObjectPropertyTreeElement = function(property)
}
WebInspector.ObjectPropertyTreeElement.prototype = {
- safePropertyValue: function(object, propertyName)
- {
- if (object["__lookupGetter__"] && object.__lookupGetter__(propertyName))
- return;
- return object[propertyName];
- },
-
onpopulate: function()
{
if (this.children.length && !this.shouldRefreshChildren)
return;
- var self = this;
var callback = function(properties) {
- self.removeChildren();
+ this.removeChildren();
if (!properties)
return;
- properties.sort(self._displaySort);
+ properties.sort(WebInspector.ObjectPropertiesSection.CompareProperties);
for (var i = 0; i < properties.length; ++i) {
- self.appendChild(new self.treeOutline.section.treeElementConstructor(properties[i]));
+ this.appendChild(new this.treeOutline.section.treeElementConstructor(properties[i]));
}
};
- InspectorController.getProperties(this.property.childObjectProxy, false, callback);
+ InjectedScriptAccess.getProperties(this.property.value, false, callback.bind(this));
},
ondblclick: function(element, event)
@@ -162,22 +162,26 @@ WebInspector.ObjectPropertyTreeElement.prototype = {
update: function()
{
- var nameElement = document.createElement("span");
- nameElement.className = "name";
- nameElement.textContent = this.property.name;
-
+ this.nameElement = document.createElement("span");
+ this.nameElement.className = "name";
+ this.nameElement.textContent = this.property.name;
+
+ var separatorElement = document.createElement("span");
+ separatorElement.className = "separator";
+ separatorElement.textContent = ": ";
+
this.valueElement = document.createElement("span");
this.valueElement.className = "value";
- this.valueElement.textContent = this.property.textContent;
+ this.valueElement.textContent = this.property.value.description;
if (this.property.isGetter)
this.valueElement.addStyleClass("dimmed");
this.listItemElement.removeChildren();
- this.listItemElement.appendChild(nameElement);
- this.listItemElement.appendChild(document.createTextNode(": "));
+ this.listItemElement.appendChild(this.nameElement);
+ this.listItemElement.appendChild(separatorElement);
this.listItemElement.appendChild(this.valueElement);
- this.hasChildren = this.property.hasChildren;
+ this.hasChildren = this.property.value.hasChildren;
},
updateSiblings: function()
@@ -247,7 +251,7 @@ WebInspector.ObjectPropertyTreeElement.prototype = {
self.updateSiblings();
}
};
- InspectorController.setPropertyValue(this.property.parentObjectProxy, this.property.name, expression.trimWhitespace(), callback);
+ InjectedScriptAccess.setPropertyValue(this.property.parentObjectProxy, this.property.name, expression.trimWhitespace(), callback);
}
}
diff --git a/WebCore/inspector/front-end/ObjectProxy.js b/WebCore/inspector/front-end/ObjectProxy.js
index fa7816e..bb4afa5 100644
--- a/WebCore/inspector/front-end/ObjectProxy.js
+++ b/WebCore/inspector/front-end/ObjectProxy.js
@@ -28,18 +28,25 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-WebInspector.ObjectProxy = function(objectId, path, protoDepth)
+WebInspector.ObjectProxy = function(objectId, path, protoDepth, description, hasChildren)
{
this.objectId = objectId;
this.path = path || [];
this.protoDepth = protoDepth || 0;
+ this.description = description;
+ this.hasChildren = hasChildren;
}
-WebInspector.ObjectPropertyProxy = function(name, object)
+WebInspector.ObjectProxy.wrapPrimitiveValue = function(value)
+{
+ var proxy = new WebInspector.ObjectProxy();
+ proxy.type = typeof value;
+ proxy.description = value;
+ return proxy;
+}
+
+WebInspector.ObjectPropertyProxy = function(name, value)
{
this.name = name;
- this.type = "object";
- this.hasChildren = true;
- this.textContent = Object.describe(object, true);
- this.childObjectProxy = new WebInspector.ObjectProxy(object);
+ this.value = value;
}
diff --git a/WebCore/inspector/front-end/Panel.js b/WebCore/inspector/front-end/Panel.js
index 3e2212c..5046f6b 100644
--- a/WebCore/inspector/front-end/Panel.js
+++ b/WebCore/inspector/front-end/Panel.js
@@ -66,18 +66,6 @@ WebInspector.Panel.prototype = {
return this._toolbarItem;
},
- createStatusBarButton: function()
- {
- var button = document.createElement("button");
- var glyph = document.createElement("div");
- glyph.className = "glyph";
- button.appendChild(glyph);
- var glyphShadow = document.createElement("div");
- glyphShadow.className = "glyph shadow";
- button.appendChild(glyphShadow);
- return button;
- },
-
show: function()
{
WebInspector.View.prototype.show.call(this);
diff --git a/WebCore/inspector/front-end/Popup.js b/WebCore/inspector/front-end/Popup.js
new file mode 100644
index 0000000..9c8ef24
--- /dev/null
+++ b/WebCore/inspector/front-end/Popup.js
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * This class provides a popup that can be shown relative to an anchor element
+ * or at an arbitrary absolute position.
+ * Points are Objects: {x: xValue, y: yValue}.
+ * Rectangles are Objects: {x: xValue, y: yValue, width: widthValue, height: heightValue}.
+ *
+ * element is an optional unparented visible element (style.display != "none" AND style.visibility != "hidden").
+ * If the element is absent/undefined, it must have been set with the element(x) setter before the show() method invocation.
+ */
+WebInspector.Popup = function(element)
+{
+ if (element)
+ this.element = element;
+ this._keyHandler = this._keyEventHandler.bind(this);
+ this._mouseDownHandler = this._mouseDownEventHandler.bind(this);
+ this._visible = false;
+ this._autoHide = true;
+}
+
+WebInspector.Popup.prototype = {
+ show: function()
+ {
+ if (this.visible)
+ return;
+ var ownerDocument = this._contentElement.ownerDocument;
+ if (!ownerDocument)
+ return;
+
+ this._glasspaneElement = ownerDocument.createElement("div");
+ this._glasspaneElement.className = "popup-glasspane";
+ ownerDocument.body.appendChild(this._glasspaneElement);
+
+ this._contentElement.positionAt(0, 0);
+ this._contentElement.removeStyleClass("hidden");
+ ownerDocument.body.appendChild(this._contentElement);
+
+ this.positionElement();
+ this._visible = true;
+ ownerDocument.addEventListener("keydown", this._keyHandler, false);
+ ownerDocument.addEventListener("mousedown", this._mouseDownHandler, false);
+ },
+
+ hide: function()
+ {
+ if (this.visible) {
+ this._visible = false;
+ this._contentElement.ownerDocument.removeEventListener("keydown", this._keyHandler, false);
+ this._contentElement.ownerDocument.removeEventListener("mousedown", this._mouseDownHandler, false);
+ this._glasspaneElement.parentElement.removeChild(this._glasspaneElement);
+ this._contentElement.parentElement.removeChild(this._contentElement);
+ }
+ },
+
+ get visible()
+ {
+ return this._visible;
+ },
+
+ set element(x)
+ {
+ this._checkNotVisible();
+ this._contentElement = x;
+ this._contentElement.addStyleClass("hidden");
+ },
+
+ get element()
+ {
+ return this._contentElement;
+ },
+
+ positionElement: function()
+ {
+ var element = this._contentElement;
+ var anchorElement = this._anchorElement;
+
+ var targetDocument = element.ownerDocument;
+ var targetDocumentBody = targetDocument.body;
+ var targetDocumentElement = targetDocument.documentElement;
+ var clippingBox = {x: 0, y: 0, width: targetDocumentElement.clientWidth, height: targetDocumentElement.clientHeight};
+ var parentElement = element.offsetParent || element.parentElement;
+
+ var anchorPosition = {x: anchorElement.totalOffsetLeft, y: anchorElement.totalOffsetTop};
+
+ // FIXME(apavlov@chromium.org): Translate anchorPosition to the element.ownerDocument frame when https://bugs.webkit.org/show_bug.cgi?id=28913 is fixed.
+ var anchorBox = {x: anchorPosition.x, y: anchorPosition.y, width: anchorElement.offsetWidth, height: anchorElement.offsetHeight};
+ var elementBox = {x: element.totalOffsetLeft, y: element.totalOffsetTop, width: element.offsetWidth, height: element.offsetHeight};
+ var newElementPosition = {x: 0, y: 0};
+
+ if (anchorBox.y - elementBox.height >= clippingBox.y)
+ newElementPosition.y = anchorBox.y - elementBox.height;
+ else
+ newElementPosition.y = Math.min(anchorBox.y + anchorBox.height, Math.max(clippingBox.y, clippingBox.y + clippingBox.height - elementBox.height));
+
+ if (anchorBox.x + elementBox.height <= clippingBox.x + clippingBox.height)
+ newElementPosition.x = anchorBox.x;
+ else
+ newElementPosition.x = Math.max(clippingBox.x, clippingBox.x + clippingBox.height - elementBox.height);
+ element.positionAt(newElementPosition.x, newElementPosition.y);
+ },
+
+ set anchor(x)
+ {
+ this._checkNotVisible();
+ this._anchorElement = x;
+ },
+
+ get anchor()
+ {
+ return this._anchorElement;
+ },
+
+ set autoHide(x)
+ {
+ this._autoHide = x;
+ },
+
+ _checkNotVisible: function()
+ {
+ if (this.visible)
+ throw new Error("The popup must not be visible.");
+ },
+
+ _keyEventHandler: function(event)
+ {
+ // Escape hides the popup.
+ if (event.keyIdentifier == "U+001B") {
+ this.hide();
+ event.preventDefault();
+ event.handled = true;
+ }
+ },
+
+ _mouseDownEventHandler: function(event)
+ {
+ if (this._autoHide && event.originalTarget === this._glasspaneElement)
+ this.hide();
+ }
+}
diff --git a/WebCore/inspector/front-end/ProfileDataGridTree.js b/WebCore/inspector/front-end/ProfileDataGridTree.js
index 84d9923..3fb0e00 100644
--- a/WebCore/inspector/front-end/ProfileDataGridTree.js
+++ b/WebCore/inspector/front-end/ProfileDataGridTree.js
@@ -50,7 +50,7 @@ WebInspector.ProfileDataGridNode.prototype = {
{
function formatMilliseconds(time)
{
- return Number.secondsToString(time / 1000, WebInspector.UIString.bind(WebInspector), true);
+ return Number.secondsToString(time / 1000, WebInspector.UIString.bind(WebInspector), !Preferences.samplingCPUProfiler);
}
var data = {};
@@ -153,8 +153,11 @@ WebInspector.ProfileDataGridNode.prototype = {
// If the grid node is collapsed, then don't sort children (save operation for later).
// If the grid node has the same sorting as previously, then there is no point in sorting it again.
- if (!force && !gridNode.expanded || gridNode.lastComparator === comparator)
+ if (!force && !gridNode.expanded || gridNode.lastComparator === comparator) {
+ if (gridNode.children.length)
+ gridNode.shouldRefreshChildren = true;
continue;
+ }
gridNode.lastComparator = comparator;
diff --git a/WebCore/inspector/front-end/ProfileView.js b/WebCore/inspector/front-end/ProfileView.js
index 2517bd2..2b8c6ce 100644
--- a/WebCore/inspector/front-end/ProfileView.js
+++ b/WebCore/inspector/front-end/ProfileView.js
@@ -39,6 +39,11 @@ WebInspector.ProfileView = function(profile)
"calls": { title: WebInspector.UIString("Calls"), width: "54px", sortable: true },
"function": { title: WebInspector.UIString("Function"), disclosure: true, sortable: true } };
+ if (Preferences.samplingCPUProfiler) {
+ delete columns.average;
+ delete columns.calls;
+ }
+
this.dataGrid = new WebInspector.DataGrid(columns);
this.dataGrid.addEventListener("sorting changed", this._sortData, this);
this.dataGrid.element.addEventListener("mousedown", this._mouseDownInDataGrid.bind(this), true);
@@ -56,25 +61,19 @@ WebInspector.ProfileView = function(profile)
this.viewSelectElement.appendChild(heavyViewOption);
this.viewSelectElement.appendChild(treeViewOption);
- this.percentButton = document.createElement("button");
- this.percentButton.className = "percent-time-status-bar-item status-bar-item";
+ this.percentButton = new WebInspector.StatusBarButton("", "percent-time-status-bar-item");
this.percentButton.addEventListener("click", this._percentClicked.bind(this), false);
- this.focusButton = document.createElement("button");
- this.focusButton.title = WebInspector.UIString("Focus selected function.");
- this.focusButton.className = "focus-profile-node-status-bar-item status-bar-item";
+ this.focusButton = new WebInspector.StatusBarButton(WebInspector.UIString("Focus selected function."), "focus-profile-node-status-bar-item");
this.focusButton.disabled = true;
this.focusButton.addEventListener("click", this._focusClicked.bind(this), false);
- this.excludeButton = document.createElement("button");
- this.excludeButton.title = WebInspector.UIString("Exclude selected function.");
- this.excludeButton.className = "exclude-profile-node-status-bar-item status-bar-item";
+ this.excludeButton = new WebInspector.StatusBarButton(WebInspector.UIString("Exclude selected function."), "exclude-profile-node-status-bar-item");
this.excludeButton.disabled = true;
this.excludeButton.addEventListener("click", this._excludeClicked.bind(this), false);
- this.resetButton = document.createElement("button");
- this.resetButton.title = WebInspector.UIString("Restore all functions.");
- this.resetButton.className = "reset-profile-status-bar-item status-bar-item hidden";
+ this.resetButton = new WebInspector.StatusBarButton(WebInspector.UIString("Restore all functions."), "reset-profile-status-bar-item");
+ this.resetButton.visible = false;
this.resetButton.addEventListener("click", this._resetClicked.bind(this), false);
this.profile = profile;
@@ -90,7 +89,7 @@ WebInspector.ProfileView = function(profile)
WebInspector.ProfileView.prototype = {
get statusBarItems()
{
- return [this.viewSelectElement, this.percentButton, this.focusButton, this.excludeButton, this.resetButton];
+ return [this.viewSelectElement, this.percentButton.element, this.focusButton.element, this.excludeButton.element, this.resetButton.element];
},
get profile()
@@ -439,10 +438,10 @@ WebInspector.ProfileView.prototype = {
{
if (this.showSelfTimeAsPercent && this.showTotalTimeAsPercent && this.showAverageTimeAsPercent) {
this.percentButton.title = WebInspector.UIString("Show absolute total and self times.");
- this.percentButton.addStyleClass("toggled-on");
+ this.percentButton.toggled = true;
} else {
this.percentButton.title = WebInspector.UIString("Show total and self times as percentages.");
- this.percentButton.removeStyleClass("toggled-on");
+ this.percentButton.toggled = false;
}
},
@@ -451,7 +450,7 @@ WebInspector.ProfileView.prototype = {
if (!this.dataGrid.selectedNode)
return;
- this.resetButton.removeStyleClass("hidden");
+ this.resetButton.visible = true;
this.profileDataGridTree.focus(this.dataGrid.selectedNode);
this.refresh();
this.refreshVisibleData();
@@ -466,7 +465,7 @@ WebInspector.ProfileView.prototype = {
selectedNode.deselect();
- this.resetButton.removeStyleClass("hidden");
+ this.resetButton.visible = true;
this.profileDataGridTree.exclude(selectedNode);
this.refresh();
this.refreshVisibleData();
@@ -474,7 +473,7 @@ WebInspector.ProfileView.prototype = {
_resetClicked: function(event)
{
- this.resetButton.addStyleClass("hidden");
+ this.resetButton.visible = false;
this.profileDataGridTree.restore();
this.refresh();
this.refreshVisibleData();
diff --git a/WebCore/inspector/front-end/ProfilesPanel.js b/WebCore/inspector/front-end/ProfilesPanel.js
index c8b948a..3bd4464 100644
--- a/WebCore/inspector/front-end/ProfilesPanel.js
+++ b/WebCore/inspector/front-end/ProfilesPanel.js
@@ -55,22 +55,32 @@ WebInspector.ProfilesPanel = function()
this.sidebarTree = new TreeOutline(this.sidebarTreeElement);
+ this.profilesListTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("CPU PROFILES"), null, true);
+ this.sidebarTree.appendChild(this.profilesListTreeElement);
+ this.profilesListTreeElement.expand();
+
+ this.snapshotsListTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("HEAP SNAPSHOTS"), null, true);
+ if (Preferences.heapProfilerPresent) {
+ this.sidebarTree.appendChild(this.snapshotsListTreeElement);
+ this.snapshotsListTreeElement.expand();
+ }
+
this.profileViews = document.createElement("div");
this.profileViews.id = "profile-views";
this.element.appendChild(this.profileViews);
- this.enableToggleButton = this.createStatusBarButton();
- this.enableToggleButton.className = "enable-toggle-status-bar-item status-bar-item";
+ this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item");
this.enableToggleButton.addEventListener("click", this._toggleProfiling.bind(this), false);
- this.recordButton = this.createStatusBarButton();
- this.recordButton.title = WebInspector.UIString("Start profiling.");
- this.recordButton.id = "record-profile-status-bar-item";
- this.recordButton.className = "status-bar-item";
+ this.recordButton = new WebInspector.StatusBarButton(WebInspector.UIString("Start profiling."), "record-profile-status-bar-item");
this.recordButton.addEventListener("click", this._recordClicked.bind(this), false);
this.recording = false;
+ this.snapshotButton = new WebInspector.StatusBarButton(WebInspector.UIString("Take heap snapshot."), "heap-snapshot-status-bar-item");
+ this.snapshotButton.visible = Preferences.heapProfilerPresent;
+ this.snapshotButton.addEventListener("click", this._snapshotClicked.bind(this), false);
+
this.profileViewStatusBarItemsContainer = document.createElement("div");
this.profileViewStatusBarItemsContainer.id = "profile-view-status-bar-items";
@@ -87,7 +97,7 @@ WebInspector.ProfilesPanel.prototype = {
get statusBarItems()
{
- return [this.enableToggleButton, this.recordButton, this.profileViewStatusBarItemsContainer];
+ return [this.enableToggleButton.element, this.recordButton.element, this.snapshotButton.element, this.profileViewStatusBarItemsContainer];
},
show: function()
@@ -137,7 +147,8 @@ WebInspector.ProfilesPanel.prototype = {
this.sidebarTreeElement.removeStyleClass("some-expandable");
- this.sidebarTree.removeChildren();
+ this.profilesListTreeElement.removeChildren();
+ this.snapshotsListTreeElement.removeChildren();
this.profileViews.removeChildren();
this.profileViewStatusBarItemsContainer.removeChildren();
@@ -155,7 +166,7 @@ WebInspector.ProfilesPanel.prototype = {
this._profiles.push(profile);
this._profilesIdMap[profile.uid] = profile;
- var sidebarParent = this.sidebarTree;
+ var sidebarParent = this.profilesListTreeElement;
var small = false;
var alternateTitle;
@@ -317,10 +328,10 @@ WebInspector.ProfilesPanel.prototype = {
this.recording = isProfiling;
if (isProfiling) {
- this.recordButton.addStyleClass("toggled-on");
+ this.recordButton.toggled = true;
this.recordButton.title = WebInspector.UIString("Stop profiling.");
} else {
- this.recordButton.removeStyleClass("toggled-on");
+ this.recordButton.toggled = false;
this.recordButton.title = WebInspector.UIString("Start profiling.");
}
},
@@ -336,14 +347,17 @@ WebInspector.ProfilesPanel.prototype = {
{
if (InspectorController.profilerEnabled()) {
this.enableToggleButton.title = WebInspector.UIString("Profiling enabled. Click to disable.");
- this.enableToggleButton.addStyleClass("toggled-on");
- this.recordButton.removeStyleClass("hidden");
+ this.enableToggleButton.toggled = true;
+ this.recordButton.visible = true;
+ if (Preferences.heapProfilerPresent)
+ this.snapshotButton.visible = true;
this.profileViewStatusBarItemsContainer.removeStyleClass("hidden");
this.panelEnablerView.visible = false;
} else {
this.enableToggleButton.title = WebInspector.UIString("Profiling disabled. Click to enable.");
- this.enableToggleButton.removeStyleClass("toggled-on");
- this.recordButton.addStyleClass("hidden");
+ this.enableToggleButton.toggled = false;
+ this.recordButton.visible = false;
+ this.snapshotButton.visible = false;
this.profileViewStatusBarItemsContainer.addStyleClass("hidden");
this.panelEnablerView.visible = true;
}
@@ -359,6 +373,11 @@ WebInspector.ProfilesPanel.prototype = {
InspectorController.stopProfiling();
},
+ _snapshotClicked: function()
+ {
+ InspectorController.takeHeapSnapshot();
+ },
+
_enableProfiling: function()
{
if (InspectorController.profilerEnabled())
@@ -376,7 +395,10 @@ WebInspector.ProfilesPanel.prototype = {
_populateProfiles: function()
{
- if (this.sidebarTree.children.length)
+ // FIXME: This code needs to be adjusted when more profiling types are added.
+ // Currently defaults to CPU profiles.
+ var cpuProfiles = this.sidebarTree.children[0];
+ if (cpuProfiles.children.length)
return;
var profiles = InspectorController.profiles();
@@ -386,8 +408,8 @@ WebInspector.ProfilesPanel.prototype = {
this.addProfile(profile);
}
- if (this.sidebarTree.children[0])
- this.sidebarTree.children[0].select();
+ if (cpuProfiles.children[0])
+ cpuProfiles.children[0].select();
delete this._shouldPopulateProfiles;
},
diff --git a/WebCore/inspector/front-end/PropertiesSidebarPane.js b/WebCore/inspector/front-end/PropertiesSidebarPane.js
index 2d32137..ec08210 100644
--- a/WebCore/inspector/front-end/PropertiesSidebarPane.js
+++ b/WebCore/inspector/front-end/PropertiesSidebarPane.js
@@ -32,7 +32,7 @@ WebInspector.PropertiesSidebarPane = function()
}
WebInspector.PropertiesSidebarPane.prototype = {
- update: function(object)
+ update: function(node)
{
var body = this.bodyElement;
@@ -40,7 +40,7 @@ WebInspector.PropertiesSidebarPane.prototype = {
this.sections = [];
- if (!object)
+ if (!node)
return;
var self = this;
@@ -51,13 +51,13 @@ WebInspector.PropertiesSidebarPane.prototype = {
// Get array of prototype user-friendly names.
for (var i = 0; i < prototypes.length; ++i) {
- var prototype = new WebInspector.ObjectProxy(object, [], i);
+ var prototype = new WebInspector.ObjectProxy(node.id, [], i);
var section = new WebInspector.ObjectPropertiesSection(prototype, prototypes[i], WebInspector.UIString("Prototype"));
self.sections.push(section);
body.appendChild(section.element);
}
};
- InspectorController.getPrototypes(object, callback);
+ InjectedScriptAccess.getPrototypes(node.id, callback);
}
}
diff --git a/WebCore/inspector/front-end/Resource.js b/WebCore/inspector/front-end/Resource.js
index bcb7b2a..56696e3 100644
--- a/WebCore/inspector/front-end/Resource.js
+++ b/WebCore/inspector/front-end/Resource.js
@@ -26,7 +26,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-WebInspector.Resource = function(requestHeaders, url, domain, path, lastPathComponent, identifier, mainResource, cached)
+WebInspector.Resource = function(requestHeaders, url, domain, path, lastPathComponent, identifier, mainResource, cached, requestMethod, requestFormData)
{
this.identifier = identifier;
@@ -39,10 +39,70 @@ WebInspector.Resource = function(requestHeaders, url, domain, path, lastPathComp
this.path = path;
this.lastPathComponent = lastPathComponent;
this.cached = cached;
+ this.requestMethod = requestMethod || "";
+ this.requestFormData = requestFormData || "";
this.category = WebInspector.resourceCategories.other;
}
+
+WebInspector.Resource.StatusText = {
+ 100: "Continue",
+ 101: "Switching Protocols",
+ 102: "Processing (WebDav)",
+ 200: "OK",
+ 201: "Created",
+ 202: "Accepted",
+ 203: "Non-Authoritative Information",
+ 204: "No Content",
+ 205: "Reset Content",
+ 206: "Partial Content",
+ 207: "Multi-Status (WebDav)",
+ 300: "Multiple Choices",
+ 301: "Moved Permanently",
+ 302: "Found",
+ 303: "See Other",
+ 304: "Not Modified",
+ 305: "Use Proxy",
+ 306: "Switch Proxy",
+ 307: "Temporary",
+ 400: "Bad Request",
+ 401: "Unauthorized",
+ 402: "Payment Required",
+ 403: "Forbidden",
+ 404: "Not Found",
+ 405: "Method Not Allowed",
+ 406: "Not Acceptable",
+ 407: "Proxy Authentication Required",
+ 408: "Request Timeout",
+ 409: "Conflict",
+ 410: "Gone",
+ 411: "Length Required",
+ 412: "Precondition Failed",
+ 413: "Request Entity Too Large",
+ 414: "Request-URI Too Long",
+ 415: "Unsupported Media Type",
+ 416: "Requested Range Not Satisfiable",
+ 417: "Expectation Failed",
+ 418: "I'm a teapot",
+ 422: "Unprocessable Entity (WebDav)",
+ 423: "Locked (WebDav)",
+ 424: "Failed Dependency (WebDav)",
+ 425: "Unordered Collection",
+ 426: "Upgrade Required",
+ 449: "Retry With",
+ 500: "Internal Server Error",
+ 501: "Not Implemented",
+ 502: "Bad Gateway",
+ 503: "Service Unavailable",
+ 504: "Gateway Timeout",
+ 505: "HTTP Version Not Supported",
+ 506: "Variant Also Negotiates",
+ 507: "Insufficient Storage (WebDav)",
+ 509: "Bandwidth Limit Exceeded",
+ 510: "Not Extended"
+};
+
// Keep these in sync with WebCore::InspectorResource::Type
WebInspector.Resource.Type = {
Document: 0,
@@ -538,7 +598,6 @@ WebInspector.Resource.prototype = {
_checkWarning: function(warning)
{
- var addWarning = false;
var msg;
switch (warning.id) {
case WebInspector.Warnings.IncorrectMIMEType.id:
@@ -619,3 +678,8 @@ WebInspector.Resource.CompareBySize = function(a, b)
return 1;
return 0;
}
+
+WebInspector.Resource.StatusTextForCode = function(code)
+{
+ return code ? code + " " + WebInspector.Resource.StatusText[code] : "";
+}
diff --git a/WebCore/inspector/front-end/ResourceView.js b/WebCore/inspector/front-end/ResourceView.js
index b480362..28586f6 100644
--- a/WebCore/inspector/front-end/ResourceView.js
+++ b/WebCore/inspector/front-end/ResourceView.js
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) IBM Corp. 2009 All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -53,11 +54,37 @@ WebInspector.ResourceView = function(resource)
this.urlTreeElement.selectable = false;
this.headersTreeOutline.appendChild(this.urlTreeElement);
+ this.httpInformationTreeElement = new TreeElement("", null, true);
+ this.httpInformationTreeElement.expanded = false;
+ this.httpInformationTreeElement.selectable = false;
+ this.headersTreeOutline.appendChild(this.httpInformationTreeElement);
+
this.requestHeadersTreeElement = new TreeElement("", null, true);
this.requestHeadersTreeElement.expanded = false;
this.requestHeadersTreeElement.selectable = false;
this.headersTreeOutline.appendChild(this.requestHeadersTreeElement);
+ this._decodeHover = WebInspector.UIString("Double-Click to toggle between URL encoded and decoded formats");
+ this._decodeRequestParameters = true;
+
+ this.queryStringTreeElement = new TreeElement("", null, true);
+ this.queryStringTreeElement.expanded = false;
+ this.queryStringTreeElement.selectable = false;
+ this.queryStringTreeElement.hidden = true;
+ this.headersTreeOutline.appendChild(this.queryStringTreeElement);
+
+ this.formDataTreeElement = new TreeElement("", null, true);
+ this.formDataTreeElement.expanded = false;
+ this.formDataTreeElement.selectable = false;
+ this.formDataTreeElement.hidden = true;
+ this.headersTreeOutline.appendChild(this.formDataTreeElement);
+
+ this.requestPayloadTreeElement = new TreeElement(WebInspector.UIString("Request Payload"), null, true);
+ this.requestPayloadTreeElement.expanded = false;
+ this.requestPayloadTreeElement.selectable = false;
+ this.requestPayloadTreeElement.hidden = true;
+ this.headersTreeOutline.appendChild(this.requestPayloadTreeElement);
+
this.responseHeadersTreeElement = new TreeElement("", null, true);
this.responseHeadersTreeElement.expanded = false;
this.responseHeadersTreeElement.selectable = false;
@@ -68,10 +95,12 @@ WebInspector.ResourceView = function(resource)
resource.addEventListener("url changed", this._refreshURL, this);
resource.addEventListener("requestHeaders changed", this._refreshRequestHeaders, this);
resource.addEventListener("responseHeaders changed", this._refreshResponseHeaders, this);
+ resource.addEventListener("finished", this._refreshHTTPInformation, this);
this._refreshURL();
this._refreshRequestHeaders();
this._refreshResponseHeaders();
+ this._refreshHTTPInformation();
}
WebInspector.ResourceView.prototype = {
@@ -104,12 +133,141 @@ WebInspector.ResourceView.prototype = {
_refreshURL: function()
{
- this.urlTreeElement.title = this.resource.url.escapeHTML();
+ var url = this.resource.url;
+ var statusCodeImage = "";
+ if (this.resource.statusCode) {
+ var statusImageSource = "";
+
+ if (this.resource.statusCode < 300)
+ statusImageSource = "Images/successGreenDot.png";
+ else if (this.resource.statusCode < 400)
+ statusImageSource = "Images/warningOrangeDot.png";
+ else
+ statusImageSource = "Images/errorRedDot.png";
+
+ statusCodeImage = "<img class=\"resource-status-image\" src=\"" + statusImageSource + "\" title=\"" + WebInspector.Resource.StatusTextForCode(this.resource.statusCode) + "\">";
+ }
+
+ this.urlTreeElement.title = statusCodeImage + "<span class=\"resource-url\">" + url.escapeHTML() + "</span>";
+ this._refreshQueryString();
+ },
+
+ _refreshQueryString: function()
+ {
+ var url = this.resource.url;
+ var hasQueryString = url.indexOf("?") >= 0;
+
+ if (!hasQueryString) {
+ this.queryStringTreeElement.hidden = true;
+ return;
+ }
+
+ this.queryStringTreeElement.hidden = false;
+ var parmString = url.split("?", 2)[1];
+ this._refreshParms(WebInspector.UIString("Query String Parameters"), parmString, this.queryStringTreeElement);
+ },
+
+ _refreshFormData: function()
+ {
+ this.formDataTreeElement.hidden = true;
+ this.requestPayloadTreeElement.hidden = true;
+
+ var isFormData = this.resource.requestFormData;
+ if (!isFormData)
+ return;
+
+ var isFormEncoded = false;
+ var requestContentType = this._getHeaderValue(this.resource.requestHeaders, "Content-Type");
+ if (requestContentType.match(/^application\/x-www-form-urlencoded\s*(;.*)?$/i))
+ isFormEncoded = true;
+
+ if (isFormEncoded) {
+ this.formDataTreeElement.hidden = false;
+ this._refreshParms(WebInspector.UIString("Form Data"), this.resource.requestFormData, this.formDataTreeElement);
+ } else {
+ this.requestPayloadTreeElement.hidden = false;
+ this._refreshRequestPayload(this.resource.requestFormData);
+ }
+ },
+
+ _refreshRequestPayload: function(formData)
+ {
+ this.requestPayloadTreeElement.removeChildren();
+
+ var title = "<div class=\"header-name\">&nbsp;</div>";
+ title += "<div class=\"raw-form-data header-value\">" + formData.escapeHTML() + "</div>";
+ var parmTreeElement = new TreeElement(title, null, false);
+ parmTreeElement.selectable = false;
+ this.requestPayloadTreeElement.appendChild(parmTreeElement);
+ },
+
+ _refreshParms: function(title, parmString, parmsTreeElement)
+ {
+ var parms = parmString.split("&");
+ for (var i = 0; i < parms.length; ++i) {
+ var parm = parms[i];
+ parm = parm.split("=", 2);
+ if (parm.length == 1)
+ parm.push("");
+ parms[i] = parm;
+ }
+
+ parmsTreeElement.removeChildren();
+
+ parmsTreeElement.title = title + "<span class=\"header-count\">" + WebInspector.UIString(" (%d)", parms.length) + "</span>";
+
+ for (var i = 0; i < parms.length; ++i) {
+ var key = parms[i][0];
+ var value = parms[i][1];
+
+ var errorDecoding = false;
+ if (this._decodeRequestParameters) {
+ if (value.indexOf("%") >= 0) {
+ try {
+ value = decodeURIComponent(value);
+ } catch(e) {
+ errorDecoding = true;
+ }
+ }
+
+ value = value.replace(/\+/g, " ");
+ }
+
+ valueEscaped = value.escapeHTML();
+ if (errorDecoding)
+ valueEscaped += " <span class=\"error-message\">" + WebInspector.UIString("(unable to decode value)").escapeHTML() + "</span>";
+
+ var title = "<div class=\"header-name\">" + key.escapeHTML() + ":</div>";
+ title += "<div class=\"header-value\">" + valueEscaped + "</div>";
+
+ var parmTreeElement = new TreeElement(title, null, false);
+ parmTreeElement.selectable = false;
+ parmTreeElement.tooltip = this._decodeHover;
+ parmTreeElement.ondblclick = this._toggleURLdecoding.bind(this);
+ parmsTreeElement.appendChild(parmTreeElement);
+ }
+ },
+
+ _toggleURLdecoding: function(treeElement, event)
+ {
+ this._decodeRequestParameters = !this._decodeRequestParameters;
+ this._refreshQueryString();
+ this._refreshFormData();
+ },
+
+ _getHeaderValue: function(headers, key)
+ {
+ var lowerKey = key.toLowerCase();
+ for (var testKey in headers) {
+ if (testKey.toLowerCase() === lowerKey)
+ return headers[testKey];
+ }
},
_refreshRequestHeaders: function()
{
this._refreshHeaders(WebInspector.UIString("Request Headers"), this.resource.sortedRequestHeaders, this.requestHeadersTreeElement);
+ this._refreshFormData();
},
_refreshResponseHeaders: function()
@@ -117,6 +275,33 @@ WebInspector.ResourceView.prototype = {
this._refreshHeaders(WebInspector.UIString("Response Headers"), this.resource.sortedResponseHeaders, this.responseHeadersTreeElement);
},
+ _refreshHTTPInformation: function()
+ {
+ const listElements = 2;
+
+ var headerElement = this.httpInformationTreeElement;
+ headerElement.removeChildren();
+ headerElement.hidden = !this.resource.statusCode;
+
+ if (this.resource.statusCode) {
+ headerElement.title = WebInspector.UIString("HTTP Information") + "<span class=\"header-count\">" + WebInspector.UIString(" (%d)", listElements) + "</span>";
+
+ var title = "<div class=\"header-name\">" + WebInspector.UIString("Request Method") + ":</div>";
+ title += "<div class=\"header-value\">" + this.resource.requestMethod + "</div>"
+
+ var headerTreeElement = new TreeElement(title, null, false);
+ headerTreeElement.selectable = false;
+ headerElement.appendChild(headerTreeElement);
+
+ title = "<div class=\"header-name\">" + WebInspector.UIString("Status Code") + ":</div>";
+ title += "<div class=\"header-value\">" + WebInspector.Resource.StatusTextForCode(this.resource.statusCode) + "</div>"
+
+ headerTreeElement = new TreeElement(title, null, false);
+ headerTreeElement.selectable = false;
+ headerElement.appendChild(headerTreeElement);
+ }
+ },
+
_refreshHeaders: function(title, headers, headersTreeElement)
{
headersTreeElement.removeChildren();
diff --git a/WebCore/inspector/front-end/ResourcesPanel.js b/WebCore/inspector/front-end/ResourcesPanel.js
index fb43551..b575fc3 100644
--- a/WebCore/inspector/front-end/ResourcesPanel.js
+++ b/WebCore/inspector/front-end/ResourcesPanel.js
@@ -60,9 +60,9 @@ WebInspector.ResourcesPanel = function()
this.containerContentElement.id = "resources-container-content";
this.containerElement.appendChild(this.containerContentElement);
- this.summaryElement = document.createElement("div");
- this.summaryElement.id = "resources-summary";
- this.containerContentElement.appendChild(this.summaryElement);
+ this.summaryBar = new WebInspector.SummaryBar(this.categories);
+ this.summaryBar.element.id = "resources-summary";
+ this.containerContentElement.appendChild(this.summaryBar.element);
this.resourcesGraphsElement = document.createElement("div");
this.resourcesGraphsElement.id = "resources-graphs";
@@ -76,16 +76,6 @@ WebInspector.ResourcesPanel = function()
this.dividersLabelBarElement.id = "resources-dividers-label-bar";
this.containerContentElement.appendChild(this.dividersLabelBarElement);
- this.summaryGraphElement = document.createElement("canvas");
- this.summaryGraphElement.setAttribute("width", "450");
- this.summaryGraphElement.setAttribute("height", "38");
- this.summaryGraphElement.id = "resources-summary-graph";
- this.summaryElement.appendChild(this.summaryGraphElement);
-
- this.legendElement = document.createElement("div");
- this.legendElement.id = "resources-graph-legend";
- this.summaryElement.appendChild(this.legendElement);
-
this.sidebarTreeElement = document.createElement("ol");
this.sidebarTreeElement.className = "sidebar-tree";
this.sidebarElement.appendChild(this.sidebarTreeElement);
@@ -139,15 +129,16 @@ WebInspector.ResourcesPanel = function()
this.element.appendChild(this.panelEnablerView.element);
- this.enableToggleButton = this.createStatusBarButton();
- this.enableToggleButton.className = "enable-toggle-status-bar-item status-bar-item";
+ this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item");
this.enableToggleButton.addEventListener("click", this._toggleResourceTracking.bind(this), false);
- this.largerResourcesButton = this.createStatusBarButton();
- this.largerResourcesButton.id = "resources-larger-resources-status-bar-item";
- this.largerResourcesButton.className = "status-bar-item toggled-on";
- this.largerResourcesButton.title = WebInspector.UIString("Use small resource rows.");
+ this.largerResourcesButton = new WebInspector.StatusBarButton(WebInspector.UIString("Use small resource rows."), "resources-larger-resources-status-bar-item");
+ this.largerResourcesButton.toggled = Preferences.resourcesLargeRows;
this.largerResourcesButton.addEventListener("click", this._toggleLargerResources.bind(this), false);
+ if (!Preferences.resourcesLargeRows) {
+ Preferences.resourcesLargeRows = !Preferences.resourcesLargeRows;
+ this._toggleLargerResources(); // this will toggle the preference back to the original
+ }
this.sortingSelectElement = document.createElement("select");
this.sortingSelectElement.className = "status-bar-item";
@@ -168,8 +159,8 @@ WebInspector.ResourcesPanel = function()
var allElement = createFilterElement.call(this, "all");
this.filter(allElement.category);
- for (var i = 0; i < this.categoryOrder.length; i++)
- createFilterElement.call(this, this.categoryOrder[i]);
+ for (var category in this.categories)
+ createFilterElement.call(this, category);
this.reset();
@@ -179,7 +170,16 @@ WebInspector.ResourcesPanel = function()
WebInspector.ResourcesPanel.prototype = {
toolbarItemClass: "resources",
- categoryOrder: ["documents", "stylesheets", "images", "scripts", "xhr", "fonts", "other"],
+ get categories()
+ {
+ if (!this._categories) {
+ this._categories = {documents: {color: {r: 47, g: 102, b: 236}}, stylesheets: {color: {r: 157, g: 231, b: 119}}, images: {color: {r: 164, g: 60, b: 255}}, scripts: {color: {r: 255, g: 121, b: 0}}, xhr: {color: {r: 231, g: 231, b: 10}}, fonts: {color: {r: 255, g: 82, b: 62}}, other: {color: {r: 186, g: 186, b: 186}}};
+ for (var category in this._categories) {
+ this._categories[category].title = WebInspector.resourceCategories[category].title;
+ }
+ }
+ return this._categories;
+ },
filter: function (category) {
if (this._filterCategory && this._filterCategory === category)
@@ -208,10 +208,41 @@ WebInspector.ResourcesPanel.prototype = {
{
return WebInspector.UIString("Resources");
},
+
+ get mainResourceLoadTime()
+ {
+ return this._mainResourceLoadTime || -1;
+ },
+
+ set mainResourceLoadTime(x)
+ {
+ if (this._mainResourceLoadTime === x)
+ return;
+
+ this._mainResourceLoadTime = x;
+
+ // Update the dividers to draw the new line
+ this._updateGraphDividersIfNeeded(true);
+ },
+
+ get mainResourceDOMContentTime()
+ {
+ return this._mainResourceDOMContentTime || -1;
+ },
+
+ set mainResourceDOMContentTime(x)
+ {
+ if (this._mainResourceDOMContentTime === x)
+ return;
+
+ this._mainResourceDOMContentTime = x;
+
+ this._updateGraphDividersIfNeeded(true);
+ },
get statusBarItems()
{
- return [this.enableToggleButton, this.largerResourcesButton, this.sortingSelectElement];
+ return [this.enableToggleButton.element, this.largerResourcesButton.element, this.sortingSelectElement];
},
show: function()
@@ -455,26 +486,27 @@ WebInspector.ResourcesPanel.prototype = {
this._resources = [];
this._staleResources = [];
+
+ this.mainResourceLoadTime = -1;
+ this.mainResourceDOMContentTime = -1;
this.resourcesTreeElement.removeChildren();
this.viewsContainerElement.removeChildren();
this.resourcesGraphsElement.removeChildren();
- this.legendElement.removeChildren();
+ this.summaryBar.reset();
this._updateGraphDividersIfNeeded(true);
- this._drawSummaryGraph(); // draws an empty graph
-
if (InspectorController.resourceTrackingEnabled()) {
this.enableToggleButton.title = WebInspector.UIString("Resource tracking enabled. Click to disable.");
- this.enableToggleButton.addStyleClass("toggled-on");
- this.largerResourcesButton.removeStyleClass("hidden");
+ this.enableToggleButton.toggled = true;
+ this.largerResourcesButton.visible = true;
this.sortingSelectElement.removeStyleClass("hidden");
this.panelEnablerView.visible = false;
} else {
this.enableToggleButton.title = WebInspector.UIString("Resource tracking disabled. Click to enable.");
- this.enableToggleButton.removeStyleClass("toggled-on");
- this.largerResourcesButton.addStyleClass("hidden");
+ this.enableToggleButton.toggled = false;
+ this.largerResourcesButton.visible = false;
this.sortingSelectElement.addStyleClass("hidden");
this.panelEnablerView.visible = true;
}
@@ -665,40 +697,6 @@ WebInspector.ResourcesPanel.prototype = {
this.sidebarTree.handleKeyEvent(event);
},
- _makeLegendElement: function(label, value, color)
- {
- var legendElement = document.createElement("label");
- legendElement.className = "resources-graph-legend-item";
-
- if (color) {
- var swatch = document.createElement("canvas");
- swatch.className = "resources-graph-legend-swatch";
- swatch.setAttribute("width", "13");
- swatch.setAttribute("height", "24");
-
- legendElement.appendChild(swatch);
-
- this._drawSwatch(swatch, color);
- }
-
- var labelElement = document.createElement("div");
- labelElement.className = "resources-graph-legend-label";
- legendElement.appendChild(labelElement);
-
- var headerElement = document.createElement("div");
- var headerElement = document.createElement("div");
- headerElement.className = "resources-graph-legend-header";
- headerElement.textContent = label;
- labelElement.appendChild(headerElement);
-
- var valueElement = document.createElement("div");
- valueElement.className = "resources-graph-legend-value";
- valueElement.textContent = value;
- labelElement.appendChild(valueElement);
-
- return legendElement;
- },
-
_sortResourcesIfNeeded: function()
{
var sortedElements = [].concat(this.resourcesTreeElement.children);
@@ -761,283 +759,42 @@ WebInspector.ResourcesPanel.prototype = {
this.dividersLabelBarElement.appendChild(divider);
}
- },
-
- _fadeOutRect: function(ctx, x, y, w, h, a1, a2)
- {
- ctx.save();
-
- var gradient = ctx.createLinearGradient(x, y, x, y + h);
- gradient.addColorStop(0.0, "rgba(0, 0, 0, " + (1.0 - a1) + ")");
- gradient.addColorStop(0.8, "rgba(0, 0, 0, " + (1.0 - a2) + ")");
- gradient.addColorStop(1.0, "rgba(0, 0, 0, 1.0)");
-
- ctx.globalCompositeOperation = "destination-out";
-
- ctx.fillStyle = gradient;
- ctx.fillRect(x, y, w, h);
-
- ctx.restore();
- },
-
- _drawSwatch: function(canvas, color)
- {
- var ctx = canvas.getContext("2d");
-
- function drawSwatchSquare() {
- ctx.fillStyle = color;
- ctx.fillRect(0, 0, 13, 13);
- var gradient = ctx.createLinearGradient(0, 0, 13, 13);
- gradient.addColorStop(0.0, "rgba(255, 255, 255, 0.2)");
- gradient.addColorStop(1.0, "rgba(255, 255, 255, 0.0)");
-
- ctx.fillStyle = gradient;
- ctx.fillRect(0, 0, 13, 13);
-
- gradient = ctx.createLinearGradient(13, 13, 0, 0);
- gradient.addColorStop(0.0, "rgba(0, 0, 0, 0.2)");
- gradient.addColorStop(1.0, "rgba(0, 0, 0, 0.0)");
-
- ctx.fillStyle = gradient;
- ctx.fillRect(0, 0, 13, 13);
-
- ctx.strokeStyle = "rgba(0, 0, 0, 0.6)";
- ctx.strokeRect(0.5, 0.5, 12, 12);
- }
-
- ctx.clearRect(0, 0, 13, 24);
-
- drawSwatchSquare();
-
- ctx.save();
-
- ctx.translate(0, 25);
- ctx.scale(1, -1);
-
- drawSwatchSquare();
-
- ctx.restore();
-
- this._fadeOutRect(ctx, 0, 13, 13, 13, 0.5, 0.0);
- },
-
- _drawSummaryGraph: function(segments)
- {
- if (!this.summaryGraphElement)
+ if (this.calculator.startAtZero) {
+ // If our current sorting method starts at zero, that means it shows all
+ // resources starting at the same point, and so onLoad event and DOMContent
+ // event lines really wouldn't make much sense here, so don't render them.
return;
-
- if (!segments || !segments.length) {
- segments = [{color: "white", value: 1}];
- this._showingEmptySummaryGraph = true;
- } else
- delete this._showingEmptySummaryGraph;
-
- // Calculate the total of all segments.
- var total = 0;
- for (var i = 0; i < segments.length; ++i)
- total += segments[i].value;
-
- // Calculate the percentage of each segment, rounded to the nearest percent.
- var percents = segments.map(function(s) { return Math.max(Math.round(100 * s.value / total), 1) });
-
- // Calculate the total percentage.
- var percentTotal = 0;
- for (var i = 0; i < percents.length; ++i)
- percentTotal += percents[i];
-
- // Make sure our percentage total is not greater-than 100, it can be greater
- // if we rounded up for a few segments.
- while (percentTotal > 100) {
- for (var i = 0; i < percents.length && percentTotal > 100; ++i) {
- if (percents[i] > 1) {
- --percents[i];
- --percentTotal;
- }
- }
}
- // Make sure our percentage total is not less-than 100, it can be less
- // if we rounded down for a few segments.
- while (percentTotal < 100) {
- for (var i = 0; i < percents.length && percentTotal < 100; ++i) {
- ++percents[i];
- ++percentTotal;
- }
+ if (this.mainResourceLoadTime !== -1) {
+ var percent = this.calculator.computePercentageFromEventTime(this.mainResourceLoadTime);
+ var loadDivider = document.createElement("div");
+ loadDivider.className = "resources-onload-divider";
+ loadDivider.style.left = percent + "%";
+ loadDivider.title = WebInspector.UIString("Load event fired");
+ this.dividersElement.appendChild(loadDivider);
}
-
- var ctx = this.summaryGraphElement.getContext("2d");
-
- var x = 0;
- var y = 0;
- var w = 450;
- var h = 19;
- var r = (h / 2);
-
- function drawPillShadow()
- {
- // This draws a line with a shadow that is offset away from the line. The line is stroked
- // twice with different X shadow offsets to give more feathered edges. Later we erase the
- // line with destination-out 100% transparent black, leaving only the shadow. This only
- // works if nothing has been drawn into the canvas yet.
-
- ctx.beginPath();
- ctx.moveTo(x + 4, y + h - 3 - 0.5);
- ctx.lineTo(x + w - 4, y + h - 3 - 0.5);
- ctx.closePath();
-
- ctx.save();
-
- ctx.shadowBlur = 2;
- ctx.shadowColor = "rgba(0, 0, 0, 0.5)";
- ctx.shadowOffsetX = 3;
- ctx.shadowOffsetY = 5;
-
- ctx.strokeStyle = "white";
- ctx.lineWidth = 1;
-
- ctx.stroke();
-
- ctx.shadowOffsetX = -3;
-
- ctx.stroke();
-
- ctx.restore();
-
- ctx.save();
-
- ctx.globalCompositeOperation = "destination-out";
- ctx.strokeStyle = "rgba(0, 0, 0, 1)";
- ctx.lineWidth = 1;
-
- ctx.stroke();
-
- ctx.restore();
- }
-
- function drawPill()
- {
- // Make a rounded rect path.
- ctx.beginPath();
- ctx.moveTo(x, y + r);
- ctx.lineTo(x, y + h - r);
- ctx.quadraticCurveTo(x, y + h, x + r, y + h);
- ctx.lineTo(x + w - r, y + h);
- ctx.quadraticCurveTo(x + w, y + h, x + w, y + h - r);
- ctx.lineTo(x + w, y + r);
- ctx.quadraticCurveTo(x + w, y, x + w - r, y);
- ctx.lineTo(x + r, y);
- ctx.quadraticCurveTo(x, y, x, y + r);
- ctx.closePath();
-
- // Clip to the rounded rect path.
- ctx.save();
- ctx.clip();
-
- // Fill the segments with the associated color.
- var previousSegmentsWidth = 0;
- for (var i = 0; i < segments.length; ++i) {
- var segmentWidth = Math.round(w * percents[i] / 100);
- ctx.fillStyle = segments[i].color;
- ctx.fillRect(x + previousSegmentsWidth, y, segmentWidth, h);
- previousSegmentsWidth += segmentWidth;
- }
-
- // Draw the segment divider lines.
- ctx.lineWidth = 1;
- for (var i = 1; i < 20; ++i) {
- ctx.beginPath();
- ctx.moveTo(x + (i * Math.round(w / 20)) + 0.5, y);
- ctx.lineTo(x + (i * Math.round(w / 20)) + 0.5, y + h);
- ctx.closePath();
-
- ctx.strokeStyle = "rgba(0, 0, 0, 0.2)";
- ctx.stroke();
-
- ctx.beginPath();
- ctx.moveTo(x + (i * Math.round(w / 20)) + 1.5, y);
- ctx.lineTo(x + (i * Math.round(w / 20)) + 1.5, y + h);
- ctx.closePath();
-
- ctx.strokeStyle = "rgba(255, 255, 255, 0.2)";
- ctx.stroke();
- }
-
- // Draw the pill shading.
- var lightGradient = ctx.createLinearGradient(x, y, x, y + (h / 1.5));
- lightGradient.addColorStop(0.0, "rgba(220, 220, 220, 0.6)");
- lightGradient.addColorStop(0.4, "rgba(220, 220, 220, 0.2)");
- lightGradient.addColorStop(1.0, "rgba(255, 255, 255, 0.0)");
-
- var darkGradient = ctx.createLinearGradient(x, y + (h / 3), x, y + h);
- darkGradient.addColorStop(0.0, "rgba(0, 0, 0, 0.0)");
- darkGradient.addColorStop(0.8, "rgba(0, 0, 0, 0.2)");
- darkGradient.addColorStop(1.0, "rgba(0, 0, 0, 0.5)");
-
- ctx.fillStyle = darkGradient;
- ctx.fillRect(x, y, w, h);
-
- ctx.fillStyle = lightGradient;
- ctx.fillRect(x, y, w, h);
-
- ctx.restore();
+
+ if (this.mainResourceDOMContentTime !== -1) {
+ var percent = this.calculator.computePercentageFromEventTime(this.mainResourceDOMContentTime);
+ var domContentDivider = document.createElement("div");
+ domContentDivider.className = "resources-ondomcontent-divider";
+ domContentDivider.title = WebInspector.UIString("DOMContent event fired");
+ domContentDivider.style.left = percent + "%";
+ this.dividersElement.appendChild(domContentDivider);
}
-
- ctx.clearRect(x, y, w, (h * 2));
-
- drawPillShadow();
- drawPill();
-
- ctx.save();
-
- ctx.translate(0, (h * 2) + 1);
- ctx.scale(1, -1);
-
- drawPill();
-
- ctx.restore();
-
- this._fadeOutRect(ctx, x, y + h + 1, w, h, 0.5, 0.0);
},
_updateSummaryGraph: function()
{
- var graphInfo = this.calculator.computeSummaryValues(this._resources);
-
- var categoryColors = {documents: {r: 47, g: 102, b: 236}, stylesheets: {r: 157, g: 231, b: 119}, images: {r: 164, g: 60, b: 255}, scripts: {r: 255, g: 121, b: 0}, xhr: {r: 231, g: 231, b: 10}, fonts: {r: 255, g: 82, b: 62}, other: {r: 186, g: 186, b: 186}};
- var fillSegments = [];
-
- this.legendElement.removeChildren();
-
- for (var i = 0; i < this.categoryOrder.length; ++i) {
- var category = this.categoryOrder[i];
- var size = graphInfo.categoryValues[category];
- if (!size)
- continue;
-
- var color = categoryColors[category];
- var colorString = "rgb(" + color.r + ", " + color.g + ", " + color.b + ")";
-
- var fillSegment = {color: colorString, value: size};
- fillSegments.push(fillSegment);
-
- var legendLabel = this._makeLegendElement(WebInspector.resourceCategories[category].title, this.calculator.formatValue(size), colorString);
- this.legendElement.appendChild(legendLabel);
- }
-
- if (graphInfo.total) {
- var totalLegendLabel = this._makeLegendElement(WebInspector.UIString("Total"), this.calculator.formatValue(graphInfo.total));
- totalLegendLabel.addStyleClass("total");
- this.legendElement.appendChild(totalLegendLabel);
- }
-
- this._drawSummaryGraph(fillSegments);
+ this.summaryBar.update(this._resources);
},
_updateDividersLabelBarPosition: function()
{
var scrollTop = this.containerElement.scrollTop;
- var dividersTop = (scrollTop < this.summaryElement.offsetHeight ? this.summaryElement.offsetHeight : scrollTop);
+ var dividersTop = (scrollTop < this.summaryBar.element.offsetHeight ? this.summaryBar.element.offsetHeight : scrollTop);
this.dividersElement.style.top = scrollTop + "px";
this.dividersLabelBarElement.style.top = dividersTop + "px";
},
@@ -1072,16 +829,18 @@ WebInspector.ResourcesPanel.prototype = {
return;
this.resourcesTreeElement.smallChildren = !this.resourcesTreeElement.smallChildren;
+ Preferences.resourcesLargeRows = !Preferences.resourcesLargeRows;
+ InspectorController.setSetting("resources-large-rows", Preferences.resourcesLargeRows);
if (this.resourcesTreeElement.smallChildren) {
this.resourcesGraphsElement.addStyleClass("small");
this.largerResourcesButton.title = WebInspector.UIString("Use large resource rows.");
- this.largerResourcesButton.removeStyleClass("toggled-on");
+ this.largerResourcesButton.toggled = false;
this._adjustScrollPosition();
} else {
this.resourcesGraphsElement.removeStyleClass("small");
this.largerResourcesButton.title = WebInspector.UIString("Use small resource rows.");
- this.largerResourcesButton.addStyleClass("toggled-on");
+ this.largerResourcesButton.toggled = true;
}
},
@@ -1096,7 +855,7 @@ WebInspector.ResourcesPanel.prototype = {
{
var selectedOption = this.sortingSelectElement[this.sortingSelectElement.selectedIndex];
this.sortingFunction = selectedOption.sortingFunction;
- this.calculator = selectedOption.calculator;
+ this.calculator = this.summaryBar.calculator = selectedOption.calculator;
},
_createResourceView: function(resource)
@@ -1354,6 +1113,17 @@ WebInspector.ResourceTimeCalculator.prototype = {
return {start: start, middle: middle, end: end};
},
+
+ computePercentageFromEventTime: function(eventTime)
+ {
+ // This function computes a percentage in terms of the total loading time
+ // of a specific event. If startAtZero is set, then this is useless, and we
+ // want to return 0.
+ if (eventTime !== -1 && !this.startAtZero)
+ return ((eventTime - this.minimumBoundary) / this.boundarySpan) * 100;
+
+ return 0;
+ },
computeBarGraphLabels: function(resource)
{
@@ -1515,7 +1285,7 @@ WebInspector.ResourceSidebarTreeElement.prototype = {
ondblclick: function(treeElement, event)
{
- InspectorController.inspectedWindow().open(this.resource.url);
+ InjectedScriptAccess.openInInspectedWindow(this.resource.url, function() {});
},
get mainTitle()
@@ -1546,6 +1316,11 @@ WebInspector.ResourceSidebarTreeElement.prototype = {
// Do nothing.
},
+ get selectable()
+ {
+ return WebInspector.panels.resources._filterCategory == "all" || WebInspector.panels.resources._filterCategory == this.resource.category.name;
+ },
+
createIconElement: function()
{
var previousIconElement = this.iconElement;
diff --git a/WebCore/inspector/front-end/ScopeChainSidebarPane.js b/WebCore/inspector/front-end/ScopeChainSidebarPane.js
index a293fa0..fdfcd38 100644
--- a/WebCore/inspector/front-end/ScopeChainSidebarPane.js
+++ b/WebCore/inspector/front-end/ScopeChainSidebarPane.js
@@ -26,6 +26,7 @@
WebInspector.ScopeChainSidebarPane = function()
{
WebInspector.SidebarPane.call(this, WebInspector.UIString("Scope Variables"));
+ this._expandedProperties = [];
}
WebInspector.ScopeChainSidebarPane.prototype = {
@@ -44,52 +45,43 @@ WebInspector.ScopeChainSidebarPane.prototype = {
return;
}
- if (!callFrame._expandedProperties) {
- // FIXME: fix this when https://bugs.webkit.org/show_bug.cgi?id=19410 is fixed.
- // The callFrame is a JSInspectedObjectWrapper, so we are not allowed to assign
- // an object created in the Inspector's context to that object. So create an
- // Object from the inspectedWindow.
- var inspectedWindow = InspectorController.inspectedWindow();
- callFrame._expandedProperties = new inspectedWindow.Object;
- }
-
var foundLocalScope = false;
var scopeChain = callFrame.scopeChain;
for (var i = 0; i < scopeChain.length; ++i) {
- var scopeObject = scopeChain[i];
+ var scopeObjectProxy = scopeChain[i];
var title = null;
- var subtitle = Object.describe(scopeObject, true);
+ var subtitle = scopeObjectProxy.description;
var emptyPlaceholder = null;
- var localScope = false;
var extraProperties = null;
- if (Object.prototype.toString.call(scopeObject) === "[object JSActivation]") {
- if (!foundLocalScope) {
- extraProperties = { "this": callFrame.thisObject };
- title = WebInspector.UIString("Local");
- } else
- title = WebInspector.UIString("Closure");
+ if (scopeObjectProxy.isLocal) {
+ foundLocalScope = true;
+ title = WebInspector.UIString("Local");
+ emptyPlaceholder = WebInspector.UIString("No Variables");
+ subtitle = null;
+ if (scopeObjectProxy.thisObject)
+ extraProperties = [ new WebInspector.ObjectPropertyProxy("this", scopeObjectProxy.thisObject) ];
+ } else if (scopeObjectProxy.isClosure) {
+ title = WebInspector.UIString("Closure");
emptyPlaceholder = WebInspector.UIString("No Variables");
subtitle = null;
- foundLocalScope = true;
- localScope = true;
} else if (i === (scopeChain.length - 1))
title = WebInspector.UIString("Global");
- else if (foundLocalScope && scopeObject instanceof InspectorController.inspectedWindow().Element)
+ else if (scopeObjectProxy.isElement)
title = WebInspector.UIString("Event Target");
- else if (foundLocalScope && scopeObject instanceof InspectorController.inspectedWindow().Document)
+ else if (scopeObjectProxy.isDocument)
title = WebInspector.UIString("Event Document");
- else if (!foundLocalScope && !localScope)
+ else if (scopeObjectProxy.isWithBlock)
title = WebInspector.UIString("With Block");
if (!title || title === subtitle)
subtitle = null;
- var section = new WebInspector.ObjectPropertiesSection(new WebInspector.ObjectProxy(scopeObject), title, subtitle, emptyPlaceholder, true, extraProperties, WebInspector.ScopeVariableTreeElement);
+ var section = new WebInspector.ObjectPropertiesSection(scopeObjectProxy, title, subtitle, emptyPlaceholder, true, extraProperties, WebInspector.ScopeVariableTreeElement);
section.editInSelectedCallFrameWhenPaused = true;
section.pane = this;
- if (!foundLocalScope || localScope)
+ if (!foundLocalScope || scopeObjectProxy.isLocal)
section.expanded = true;
this.sections.push(section);
@@ -109,18 +101,18 @@ WebInspector.ScopeVariableTreeElement.prototype = {
onattach: function()
{
WebInspector.ObjectPropertyTreeElement.prototype.onattach.call(this);
- if (this.hasChildren && this.propertyIdentifier in this.treeOutline.section.pane.callFrame._expandedProperties)
+ if (this.hasChildren && this.propertyIdentifier in this.treeOutline.section.pane._expandedProperties)
this.expand();
},
onexpand: function()
{
- this.treeOutline.section.pane.callFrame._expandedProperties[this.propertyIdentifier] = true;
+ this.treeOutline.section.pane._expandedProperties[this.propertyIdentifier] = true;
},
oncollapse: function()
{
- delete this.treeOutline.section.pane.callFrame._expandedProperties[this.propertyIdentifier];
+ delete this.treeOutline.section.pane._expandedProperties[this.propertyIdentifier];
},
get propertyIdentifier()
diff --git a/WebCore/inspector/front-end/ScriptsPanel.js b/WebCore/inspector/front-end/ScriptsPanel.js
index 0058374..05ec197 100644
--- a/WebCore/inspector/front-end/ScriptsPanel.js
+++ b/WebCore/inspector/front-end/ScriptsPanel.js
@@ -126,6 +126,7 @@ WebInspector.ScriptsPanel = function()
this.topStatusBar.appendChild(this.sidebarResizeWidgetElement);
this.sidebarPanes = {};
+ this.sidebarPanes.watchExpressions = new WebInspector.WatchExpressionsSidebarPane();
this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane();
this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane();
this.sidebarPanes.breakpoints = new WebInspector.BreakpointsSidebarPane();
@@ -151,13 +152,10 @@ WebInspector.ScriptsPanel = function()
this.element.appendChild(this.sidebarElement);
this.element.appendChild(this.sidebarResizeElement);
- this.enableToggleButton = this.createStatusBarButton();
- this.enableToggleButton.className = "enable-toggle-status-bar-item status-bar-item";
+ this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item");
this.enableToggleButton.addEventListener("click", this._toggleDebugging.bind(this), false);
- this.pauseOnExceptionButton = this.createStatusBarButton();
- this.pauseOnExceptionButton.id = "scripts-pause-on-exceptions-status-bar-item";
- this.pauseOnExceptionButton.className = "status-bar-item";
+ this.pauseOnExceptionButton = new WebInspector.StatusBarButton("", "scripts-pause-on-exceptions-status-bar-item");
this.pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions.bind(this), false);
this._breakpointsURLMap = {};
@@ -208,7 +206,7 @@ WebInspector.ScriptsPanel.prototype = {
get statusBarItems()
{
- return [this.enableToggleButton, this.pauseOnExceptionButton];
+ return [this.enableToggleButton.element, this.pauseOnExceptionButton.element];
},
get paused()
@@ -286,7 +284,7 @@ WebInspector.ScriptsPanel.prototype = {
if (startingLine <= breakpoint.line) {
breakpoint.sourceID = sourceID;
if (breakpoint.enabled)
- InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line);
+ InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line, breakpoint.condition);
}
}
}
@@ -353,7 +351,15 @@ WebInspector.ScriptsPanel.prototype = {
sourceFrame.removeBreakpoint(breakpoint);
},
- evaluateInSelectedCallFrame: function(code, updateInterface, callback)
+ selectedCallFrameId: function()
+ {
+ var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame;
+ if (!selectedCallFrame)
+ return null;
+ return selectedCallFrame.id;
+ },
+
+ evaluateInSelectedCallFrame: function(code, updateInterface, objectGroup, callback)
{
var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame;
if (!this._paused || !selectedCallFrame)
@@ -369,41 +375,36 @@ WebInspector.ScriptsPanel.prototype = {
if (updateInterface)
self.sidebarPanes.scopechain.update(selectedCallFrame);
}
- this.doEvalInCallFrame(selectedCallFrame, code, updatingCallbackWrapper);
+ this.doEvalInCallFrame(selectedCallFrame, code, objectGroup, updatingCallbackWrapper);
},
- doEvalInCallFrame: function(callFrame, code, callback)
+ doEvalInCallFrame: function(callFrame, code, objectGroup, callback)
{
- var panel = this;
- function delayedEvaluation()
+ function evalCallback(result)
{
- if (!code) {
- // Evaluate into properties in scope of the selected call frame.
- callback(panel._variablesInScope(callFrame));
- return;
- }
- try {
- callback(callFrame.evaluate(code));
- } catch (e) {
- callback(e, true);
- }
+ if (result)
+ callback(result.value, result.isException);
}
- setTimeout(delayedEvaluation, 0);
+ InjectedScriptAccess.evaluateInCallFrame(callFrame.id, code, objectGroup, evalCallback);
},
- _variablesInScope: function(callFrame)
+ variablesInSelectedCallFrame: function()
{
+ var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame;
+ if (!this._paused || !selectedCallFrame)
+ return {};
+
var result = {};
- var scopeChain = callFrame.scopeChain;
+ var scopeChain = selectedCallFrame.scopeChain;
for (var i = 0; i < scopeChain.length; ++i) {
- var scopeObject = scopeChain[i];
- for (var property in scopeObject)
- result[property] = true;
+ var scopeObjectProperties = scopeChain[i].properties;
+ for (var j = 0; j < scopeObjectProperties.length; ++j)
+ result[scopeObjectProperties[j]] = true;
}
return result;
},
- debuggerPaused: function()
+ debuggerPaused: function(callFrames)
{
this._paused = true;
this._waitingToPause = false;
@@ -411,10 +412,8 @@ WebInspector.ScriptsPanel.prototype = {
this._updateDebuggerButtons();
- var callStackPane = this.sidebarPanes.callstack;
- var currentFrame = InspectorController.currentCallFrame();
- callStackPane.update(currentFrame, this._sourceIDMap);
- callStackPane.selectedCallFrame = currentFrame;
+ this.sidebarPanes.callstack.update(callFrames, this._sourceIDMap);
+ this.sidebarPanes.callstack.selectedCallFrame = callFrames[0];
WebInspector.currentPanel = this;
window.focus();
@@ -481,6 +480,8 @@ WebInspector.ScriptsPanel.prototype = {
}
this._sourceIDMap = {};
+
+ this.sidebarPanes.watchExpressions.refreshExpressions();
},
get visibleView()
@@ -714,6 +715,7 @@ WebInspector.ScriptsPanel.prototype = {
return;
this.sidebarPanes.scopechain.update(currentFrame);
+ this.sidebarPanes.watchExpressions.refreshExpressions();
var scriptOrResource = this._sourceIDMap[currentFrame.sourceID];
this._showScriptOrResource(scriptOrResource, currentFrame.line);
@@ -764,10 +766,10 @@ WebInspector.ScriptsPanel.prototype = {
{
if (InspectorController.pauseOnExceptions()) {
this.pauseOnExceptionButton.title = WebInspector.UIString("Don't pause on exceptions.");
- this.pauseOnExceptionButton.addStyleClass("toggled-on");
+ this.pauseOnExceptionButton.toggled = true;
} else {
this.pauseOnExceptionButton.title = WebInspector.UIString("Pause on exceptions.");
- this.pauseOnExceptionButton.removeStyleClass("toggled-on");
+ this.pauseOnExceptionButton.toggled = false;
}
},
@@ -775,13 +777,13 @@ WebInspector.ScriptsPanel.prototype = {
{
if (InspectorController.debuggerEnabled()) {
this.enableToggleButton.title = WebInspector.UIString("Debugging enabled. Click to disable.");
- this.enableToggleButton.addStyleClass("toggled-on");
- this.pauseOnExceptionButton.removeStyleClass("hidden");
+ this.enableToggleButton.toggled = true;
+ this.pauseOnExceptionButton.visible = true;
this.panelEnablerView.visible = false;
} else {
this.enableToggleButton.title = WebInspector.UIString("Debugging disabled. Click to enable.");
- this.enableToggleButton.removeStyleClass("toggled-on");
- this.pauseOnExceptionButton.addStyleClass("hidden");
+ this.enableToggleButton.toggled = false;
+ this.pauseOnExceptionButton.visible = false;
this.panelEnablerView.visible = true;
}
diff --git a/WebCore/inspector/front-end/SourceFrame.js b/WebCore/inspector/front-end/SourceFrame.js
index 930eb16..790055a 100644
--- a/WebCore/inspector/front-end/SourceFrame.js
+++ b/WebCore/inspector/front-end/SourceFrame.js
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -115,7 +116,7 @@ WebInspector.SourceFrame.prototype = {
this._lineNumberToReveal = lineNumber;
return;
}
-
+
var row = this.sourceRow(lineNumber);
if (row)
row.scrollIntoViewIfNeeded(true);
@@ -199,6 +200,7 @@ WebInspector.SourceFrame.prototype = {
_loaded: function()
{
WebInspector.addMainEventListeners(this.element.contentDocument);
+ this.element.contentDocument.addEventListener("contextmenu", this._documentContextMenu.bind(this), true);
this.element.contentDocument.addEventListener("mousedown", this._documentMouseDown.bind(this), true);
this.element.contentDocument.addEventListener("keydown", this._documentKeyDown.bind(this), true);
this.element.contentDocument.addEventListener("keyup", WebInspector.documentKeyUp.bind(WebInspector), true);
@@ -215,27 +217,45 @@ WebInspector.SourceFrame.prototype = {
headElement = this.element.contentDocument.createElement("head");
this.element.contentDocument.documentElement.insertBefore(headElement, this.element.contentDocument.documentElement.firstChild);
}
+
+ var linkElement = this.element.contentDocument.createElement("link");
+ linkElement.type = "text/css";
+ linkElement.rel = "stylesheet";
+ linkElement.href = "inspectorSyntaxHighlight.css";
+ headElement.appendChild(linkElement);
var styleElement = this.element.contentDocument.createElement("style");
headElement.appendChild(styleElement);
// Add these style rules here since they are specific to the Inspector. They also behave oddly and not
- // all properties apply if added to view-source.css (becuase it is a user agent sheet.)
+ // all properties apply if added to view-source.css (because it is a user agent sheet.)
var styleText = ".webkit-line-number { background-repeat: no-repeat; background-position: right 1px; }\n";
+ styleText += ".webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(program-counter); }\n";
+
styleText += ".webkit-breakpoint .webkit-line-number { color: white; background-image: -webkit-canvas(breakpoint); }\n";
styleText += ".webkit-breakpoint-disabled .webkit-line-number { color: white; background-image: -webkit-canvas(breakpoint-disabled); }\n";
- styleText += ".webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(program-counter); }\n";
styleText += ".webkit-breakpoint.webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(breakpoint-program-counter); }\n";
styleText += ".webkit-breakpoint-disabled.webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(breakpoint-disabled-program-counter); }\n";
+
+ styleText += ".webkit-breakpoint.webkit-breakpoint-conditional .webkit-line-number { color: white; background-image: -webkit-canvas(breakpoint-conditional); }\n";
+ styleText += ".webkit-breakpoint-disabled.webkit-breakpoint-conditional .webkit-line-number { color: white; background-image: -webkit-canvas(breakpoint-disabled-conditional); }\n";
+ styleText += ".webkit-breakpoint.webkit-breakpoint-conditional.webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(breakpoint-conditional-program-counter); }\n";
+ styleText += ".webkit-breakpoint-disabled.webkit-breakpoint-conditional.webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(breakpoint-disabled-conditional-program-counter); }\n";
+
styleText += ".webkit-execution-line .webkit-line-content { background-color: rgb(171, 191, 254); outline: 1px solid rgb(64, 115, 244); }\n";
styleText += ".webkit-height-sized-to-fit { overflow-y: hidden }\n";
styleText += ".webkit-line-content { background-color: white; }\n";
styleText += "@-webkit-keyframes fadeout {from {background-color: rgb(255, 255, 120);} to { background-color: white;}}\n";
styleText += ".webkit-highlighted-line .webkit-line-content { background-color: rgb(255, 255, 120); -webkit-animation: 'fadeout' 2s 500ms}\n";
- styleText += ".webkit-javascript-comment { color: rgb(0, 116, 0); }\n";
- styleText += ".webkit-javascript-keyword { color: rgb(170, 13, 145); }\n";
- styleText += ".webkit-javascript-number { color: rgb(28, 0, 207); }\n";
- styleText += ".webkit-javascript-string, .webkit-javascript-regexp { color: rgb(196, 26, 22); }\n";
+
+ // TODO: Move these styles into inspector.css once https://bugs.webkit.org/show_bug.cgi?id=28913 is fixed and popup moved into the top frame.
+ styleText += ".popup-content { position: absolute; z-index: 10000; padding: 4px; background-color: rgb(203, 226, 255); -webkit-border-radius: 7px; border: 2px solid rgb(169, 172, 203); }";
+ styleText += ".popup-glasspane { position: absolute; top: 0; left: 0; height: 100%; width: 100%; opacity: 0; z-index: 9900; }";
+ styleText += ".popup-message { background-color: transparent; font-family: Lucida Grande, sans-serif; font-weight: normal; font-size: 11px; text-align: left; text-shadow: none; color: rgb(85, 85, 85); cursor: default; margin: 0 0 2px 0; }";
+ styleText += ".popup-content.breakpoint-condition { width: 90%; }";
+ styleText += ".popup-content input#bp-condition { font-family: monospace; margin: 0; border: 1px inset rgb(190, 190, 190) !important; width: 100%; box-shadow: none !important; outline: none !important; -webkit-user-modify: read-write; }";
+ // This class is already in inspector.css
+ styleText += ".hidden { display: none !important; }";
styleElement.textContent = styleText;
@@ -244,8 +264,12 @@ WebInspector.SourceFrame.prototype = {
this.element.contentWindow.Element.prototype.addStyleClass = Element.prototype.addStyleClass;
this.element.contentWindow.Element.prototype.removeStyleClass = Element.prototype.removeStyleClass;
+ this.element.contentWindow.Element.prototype.positionAt = Element.prototype.positionAt;
this.element.contentWindow.Element.prototype.removeMatchingStyleClasses = Element.prototype.removeMatchingStyleClasses;
this.element.contentWindow.Element.prototype.hasStyleClass = Element.prototype.hasStyleClass;
+ this.element.contentWindow.Element.prototype.pageOffsetRelativeToWindow = Element.prototype.pageOffsetRelativeToWindow;
+ this.element.contentWindow.Element.prototype.__defineGetter__("totalOffsetLeft", Element.prototype.__lookupGetter__("totalOffsetLeft"));
+ this.element.contentWindow.Element.prototype.__defineGetter__("totalOffsetTop", Element.prototype.__lookupGetter__("totalOffsetTop"));
this.element.contentWindow.Node.prototype.enclosingNodeOrSelfWithNodeName = Node.prototype.enclosingNodeOrSelfWithNodeName;
this.element.contentWindow.Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = Node.prototype.enclosingNodeOrSelfWithNodeNameInArray;
@@ -257,20 +281,20 @@ WebInspector.SourceFrame.prototype = {
if (this.autoSizesToFitContentHeight)
this.sizeToFitContentHeight();
-
+
if (this._lineNumberToReveal) {
this.revealLine(this._lineNumberToReveal);
delete this._lineNumberToReveal;
}
-
+
if (this._lineNumberToHighlight) {
this.highlightLine(this._lineNumberToHighlight);
delete this._lineNumberToHighlight;
}
-
+
this.dispatchEventToListeners("content loaded");
},
-
+
_isContentLoaded: function() {
var doc = this.element.contentDocument;
return doc && doc.getElementsByTagName("table")[0];
@@ -283,18 +307,102 @@ WebInspector.SourceFrame.prototype = {
this.sizeToFitContentHeight();
},
- _documentMouseDown: function(event)
+ _documentContextMenu: function(event)
{
if (!event.target.hasStyleClass("webkit-line-number"))
return;
+ var sourceRow = event.target.enclosingNodeOrSelfWithNodeName("tr");
+ if (!sourceRow._breakpointObject && this.addBreakpointDelegate)
+ this.addBreakpointDelegate(this.lineNumberForSourceRow(sourceRow));
+
+ var breakpoint = sourceRow._breakpointObject;
+ if (!breakpoint)
+ return;
+ this._editBreakpointCondition(event.target, sourceRow, breakpoint);
+ event.preventDefault();
+ },
+
+ _documentMouseDown: function(event)
+ {
+ if (!event.target.hasStyleClass("webkit-line-number"))
+ return;
+ if (event.button != 0 || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey)
+ return;
var sourceRow = event.target.enclosingNodeOrSelfWithNodeName("tr");
- if (sourceRow._breakpointObject)
- sourceRow._breakpointObject.enabled = !sourceRow._breakpointObject.enabled;
+ if (sourceRow._breakpointObject && sourceRow._breakpointObject.enabled)
+ sourceRow._breakpointObject.enabled = false;
+ else if (sourceRow._breakpointObject)
+ WebInspector.panels.scripts.removeBreakpoint(sourceRow._breakpointObject);
else if (this.addBreakpointDelegate)
this.addBreakpointDelegate(this.lineNumberForSourceRow(sourceRow));
},
+ _editBreakpointCondition: function(eventTarget, sourceRow, breakpoint)
+ {
+ // TODO: Migrate the popup to the top-level document and remove the blur listener from conditionElement once https://bugs.webkit.org/show_bug.cgi?id=28913 is fixed.
+ var popupDocument = this.element.contentDocument;
+ this._showBreakpointConditionPopup(eventTarget, breakpoint.line, popupDocument);
+
+ function committed(element, newText)
+ {
+ breakpoint.condition = newText;
+ if (breakpoint.condition)
+ sourceRow.addStyleClass("webkit-breakpoint-conditional");
+ else
+ sourceRow.removeStyleClass("webkit-breakpoint-conditional");
+ dismissed.call(this);
+ }
+
+ function dismissed()
+ {
+ this._popup.hide();
+ delete this._conditionEditorElement;
+ }
+
+ var dismissedHandler = dismissed.bind(this);
+ this._conditionEditorElement.addEventListener("blur", dismissedHandler, false);
+
+ WebInspector.startEditing(this._conditionEditorElement, committed.bind(this), dismissedHandler);
+ this._conditionEditorElement.value = breakpoint.condition;
+ this._conditionEditorElement.select();
+ },
+
+ _showBreakpointConditionPopup: function(clickedElement, lineNumber, popupDocument)
+ {
+ var popupContentElement = this._createPopupElement(lineNumber, popupDocument);
+ var lineElement = clickedElement.enclosingNodeOrSelfWithNodeName("td").nextSibling;
+ if (this._popup) {
+ this._popup.hide();
+ this._popup.element = popupContentElement;
+ } else {
+ this._popup = new WebInspector.Popup(popupContentElement);
+ this._popup.autoHide = true;
+ }
+ this._popup.anchor = lineElement;
+ this._popup.show();
+ },
+
+ _createPopupElement: function(lineNumber, popupDocument)
+ {
+ var popupContentElement = popupDocument.createElement("div");
+ popupContentElement.className = "popup-content breakpoint-condition";
+
+ var labelElement = document.createElement("label");
+ labelElement.className = "popup-message";
+ labelElement.htmlFor = "bp-condition";
+ labelElement.appendChild(document.createTextNode(WebInspector.UIString("The breakpoint on line %d will stop only if this expression is true:", lineNumber)));
+ popupContentElement.appendChild(labelElement);
+
+ var editorElement = document.createElement("input");
+ editorElement.id = "bp-condition";
+ editorElement.type = "text"
+ popupContentElement.appendChild(editorElement);
+ this._conditionEditorElement = editorElement;
+
+ return popupContentElement;
+ },
+
_documentKeyDown: function(event)
{
var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event);
@@ -380,6 +488,8 @@ WebInspector.SourceFrame.prototype = {
sourceRow.addStyleClass("webkit-breakpoint");
if (!breakpoint.enabled)
sourceRow.addStyleClass("webkit-breakpoint-disabled");
+ if (breakpoint.condition)
+ sourceRow.addStyleClass("webkit-breakpoint-conditional");
},
_removeBreakpointFromSource: function(breakpoint)
@@ -392,8 +502,9 @@ WebInspector.SourceFrame.prototype = {
sourceRow.removeStyleClass("webkit-breakpoint");
sourceRow.removeStyleClass("webkit-breakpoint-disabled");
+ sourceRow.removeStyleClass("webkit-breakpoint-conditional");
},
-
+
_incrementMessageRepeatCount: function(msg, repeatDelta)
{
if (!msg._resourceMessageLineElement)
@@ -518,12 +629,12 @@ WebInspector.SourceFrame.prototype = {
delete this._needsProgramCounterImage;
},
- _drawBreakpointImagesIfNeeded: function()
+ _drawBreakpointImagesIfNeeded: function(conditional)
{
if (!this._needsBreakpointImages || !this.element.contentDocument)
return;
- function drawBreakpoint(ctx, disabled)
+ function drawBreakpoint(ctx, disabled, conditional)
{
ctx.beginPath();
ctx.moveTo(0, 2);
@@ -534,8 +645,8 @@ WebInspector.SourceFrame.prototype = {
ctx.lineTo(2, 11);
ctx.lineTo(0, 9);
ctx.closePath();
- ctx.fillStyle = "rgb(1, 142, 217)";
- ctx.strokeStyle = "rgb(0, 103, 205)";
+ ctx.fillStyle = conditional ? "rgb(217, 142, 1)" : "rgb(1, 142, 217)";
+ ctx.strokeStyle = conditional ? "rgb(205, 103, 0)" : "rgb(0, 103, 205)";
ctx.lineWidth = 3;
ctx.fill();
ctx.save();
@@ -553,6 +664,9 @@ WebInspector.SourceFrame.prototype = {
ctx.restore();
}
+
+ // Unconditional breakpoints.
+
var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint", 26, 11);
ctx.clearRect(0, 0, 26, 11);
drawBreakpoint(ctx);
@@ -573,6 +687,29 @@ WebInspector.SourceFrame.prototype = {
ctx.clearRect(20, 0, 6, 11);
this._drawProgramCounterInContext(ctx, true);
+
+ // Conditional breakpoints.
+
+ var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-conditional", 26, 11);
+ ctx.clearRect(0, 0, 26, 11);
+ drawBreakpoint(ctx, false, true);
+
+ var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-conditional-program-counter", 26, 11);
+ ctx.clearRect(0, 0, 26, 11);
+ drawBreakpoint(ctx, false, true);
+ ctx.clearRect(20, 0, 6, 11);
+ this._drawProgramCounterInContext(ctx, true);
+
+ var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-disabled-conditional", 26, 11);
+ ctx.clearRect(0, 0, 26, 11);
+ drawBreakpoint(ctx, true, true);
+
+ var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-disabled-conditional-program-counter", 26, 11);
+ ctx.clearRect(0, 0, 26, 11);
+ drawBreakpoint(ctx, true, true);
+ ctx.clearRect(20, 0, 6, 11);
+ this._drawProgramCounterInContext(ctx, true);
+
delete this._needsBreakpointImages;
},
@@ -582,190 +719,394 @@ WebInspector.SourceFrame.prototype = {
if (!table)
return;
- function deleteContinueFlags(cell)
- {
- if (!cell)
- return;
- delete cell._commentContinues;
- delete cell._singleQuoteStringContinues;
- delete cell._doubleQuoteStringContinues;
- delete cell._regexpContinues;
- }
+ var jsSyntaxHighlighter = new WebInspector.JavaScriptSourceSyntaxHighlighter(table, this);
+ jsSyntaxHighlighter.process();
+ },
- function createSpan(content, className)
- {
- var span = document.createElement("span");
- span.className = className;
- span.appendChild(document.createTextNode(content));
- return span;
- }
+ syntaxHighlightCSS: function()
+ {
+ var table = this.element.contentDocument.getElementsByTagName("table")[0];
+ if (!table)
+ return;
- function generateFinder(regex, matchNumber, className)
- {
- return function(str) {
- var match = regex.exec(str);
- if (!match)
- return null;
- previousMatchLength = match[matchNumber].length;
- return createSpan(match[matchNumber], className);
- };
- }
+ var cssSyntaxHighlighter = new WebInspector.CSSSourceSyntaxHighligher(table, this);
+ cssSyntaxHighlighter.process();
+ }
+}
- var findNumber = generateFinder(/^(-?(\d+\.?\d*([eE][+-]\d+)?|0[xX]\h+|Infinity)|NaN)(?:\W|$)/, 1, "webkit-javascript-number");
- var findKeyword = generateFinder(/^(null|true|false|break|case|catch|const|default|finally|for|instanceof|new|var|continue|function|return|void|delete|if|this|do|while|else|in|switch|throw|try|typeof|with|debugger|class|enum|export|extends|import|super|get|set)(?:\W|$)/, 1, "webkit-javascript-keyword");
- var findSingleLineString = generateFinder(/^"(?:[^"\\]|\\.)*"|^'([^'\\]|\\.)*'/, 0, "webkit-javascript-string"); // " this quote keeps Xcode happy
- var findMultilineCommentStart = generateFinder(/^\/\*.*$/, 0, "webkit-javascript-comment");
- var findMultilineCommentEnd = generateFinder(/^.*?\*\//, 0, "webkit-javascript-comment");
- var findMultilineSingleQuoteStringStart = generateFinder(/^'(?:[^'\\]|\\.)*\\$/, 0, "webkit-javascript-string");
- var findMultilineSingleQuoteStringEnd = generateFinder(/^(?:[^'\\]|\\.)*?'/, 0, "webkit-javascript-string");
- var findMultilineDoubleQuoteStringStart = generateFinder(/^"(?:[^"\\]|\\.)*\\$/, 0, "webkit-javascript-string");
- var findMultilineDoubleQuoteStringEnd = generateFinder(/^(?:[^"\\]|\\.)*?"/, 0, "webkit-javascript-string");
- var findMultilineRegExpEnd = generateFinder(/^(?:[^\/\\]|\\.)*?\/([gim]{0,3})/, 0, "webkit-javascript-regexp");
- var findSingleLineComment = generateFinder(/^\/\/.*|^\/\*.*?\*\//, 0, "webkit-javascript-comment");
-
- function findMultilineRegExpStart(str)
- {
- var match = /^\/(?:[^\/\\]|\\.)*\\$/.exec(str);
- if (!match || !/\\|\$|\.[\?\*\+]|[^\|]\|[^\|]/.test(match[0]))
+WebInspector.SourceFrame.prototype.__proto__ = WebInspector.Object.prototype;
+
+WebInspector.SourceSyntaxHighligher = function(table, sourceFrame)
+{
+ this.table = table;
+ this.sourceFrame = sourceFrame;
+}
+
+WebInspector.SourceSyntaxHighligher.prototype = {
+ createSpan: function(content, className)
+ {
+ var span = document.createElement("span");
+ span.className = className;
+ span.appendChild(document.createTextNode(content));
+ return span;
+ },
+
+ generateFinder: function(regex, matchNumber, className)
+ {
+ return function(str) {
+ var match = regex.exec(str);
+ if (!match)
return null;
- var node = createSpan(match[0], "webkit-javascript-regexp");
- previousMatchLength = match[0].length;
- return node;
- }
+ this.previousMatchLength = match[matchNumber].length;
+ return this.createSpan(match[matchNumber], className);
+ };
+ },
+
+ process: function()
+ {
+ // Split up the work into chunks so we don't block the
+ // UI thread while processing.
+
+ var i = 0;
+ var rows = this.table.rows;
+ var rowsLength = rows.length;
+ var previousCell = null;
+ const linesPerChunk = 10;
- function findSingleLineRegExp(str)
+ function processChunk()
{
- var match = /^(\/(?:[^\/\\]|\\.)*\/([gim]{0,3}))(.?)/.exec(str);
- if (!match || !(match[2].length > 0 || /\\|\$|\.[\?\*\+]|[^\|]\|[^\|]/.test(match[1]) || /\.|;|,/.test(match[3])))
- return null;
- var node = createSpan(match[1], "webkit-javascript-regexp");
- previousMatchLength = match[1].length;
- return node;
+ for (var end = Math.min(i + linesPerChunk, rowsLength); i < end; ++i) {
+ var row = rows[i];
+ if (!row)
+ continue;
+ var cell = row.cells[1];
+ if (!cell)
+ continue;
+ this.syntaxHighlightLine(cell, previousCell);
+ if (i < (end - 1))
+ this.deleteContinueFlags(previousCell);
+ previousCell = cell;
+ }
+
+ if (i >= rowsLength && processChunkInterval) {
+ this.deleteContinueFlags(previousCell);
+ delete this.previousMatchLength;
+ clearInterval(processChunkInterval);
+
+ this.sourceFrame.dispatchEventToListeners("syntax highlighting complete");
+ }
}
- function syntaxHighlightJavascriptLine(line, prevLine)
- {
- var messageBubble = line.lastChild;
- if (messageBubble && messageBubble.nodeType === Node.ELEMENT_NODE && messageBubble.hasStyleClass("webkit-html-message-bubble"))
- line.removeChild(messageBubble);
- else
- messageBubble = null;
+ var boundProcessChunk = processChunk.bind(this);
+ var processChunkInterval = setInterval(boundProcessChunk, 25);
+ boundProcessChunk();
+ }
+}
+
+WebInspector.CSSSourceSyntaxHighligher = function(table, sourceFrame) {
+ WebInspector.SourceSyntaxHighligher.call(this, table, sourceFrame);
+
+ this.findNumber = this.generateFinder(/^((-?(\d+|\d*\.\d+))|^(#[a-fA-F0-9]{3,6}))(?:\D|$)/, 1, "webkit-css-number");
+ this.findUnits = this.generateFinder(/^(px|em|pt|in|cm|mm|pc|ex)(?:\W|$)/, 1, "webkit-css-unit");
+ this.findKeyword = this.generateFinder(/^(rgba?|hsla?|var)(?:\W|$)/, 1, "webkit-css-keyword");
+ this.findSingleLineString = this.generateFinder(/^"(?:[^"\\]|\\.)*"|^'([^'\\]|\\.)*'/, 0, "webkit-css-string"); // " this quote keeps Xcode happy
+ this.findSingleLineComment = this.generateFinder(/^\/\*.*?\*\//, 0, "webkit-css-comment");
+ this.findMultilineCommentStart = this.generateFinder(/^\/\*.*$/, 0, "webkit-css-comment");
+ this.findMultilineCommentEnd = this.generateFinder(/^.*?\*\//, 0, "webkit-css-comment");
+ this.findSelector = this.generateFinder(/^([#\.]?[_a-zA-Z].*?)(?:\W|$)/, 1, "webkit-css-selector");
+ this.findProperty = this.generateFinder(/^(-?[_a-z0-9][_a-z0-9-]*\s*)(?:\:)/, 1, "webkit-css-property");
+ this.findGenericIdent = this.generateFinder(/^([@-]?[_a-z0-9][_a-z0-9-]*)(?:\W|$)/, 1, "webkit-css-string");
+}
+
+WebInspector.CSSSourceSyntaxHighligher.prototype = {
+ deleteContinueFlags: function(cell)
+ {
+ if (!cell)
+ return;
+ delete cell._commentContinues;
+ delete cell._inSelector;
+ },
+
+ findPseudoClass: function(str)
+ {
+ var match = /^(::?)([_a-z0-9][_a-z0-9-]*)/.exec(str);
+ if (!match)
+ return null;
+ this.previousMatchLength = match[0].length;
+ var span = document.createElement("span");
+ span.appendChild(document.createTextNode(match[1]));
+ span.appendChild(this.createSpan(match[2], "webkit-css-pseudo-class"));
+ return span;
+ },
+
+ findURL: function(str)
+ {
+ var match = /^(?:local|url)\(([^\)]*?)\)/.exec(str);
+ if (!match)
+ return null;
+ this.previousMatchLength = match[0].length;
+ var innerUrlSpan = this.createSpan(match[1], "webkit-css-url");
+ var outerSpan = document.createElement("span");
+ outerSpan.appendChild(this.createSpan("url", "webkit-css-keyword"));
+ outerSpan.appendChild(document.createTextNode("("));
+ outerSpan.appendChild(innerUrlSpan);
+ outerSpan.appendChild(document.createTextNode(")"));
+ return outerSpan;
+ },
+
+ findAtRule: function(str)
+ {
+ var match = /^@[_a-z0-9][_a-z0-9-]*(?:\W|$)/.exec(str);
+ if (!match)
+ return null;
+ this.previousMatchLength = match[0].length;
+ return this.createSpan(match[0], "webkit-css-at-rule");
+ },
- var code = line.textContent;
+ syntaxHighlightLine: function(line, prevLine)
+ {
+ var code = line.textContent;
+ while (line.firstChild)
+ line.removeChild(line.firstChild);
- while (line.firstChild)
- line.removeChild(line.firstChild);
+ var token;
+ var tmp = 0;
+ var i = 0;
+ this.previousMatchLength = 0;
- var token;
- var tmp = 0;
- var i = 0;
- previousMatchLength = 0;
+ if (prevLine) {
+ if (prevLine._commentContinues) {
+ if (!(token = this.findMultilineCommentEnd(code))) {
+ token = this.createSpan(code, "webkit-javascript-comment");
+ line._commentContinues = true;
+ }
+ }
+ if (token) {
+ i += this.previousMatchLength ? this.previousMatchLength : code.length;
+ tmp = i;
+ line.appendChild(token);
+ }
+ }
- if (prevLine) {
- if (prevLine._commentContinues) {
- if (!(token = findMultilineCommentEnd(code))) {
- token = createSpan(code, "webkit-javascript-comment");
- line._commentContinues = true;
+ var inSelector = (prevLine && prevLine._inSelector); // inside a selector, we can now parse properties and values
+ var inAtRuleBlock = (prevLine && prevLine._inAtRuleBlock); // inside an @rule block, but not necessarily inside a selector yet
+ var atRuleStarted = (prevLine && prevLine._atRuleStarted); // we received an @rule, we may stop the @rule at a semicolon or open a block and become inAtRuleBlock
+ var atRuleIsSelector = (prevLine && prevLine._atRuleIsSelector); // when this @rule opens a block it immediately goes into parsing properties and values instead of selectors
+
+ for ( ; i < code.length; ++i) {
+ var codeFragment = code.substr(i);
+ var prevChar = code[i - 1];
+ var currChar = codeFragment[0];
+ token = this.findSingleLineComment(codeFragment);
+ if (!token) {
+ if ((token = this.findMultilineCommentStart(codeFragment)))
+ line._commentContinues = true;
+ else if (currChar === ";" && !inAtRuleBlock)
+ atRuleStarted = false;
+ else if (currChar === "}") {
+ if (inSelector && inAtRuleBlock && atRuleIsSelector) {
+ inSelector = false;
+ inAtRuleBlock = false;
+ atRuleStarted = false;
+ } else if (inSelector) {
+ inSelector = false;
+ } else if (inAtRuleBlock) {
+ inAtRuleBlock = false;
+ atRuleStarted = false;
}
- } else if (prevLine._singleQuoteStringContinues) {
- if (!(token = findMultilineSingleQuoteStringEnd(code))) {
- token = createSpan(code, "webkit-javascript-string");
- line._singleQuoteStringContinues = true;
+ } else if (currChar === "{") {
+ if (!atRuleStarted || inAtRuleBlock) {
+ inSelector = true;
+ } else if (!inAtRuleBlock && atRuleIsSelector) {
+ inAtRuleBlock = true;
+ inSelector = true;
+ } else if (!inAtRuleBlock) {
+ inAtRuleBlock = true;
+ inSelector = false;
}
- } else if (prevLine._doubleQuoteStringContinues) {
- if (!(token = findMultilineDoubleQuoteStringEnd(code))) {
- token = createSpan(code, "webkit-javascript-string");
- line._doubleQuoteStringContinues = true;
+ } else if (inSelector) {
+ if (!prevChar || /^\d/.test(prevChar)) {
+ token = this.findUnits(codeFragment);
+ } else if (!prevChar || /^\W/.test(prevChar)) {
+ token = this.findNumber(codeFragment) ||
+ this.findKeyword(codeFragment) ||
+ this.findURL(codeFragment) ||
+ this.findProperty(codeFragment) ||
+ this.findAtRule(codeFragment) ||
+ this.findGenericIdent(codeFragment) ||
+ this.findSingleLineString(codeFragment);
}
- } else if (prevLine._regexpContinues) {
- if (!(token = findMultilineRegExpEnd(code))) {
- token = createSpan(code, "webkit-javascript-regexp");
- line._regexpContinues = true;
+ } else if (!inSelector) {
+ if (atRuleStarted && !inAtRuleBlock)
+ token = this.findURL(codeFragment); // for @import
+ if (!token) {
+ token = this.findSelector(codeFragment) ||
+ this.findPseudoClass(codeFragment) ||
+ this.findAtRule(codeFragment);
}
}
- if (token) {
- i += previousMatchLength ? previousMatchLength : code.length;
- tmp = i;
- line.appendChild(token);
- }
}
- for ( ; i < code.length; ++i) {
- var codeFragment = code.substr(i);
- var prevChar = code[i - 1];
- token = findSingleLineComment(codeFragment);
- if (!token) {
- if ((token = findMultilineCommentStart(codeFragment)))
- line._commentContinues = true;
- else if (!prevChar || /^\W/.test(prevChar)) {
- token = findNumber(codeFragment, code[i - 1]) ||
- findKeyword(codeFragment, code[i - 1]) ||
- findSingleLineString(codeFragment) ||
- findSingleLineRegExp(codeFragment);
- if (!token) {
- if (token = findMultilineSingleQuoteStringStart(codeFragment))
- line._singleQuoteStringContinues = true;
- else if (token = findMultilineDoubleQuoteStringStart(codeFragment))
- line._doubleQuoteStringContinues = true;
- else if (token = findMultilineRegExpStart(codeFragment))
- line._regexpContinues = true;
- }
- }
- }
+ if (token) {
+ if (currChar === "@") {
+ atRuleStarted = true;
- if (token) {
- if (tmp !== i)
- line.appendChild(document.createTextNode(code.substring(tmp, i)));
- line.appendChild(token);
- i += previousMatchLength - 1;
- tmp = i + 1;
+ // The @font-face, @page, and @variables at-rules do not contain selectors like other at-rules
+ // instead it acts as a selector and contains properties and values.
+ var text = token.textContent;
+ atRuleIsSelector = /font-face/.test(text) || /page/.test(text) || /variables/.test(text);
}
+
+ if (tmp !== i)
+ line.appendChild(document.createTextNode(code.substring(tmp, i)));
+ line.appendChild(token);
+ i += this.previousMatchLength - 1;
+ tmp = i + 1;
}
+ }
- if (tmp < code.length)
- line.appendChild(document.createTextNode(code.substring(tmp, i)));
+ line._inSelector = inSelector;
+ line._inAtRuleBlock = inAtRuleBlock;
+ line._atRuleStarted = atRuleStarted;
+ line._atRuleIsSelector = atRuleIsSelector;
- if (messageBubble)
- line.appendChild(messageBubble);
- }
+ if (tmp < code.length)
+ line.appendChild(document.createTextNode(code.substring(tmp, i)));
+ }
+}
- var i = 0;
- var rows = table.rows;
- var rowsLength = rows.length;
- var previousCell = null;
- var previousMatchLength = 0;
- var sourceFrame = this;
+WebInspector.CSSSourceSyntaxHighligher.prototype.__proto__ = WebInspector.SourceSyntaxHighligher.prototype;
+
+WebInspector.JavaScriptSourceSyntaxHighlighter = function(table, sourceFrame) {
+ WebInspector.SourceSyntaxHighligher.call(this, table, sourceFrame);
+
+ this.findNumber = this.generateFinder(/^(-?(\d+\.?\d*([eE][+-]\d+)?|0[xX]\h+|Infinity)|NaN)(?:\W|$)/, 1, "webkit-javascript-number");
+ this.findKeyword = this.generateFinder(/^(null|true|false|break|case|catch|const|default|finally|for|instanceof|new|var|continue|function|return|void|delete|if|this|do|while|else|in|switch|throw|try|typeof|with|debugger|class|enum|export|extends|import|super|get|set)(?:\W|$)/, 1, "webkit-javascript-keyword");
+ this.findSingleLineString = this.generateFinder(/^"(?:[^"\\]|\\.)*"|^'([^'\\]|\\.)*'/, 0, "webkit-javascript-string"); // " this quote keeps Xcode happy
+ this.findMultilineCommentStart = this.generateFinder(/^\/\*.*$/, 0, "webkit-javascript-comment");
+ this.findMultilineCommentEnd = this.generateFinder(/^.*?\*\//, 0, "webkit-javascript-comment");
+ this.findMultilineSingleQuoteStringStart = this.generateFinder(/^'(?:[^'\\]|\\.)*\\$/, 0, "webkit-javascript-string");
+ this.findMultilineSingleQuoteStringEnd = this.generateFinder(/^(?:[^'\\]|\\.)*?'/, 0, "webkit-javascript-string");
+ this.findMultilineDoubleQuoteStringStart = this.generateFinder(/^"(?:[^"\\]|\\.)*\\$/, 0, "webkit-javascript-string");
+ this.findMultilineDoubleQuoteStringEnd = this.generateFinder(/^(?:[^"\\]|\\.)*?"/, 0, "webkit-javascript-string");
+ this.findMultilineRegExpEnd = this.generateFinder(/^(?:[^\/\\]|\\.)*?\/([gim]{0,3})/, 0, "webkit-javascript-regexp");
+ this.findSingleLineComment = this.generateFinder(/^\/\/.*|^\/\*.*?\*\//, 0, "webkit-javascript-comment");
+}
- // Split up the work into chunks so we don't block the
- // UI thread while processing.
+WebInspector.JavaScriptSourceSyntaxHighlighter.prototype = {
+ deleteContinueFlags: function(cell)
+ {
+ if (!cell)
+ return;
+ delete cell._commentContinues;
+ delete cell._singleQuoteStringContinues;
+ delete cell._doubleQuoteStringContinues;
+ delete cell._regexpContinues;
+ },
- function processChunk()
- {
- for (var end = Math.min(i + 10, rowsLength); i < end; ++i) {
- var row = rows[i];
- if (!row)
- continue;
- var cell = row.cells[1];
- if (!cell)
- continue;
- syntaxHighlightJavascriptLine(cell, previousCell);
- if (i < (end - 1))
- deleteContinueFlags(previousCell);
- previousCell = cell;
+ findMultilineRegExpStart: function(str)
+ {
+ var match = /^\/(?:[^\/\\]|\\.)*\\$/.exec(str);
+ if (!match || !/\\|\$|\.[\?\*\+]|[^\|]\|[^\|]/.test(match[0]))
+ return null;
+ this.previousMatchLength = match[0].length;
+ return this.createSpan(match[0], "webkit-javascript-regexp");
+ },
+
+ findSingleLineRegExp: function(str)
+ {
+ var match = /^(\/(?:[^\/\\]|\\.)*\/([gim]{0,3}))(.?)/.exec(str);
+ if (!match || !(match[2].length > 0 || /\\|\$|\.[\?\*\+]|[^\|]\|[^\|]/.test(match[1]) || /\.|;|,/.test(match[3])))
+ return null;
+ this.previousMatchLength = match[1].length;
+ return this.createSpan(match[1], "webkit-javascript-regexp");
+ },
+
+ syntaxHighlightLine: function(line, prevLine)
+ {
+ var messageBubble = line.lastChild;
+ if (messageBubble && messageBubble.nodeType === Node.ELEMENT_NODE && messageBubble.hasStyleClass("webkit-html-message-bubble"))
+ line.removeChild(messageBubble);
+ else
+ messageBubble = null;
+
+ var code = line.textContent;
+
+ while (line.firstChild)
+ line.removeChild(line.firstChild);
+
+ var token;
+ var tmp = 0;
+ var i = 0;
+ this.previousMatchLength = 0;
+
+ if (prevLine) {
+ if (prevLine._commentContinues) {
+ if (!(token = this.findMultilineCommentEnd(code))) {
+ token = this.createSpan(code, "webkit-javascript-comment");
+ line._commentContinues = true;
+ }
+ } else if (prevLine._singleQuoteStringContinues) {
+ if (!(token = this.findMultilineSingleQuoteStringEnd(code))) {
+ token = this.createSpan(code, "webkit-javascript-string");
+ line._singleQuoteStringContinues = true;
+ }
+ } else if (prevLine._doubleQuoteStringContinues) {
+ if (!(token = this.findMultilineDoubleQuoteStringEnd(code))) {
+ token = this.createSpan(code, "webkit-javascript-string");
+ line._doubleQuoteStringContinues = true;
+ }
+ } else if (prevLine._regexpContinues) {
+ if (!(token = this.findMultilineRegExpEnd(code))) {
+ token = this.createSpan(code, "webkit-javascript-regexp");
+ line._regexpContinues = true;
+ }
+ }
+ if (token) {
+ i += this.previousMatchLength ? this.previousMatchLength : code.length;
+ tmp = i;
+ line.appendChild(token);
}
+ }
- if (i >= rowsLength && processChunkInterval) {
- deleteContinueFlags(previousCell);
- clearInterval(processChunkInterval);
+ for ( ; i < code.length; ++i) {
+ var codeFragment = code.substr(i);
+ var prevChar = code[i - 1];
+ token = this.findSingleLineComment(codeFragment);
+ if (!token) {
+ if ((token = this.findMultilineCommentStart(codeFragment)))
+ line._commentContinues = true;
+ else if (!prevChar || /^\W/.test(prevChar)) {
+ token = this.findNumber(codeFragment) ||
+ this.findKeyword(codeFragment) ||
+ this.findSingleLineString(codeFragment) ||
+ this.findSingleLineRegExp(codeFragment);
+ if (!token) {
+ if (token = this.findMultilineSingleQuoteStringStart(codeFragment))
+ line._singleQuoteStringContinues = true;
+ else if (token = this.findMultilineDoubleQuoteStringStart(codeFragment))
+ line._doubleQuoteStringContinues = true;
+ else if (token = this.findMultilineRegExpStart(codeFragment))
+ line._regexpContinues = true;
+ }
+ }
+ }
- sourceFrame.dispatchEventToListeners("syntax highlighting complete");
+ if (token) {
+ if (tmp !== i)
+ line.appendChild(document.createTextNode(code.substring(tmp, i)));
+ line.appendChild(token);
+ i += this.previousMatchLength - 1;
+ tmp = i + 1;
}
}
- processChunk();
+ if (tmp < code.length)
+ line.appendChild(document.createTextNode(code.substring(tmp, i)));
- var processChunkInterval = setInterval(processChunk, 25);
+ if (messageBubble)
+ line.appendChild(messageBubble);
}
}
-WebInspector.SourceFrame.prototype.__proto__ = WebInspector.Object.prototype;
+WebInspector.JavaScriptSourceSyntaxHighlighter.prototype.__proto__ = WebInspector.SourceSyntaxHighligher.prototype;
diff --git a/WebCore/inspector/front-end/SourceView.js b/WebCore/inspector/front-end/SourceView.js
index 97a5bd5..c1b1bbf 100644
--- a/WebCore/inspector/front-end/SourceView.js
+++ b/WebCore/inspector/front-end/SourceView.js
@@ -106,11 +106,16 @@ WebInspector.SourceView.prototype = {
this.sourceFrame.removeEventListener("content loaded", this._contentLoaded, this);
if (this.resource.type === WebInspector.Resource.Type.Script
- || this.resource.mimeType === 'application/json'
- || this.resource.mimeType === 'application/javascript'
+ || this.resource.mimeType === "application/json"
+ || this.resource.mimeType === "application/javascript"
|| /\.js(on)?$/.test(this.resource.lastPathComponent) ) {
this.sourceFrame.addEventListener("syntax highlighting complete", this._syntaxHighlightingComplete, this);
this.sourceFrame.syntaxHighlightJavascript();
+ } else if (this.resource.type === WebInspector.Resource.Type.Stylesheet
+ || this.resource.mimeType === "text/css"
+ || /\.css$/.test(this.resource.lastPathComponent) ) {
+ this.sourceFrame.addEventListener("syntax highlighting complete", this._syntaxHighlightingComplete, this);
+ this.sourceFrame.syntaxHighlightCSS();
} else
this._sourceFrameSetupFinished();
},
diff --git a/WebCore/inspector/front-end/StatusBarButton.js b/WebCore/inspector/front-end/StatusBarButton.js
new file mode 100644
index 0000000..5c69ed5
--- /dev/null
+++ b/WebCore/inspector/front-end/StatusBarButton.js
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.StatusBarButton = function(title, className)
+{
+ this.element = document.createElement("button");
+ this.element.className = className + " status-bar-item";
+ this.element.addEventListener("click", this._clicked.bind(this), false);
+
+ this.glyph = document.createElement("div");
+ this.glyph.className = "glyph";
+ this.element.appendChild(this.glyph);
+
+ this.glyphShadow = document.createElement("div");
+ this.glyphShadow.className = "glyph shadow";
+ this.element.appendChild(this.glyphShadow);
+
+ this.title = title;
+ this.disabled = false;
+ this._toggled = false;
+ this._visible = true;
+}
+
+WebInspector.StatusBarButton.prototype = {
+ _clicked: function()
+ {
+ this.dispatchEventToListeners("click");
+ },
+
+ get disabled()
+ {
+ return this._disabled;
+ },
+
+ set disabled(x)
+ {
+ if (this._disabled === x)
+ return;
+ this._disabled = x;
+ this.element.disabled = x;
+ },
+
+ get title()
+ {
+ return this._title;
+ },
+
+ set title(x)
+ {
+ if (this._title === x)
+ return;
+ this._title = x;
+ this.element.title = x;
+ },
+
+ get toggled()
+ {
+ return this._toggled;
+ },
+
+ set toggled(x)
+ {
+ if (this._toggled === x)
+ return;
+
+ if (x)
+ this.element.addStyleClass("toggled-on");
+ else
+ this.element.removeStyleClass("toggled-on");
+ this._toggled = x;
+ },
+
+ get visible()
+ {
+ return this._visible;
+ },
+
+ set visible(x)
+ {
+ if (this._visible === x)
+ return;
+
+ if (x)
+ this.element.removeStyleClass("hidden");
+ else
+ this.element.addStyleClass("hidden");
+ this._visible = x;
+ }
+}
+
+WebInspector.StatusBarButton.prototype.__proto__ = WebInspector.Object.prototype;
diff --git a/WebCore/inspector/front-end/DatabasesPanel.js b/WebCore/inspector/front-end/StoragePanel.js
index a31e3ff..089bb98 100644
--- a/WebCore/inspector/front-end/DatabasesPanel.js
+++ b/WebCore/inspector/front-end/StoragePanel.js
@@ -27,12 +27,12 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-WebInspector.DatabasesPanel = function(database)
+WebInspector.StoragePanel = function(database)
{
WebInspector.Panel.call(this);
this.sidebarElement = document.createElement("div");
- this.sidebarElement.id = "databases-sidebar";
+ this.sidebarElement.id = "storage-sidebar";
this.sidebarElement.className = "sidebar";
this.element.appendChild(this.sidebarElement);
@@ -59,6 +59,10 @@ WebInspector.DatabasesPanel = function(database)
this.sidebarTree.appendChild(this.sessionStorageListTreeElement);
this.sessionStorageListTreeElement.expand();
+ this.cookieListTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("COOKIES"), {}, true);
+ this.sidebarTree.appendChild(this.cookieListTreeElement);
+ this.cookieListTreeElement.expand();
+
this.storageViews = document.createElement("div");
this.storageViews.id = "storage-views";
this.element.appendChild(this.storageViews);
@@ -69,12 +73,12 @@ WebInspector.DatabasesPanel = function(database)
this.reset();
}
-WebInspector.DatabasesPanel.prototype = {
- toolbarItemClass: "databases",
+WebInspector.StoragePanel.prototype = {
+ toolbarItemClass: "storage",
get toolbarItemLabel()
{
- return WebInspector.UIString("Databases");
+ return WebInspector.UIString("Storage");
},
get statusBarItems()
@@ -86,7 +90,6 @@ WebInspector.DatabasesPanel.prototype = {
{
WebInspector.Panel.prototype.show.call(this);
this._updateSidebarWidth();
- this._registerStorageEventListener();
},
reset: function()
@@ -103,8 +106,6 @@ WebInspector.DatabasesPanel.prototype = {
this._databases = [];
- this._unregisterStorageEventListener();
-
if (this._domStorage) {
var domStorageLength = this._domStorage.length;
for (var i = 0; i < domStorageLength; ++i) {
@@ -116,12 +117,20 @@ WebInspector.DatabasesPanel.prototype = {
this._domStorage = [];
+ this._cookieDomains = {};
+ this._cookieViews = {};
+
this.databasesListTreeElement.removeChildren();
this.localStorageListTreeElement.removeChildren();
this.sessionStorageListTreeElement.removeChildren();
- this.storageViews.removeChildren();
-
+ this.cookieListTreeElement.removeChildren();
+
+ this.storageViews.removeChildren();
+
this.storageViewStatusBarItemsContainer.removeChildren();
+
+ if (this.sidebarTree.selectedTreeElement)
+ this.sidebarTree.selectedTreeElement.deselect();
},
handleKeyEvent: function(event)
@@ -137,11 +146,22 @@ WebInspector.DatabasesPanel.prototype = {
database._databasesTreeElement = databaseTreeElement;
this.databasesListTreeElement.appendChild(databaseTreeElement);
},
+
+ addCookieDomain: function(domain)
+ {
+ // Eliminate duplicate domains from the list.
+ if (typeof this._cookieDomains[domain] !== "undefined")
+ return;
+
+ var cookieDomainTreeElement = new WebInspector.CookieSidebarTreeElement(domain);
+ this.cookieListTreeElement.appendChild(cookieDomainTreeElement);
+ this._cookieDomains[domain] = true;
+ },
addDOMStorage: function(domStorage)
{
this._domStorage.push(domStorage);
- var domStorageTreeElement = new WebInspector.DOMStorageSidebarTreeElement(domStorage);
+ var domStorageTreeElement = new WebInspector.DOMStorageSidebarTreeElement(domStorage, (domStorage.isLocalStorage ? "local-storage" : "session-storage"));
domStorage._domStorageTreeElement = domStorageTreeElement;
if (domStorage.isLocalStorage)
this.localStorageListTreeElement.appendChild(domStorageTreeElement);
@@ -149,12 +169,12 @@ WebInspector.DatabasesPanel.prototype = {
this.sessionStorageListTreeElement.appendChild(domStorageTreeElement);
},
- selectDatabase: function(db)
+ selectDatabase: function(databaseId)
{
var database;
for (var i = 0, len = this._databases.length; i < len; ++i) {
database = this._databases[i];
- if ( db === database.database ) {
+ if (database.id === databaseId) {
this.showDatabase(database);
database._databasesTreeElement.select();
return;
@@ -162,16 +182,12 @@ WebInspector.DatabasesPanel.prototype = {
}
},
- selectDOMStorage: function(s)
+ selectDOMStorage: function(storageId)
{
- var isLocalStorage = (s === InspectorController.inspectedWindow().localStorage);
- for (var i = 0, len = this._domStorage.length; i < len; ++i) {
- var storage = this._domStorage[i];
- if ( isLocalStorage === storage.isLocalStorage ) {
- this.showDOMStorage(storage);
- storage._domStorageTreeElement.select();
- return;
- }
+ var domStorage = this._domStorageForId(storageId);
+ if (domStorage) {
+ this.showDOMStorage(domStorage);
+ domStorage._domStorageTreeElement.select();
}
},
@@ -207,7 +223,7 @@ WebInspector.DatabasesPanel.prototype = {
this.storageViewStatusBarItemsContainer.removeChildren();
var statusBarItems = view.statusBarItems || [];
for (var i = 0; i < statusBarItems.length; ++i)
- this.storageViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
+ this.storageViewStatusBarItemsContainer.appendChild(statusBarItems[i].element);
},
showDOMStorage: function(domStorage)
@@ -235,6 +251,27 @@ WebInspector.DatabasesPanel.prototype = {
this.storageViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
},
+ showCookies: function(cookieDomain)
+ {
+ if (this.visibleView)
+ this.visibleView.hide();
+
+ var view = this._cookieViews[cookieDomain];
+ if (!view) {
+ view = new WebInspector.CookieItemsView(cookieDomain);
+ this._cookieViews[cookieDomain] = view;
+ }
+
+ view.show(this.storageViews);
+
+ this.visibleView = view;
+
+ this.storageViewStatusBarItemsContainer.removeChildren();
+ var statusBarItems = view.statusBarItems;
+ for (var i = 0; i < statusBarItems.length; ++i)
+ this.storageViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
+ },
+
closeVisibleView: function()
{
if (this.visibleView)
@@ -253,34 +290,39 @@ WebInspector.DatabasesPanel.prototype = {
return;
var tableNamesHash = {};
- var tableNames = database.tableNames;
- var tableNamesLength = tableNames.length;
- for (var i = 0; i < tableNamesLength; ++i)
- tableNamesHash[tableNames[i]] = true;
-
- for (var tableName in database._tableViews) {
- if (!(tableName in tableNamesHash)) {
- if (this.visibleView === database._tableViews[tableName])
- this.closeVisibleView();
- delete database._tableViews[tableName];
+ var self = this;
+ function tableNamesCallback(tableNames)
+ {
+ var tableNamesLength = tableNames.length;
+ for (var i = 0; i < tableNamesLength; ++i)
+ tableNamesHash[tableNames[i]] = true;
+
+ for (var tableName in database._tableViews) {
+ if (!(tableName in tableNamesHash)) {
+ if (self.visibleView === database._tableViews[tableName])
+ self.closeVisibleView();
+ delete database._tableViews[tableName];
+ }
}
}
+ database.getTableNames(tableNamesCallback);
},
- dataGridForResult: function(result)
+ dataGridForResult: function(rows)
{
- if (!result.rows.length)
+ if (!rows.length)
return null;
var columns = {};
+ var numColumns = 0;
- var rows = result.rows;
- for (var columnIdentifier in rows.item(0)) {
+ for (var columnIdentifier in rows[0]) {
var column = {};
column.width = columnIdentifier.length;
column.title = columnIdentifier;
columns[columnIdentifier] = column;
+ ++numColumns;
}
var nodes = [];
@@ -288,12 +330,9 @@ WebInspector.DatabasesPanel.prototype = {
for (var i = 0; i < length; ++i) {
var data = {};
- var row = rows.item(i);
+ var row = rows[i];
for (var columnIdentifier in row) {
- // FIXME: (Bug 19439) We should specially format SQL NULL here
- // (which is represented by JavaScript null here, and turned
- // into the string "null" by the String() function).
- var text = String(row[columnIdentifier]);
+ var text = row[columnIdentifier];
data[columnIdentifier] = text;
if (text.length > columns[columnIdentifier].width)
columns[columnIdentifier].width = text.length;
@@ -309,7 +348,7 @@ WebInspector.DatabasesPanel.prototype = {
totalColumnWidths += columns[columnIdentifier].width;
// Calculate the percentage width for the columns.
- const minimumPrecent = 5;
+ const minimumPrecent = Math.min(5, Math.floor(100/numColumns));
var recoupPercent = 0;
for (var columnIdentifier in columns) {
var width = columns[columnIdentifier].width;
@@ -346,61 +385,6 @@ WebInspector.DatabasesPanel.prototype = {
return dataGrid;
},
- dataGridForDOMStorage: function(domStorage)
- {
- if (!domStorage.length)
- return null;
-
- var columns = {};
- columns[0] = {};
- columns[1] = {};
- columns[0].title = WebInspector.UIString("Key");
- columns[0].width = columns[0].title.length;
- columns[1].title = WebInspector.UIString("Value");
- columns[1].width = columns[0].title.length;
-
- var nodes = [];
-
- var length = domStorage.length;
- for (var index = 0; index < domStorage.length; index++) {
- var data = {};
-
- var key = String(domStorage.key(index));
- data[0] = key;
- if (key.length > columns[0].width)
- columns[0].width = key.length;
-
- var value = String(domStorage.getItem(key));
- data[1] = value;
- if (value.length > columns[1].width)
- columns[1].width = value.length;
- var node = new WebInspector.DataGridNode(data, false);
- node.selectable = true;
- nodes.push(node);
- }
-
- var totalColumnWidths = columns[0].width + columns[1].width;
- width = Math.round((columns[0].width * 100) / totalColumnWidths);
- const minimumPrecent = 10;
- if (width < minimumPrecent)
- width = minimumPrecent;
- if (width > 100 - minimumPrecent)
- width = 100 - minimumPrecent;
- columns[0].width = width;
- columns[1].width = 100 - width;
- columns[0].width += "%";
- columns[1].width += "%";
-
- var dataGrid = new WebInspector.DOMStorageDataGrid(columns);
- var length = nodes.length;
- for (var i = 0; i < length; ++i)
- dataGrid.appendChild(nodes[i]);
- dataGrid.addCreationNode(false);
- if (length > 0)
- nodes[0].selected = true;
- return dataGrid;
- },
-
resize: function()
{
var visibleView = this.visibleView;
@@ -408,44 +392,28 @@ WebInspector.DatabasesPanel.prototype = {
visibleView.resize();
},
- _registerStorageEventListener: function()
+ updateDOMStorage: function(storageId)
{
- var inspectedWindow = InspectorController.inspectedWindow();
- if (!inspectedWindow || !inspectedWindow.document)
- return;
-
- this._storageEventListener = InspectorController.wrapCallback(this._storageEvent.bind(this));
- inspectedWindow.addEventListener("storage", this._storageEventListener, true);
- },
-
- _unregisterStorageEventListener: function()
- {
- if (!this._storageEventListener)
- return;
-
- var inspectedWindow = InspectorController.inspectedWindow();
- if (!inspectedWindow || !inspectedWindow.document)
+ var domStorage = this._domStorageForId(storageId);
+ if (!domStorage)
return;
- inspectedWindow.removeEventListener("storage", this._storageEventListener, true);
- delete this._storageEventListener;
+ var view = domStorage._domStorageView;
+ if (this.visibleView && view === this.visibleView)
+ domStorage._domStorageView.update();
},
- _storageEvent: function(event)
+ _domStorageForId: function(storageId)
{
if (!this._domStorage)
- return;
-
- var isLocalStorage = (event.storageArea === InspectorController.inspectedWindow().localStorage);
+ return null;
var domStorageLength = this._domStorage.length;
for (var i = 0; i < domStorageLength; ++i) {
var domStorage = this._domStorage[i];
- if (isLocalStorage === domStorage.isLocalStorage) {
- var view = domStorage._domStorageView;
- if (this.visibleView && view === this.visibleView)
- domStorage._domStorageView.update();
- }
+ if (domStorage.id == storageId)
+ return domStorage;
}
+ return null;
},
_startSidebarDragging: function(event)
@@ -494,7 +462,7 @@ WebInspector.DatabasesPanel.prototype = {
}
}
-WebInspector.DatabasesPanel.prototype.__proto__ = WebInspector.Panel.prototype;
+WebInspector.StoragePanel.prototype.__proto__ = WebInspector.Panel.prototype;
WebInspector.DatabaseSidebarTreeElement = function(database)
{
@@ -508,7 +476,7 @@ WebInspector.DatabaseSidebarTreeElement = function(database)
WebInspector.DatabaseSidebarTreeElement.prototype = {
onselect: function()
{
- WebInspector.panels.databases.showDatabase(this.database);
+ WebInspector.panels.storage.showDatabase(this.database);
},
oncollapse: function()
@@ -522,10 +490,14 @@ WebInspector.DatabaseSidebarTreeElement.prototype = {
{
this.removeChildren();
- var tableNames = this.database.tableNames;
- var tableNamesLength = tableNames.length;
- for (var i = 0; i < tableNamesLength; ++i)
- this.appendChild(new WebInspector.SidebarDatabaseTableTreeElement(this.database, tableNames[i]));
+ var self = this;
+ function tableNamesCallback(tableNames)
+ {
+ var tableNamesLength = tableNames.length;
+ for (var i = 0; i < tableNamesLength; ++i)
+ self.appendChild(new WebInspector.SidebarDatabaseTableTreeElement(self.database, tableNames[i]));
+ }
+ this.database.getTableNames(tableNamesCallback);
},
get mainTitle()
@@ -562,18 +534,18 @@ WebInspector.SidebarDatabaseTableTreeElement = function(database, tableName)
WebInspector.SidebarDatabaseTableTreeElement.prototype = {
onselect: function()
{
- WebInspector.panels.databases.showDatabase(this.database, this.tableName);
+ WebInspector.panels.storage.showDatabase(this.database, this.tableName);
}
}
WebInspector.SidebarDatabaseTableTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
-WebInspector.DOMStorageSidebarTreeElement = function(domStorage)
+WebInspector.DOMStorageSidebarTreeElement = function(domStorage, className)
{
this.domStorage = domStorage;
- WebInspector.SidebarTreeElement.call(this, "domstorage-sidebar-tree-item", domStorage, "", null, false);
+ WebInspector.SidebarTreeElement.call(this, "domstorage-sidebar-tree-item " + className, domStorage, "", null, false);
this.refreshTitles();
}
@@ -581,7 +553,7 @@ WebInspector.DOMStorageSidebarTreeElement = function(domStorage)
WebInspector.DOMStorageSidebarTreeElement.prototype = {
onselect: function()
{
- WebInspector.panels.databases.showDOMStorage(this.domStorage);
+ WebInspector.panels.storage.showDOMStorage(this.domStorage);
},
get mainTitle()
@@ -606,3 +578,30 @@ WebInspector.DOMStorageSidebarTreeElement.prototype = {
}
WebInspector.DOMStorageSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
+
+WebInspector.CookieSidebarTreeElement = function(cookieDomain)
+{
+ WebInspector.SidebarTreeElement.call(this, "cookie-sidebar-tree-item", cookieDomain, "", null, false);
+ this._cookieDomain = cookieDomain;
+
+ this.refreshTitles();
+}
+
+WebInspector.CookieSidebarTreeElement.prototype = {
+ onselect: function()
+ {
+ WebInspector.panels.storage.showCookies(this._cookieDomain);
+ },
+
+ get subtitle()
+ {
+ return "";
+ },
+
+ set subtitle(x)
+ {
+ // Do nothing.
+ }
+}
+
+WebInspector.CookieSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
diff --git a/WebCore/inspector/front-end/StylesSidebarPane.js b/WebCore/inspector/front-end/StylesSidebarPane.js
index 8a3a67f..3582f96 100644
--- a/WebCore/inspector/front-end/StylesSidebarPane.js
+++ b/WebCore/inspector/front-end/StylesSidebarPane.js
@@ -30,6 +30,44 @@
WebInspector.StylesSidebarPane = function()
{
WebInspector.SidebarPane.call(this, WebInspector.UIString("Styles"));
+
+ this.settingsSelectElement = document.createElement("select");
+
+ var option = document.createElement("option");
+ option.value = "hex";
+ option.action = this._changeColorFormat.bind(this);
+ if (Preferences.colorFormat === "hex")
+ option.selected = true;
+ option.label = WebInspector.UIString("Hex Colors");
+ this.settingsSelectElement.appendChild(option);
+
+ option = document.createElement("option");
+ option.value = "rgb";
+ option.action = this._changeColorFormat.bind(this);
+ if (Preferences.colorFormat === "rgb")
+ option.selected = true;
+ option.label = WebInspector.UIString("RGB Colors");
+ this.settingsSelectElement.appendChild(option);
+
+ option = document.createElement("option");
+ option.value = "hsl";
+ option.action = this._changeColorFormat.bind(this);
+ if (Preferences.colorFormat === "hsl")
+ option.selected = true;
+ option.label = WebInspector.UIString("HSL Colors");
+ this.settingsSelectElement.appendChild(option);
+
+ this.settingsSelectElement.appendChild(document.createElement("hr"));
+
+ option = document.createElement("option");
+ option.action = this._createNewRule.bind(this);
+ option.label = WebInspector.UIString("New Style Rule");
+ this.settingsSelectElement.appendChild(option);
+
+ this.settingsSelectElement.addEventListener("click", function(event) { event.stopPropagation() }, false);
+ this.settingsSelectElement.addEventListener("change", this._changeSetting.bind(this), false);
+
+ this.titleElement.appendChild(this.settingsSelectElement);
}
WebInspector.StylesSidebarPane.prototype = {
@@ -64,13 +102,15 @@ WebInspector.StylesSidebarPane.prototype = {
return;
var self = this;
- var callback = function(styles) {
+ function callback(styles)
+ {
if (!styles)
return;
- var nodeWrapper = WebInspector.wrapNodeWithStyles(node, styles);
- self._update(refresh, body, nodeWrapper, editedSection, forceUpdate);
- };
- InspectorController.getStyles(node, !Preferences.showUserAgentStyles, callback);
+ node._setStyles(styles.computedStyle, styles.inlineStyle, styles.styleAttributes, styles.matchedCSSRules);
+ self._update(refresh, body, node, editedSection, forceUpdate);
+ }
+
+ InjectedScriptAccess.getStyles(node.id, !Preferences.showUserAgentStyles, callback);
},
_update: function(refresh, body, node, editedSection, forceUpdate)
@@ -85,7 +125,7 @@ WebInspector.StylesSidebarPane.prototype = {
if (refresh) {
for (var i = 0; i < this.sections.length; ++i) {
var section = this.sections[i];
- if (section._blank)
+ if (section instanceof WebInspector.BlankStylePropertiesSection)
continue;
if (section.computedStyle)
section.styleRule.style = node.ownerDocument.defaultView.getComputedStyle(node);
@@ -269,41 +309,64 @@ WebInspector.StylesSidebarPane.prototype = {
body.appendChild(section.element);
this.sections.push(section);
}
+ }
+ },
- this.addBlankSection();
+ _changeSetting: function(event)
+ {
+ var options = this.settingsSelectElement.options;
+ var selectedOption = options[this.settingsSelectElement.selectedIndex];
+ selectedOption.action(event);
+
+ // Select the correct color format setting again, since it needs to be selected.
+ var selectedIndex = 0;
+ for (var i = 0; i < options.length; ++i) {
+ if (options[i].value === Preferences.colorFormat) {
+ selectedIndex = i;
+ break;
+ }
}
+
+ this.settingsSelectElement.selectedIndex = selectedIndex;
},
- addBlankSection: function()
+ _changeColorFormat: function(event)
{
- var blankSection = new WebInspector.BlankStylePropertiesSection();
- blankSection.pane = this;
+ var selectedOption = this.settingsSelectElement[this.settingsSelectElement.selectedIndex];
+ Preferences.colorFormat = selectedOption.value;
+
+ InspectorController.setSetting("color-format", Preferences.colorFormat);
- this.bodyElement.insertBefore(blankSection.element, this.bodyElement.firstChild.nextSibling.nextSibling); // 0 is computed, 1 is element.style
- var computed = this.sections.shift();
- var elementStyle = this.sections.shift();
- this.sections.unshift(blankSection);
- this.sections.unshift(elementStyle);
- this.sections.unshift(computed);
+ for (var i = 0; i < this.sections.length; ++i)
+ this.sections[i].update(true);
},
- appropriateSelectorForNode: function()
+ _createNewRule: function(event)
{
- var node = this.node;
- if (!node)
- return;
+ this.addBlankSection().startEditingSelector();
+ },
- if (node.id)
- return "#" + node.id;
+ addBlankSection: function()
+ {
+ var blankSection = new WebInspector.BlankStylePropertiesSection(appropriateSelectorForNode(this.node, true));
+ blankSection.pane = this;
- if (node.className)
- return "." + node.className.replace(/\s+/, ".");
+ var elementStyleSection = this.sections[1];
+ this.bodyElement.insertBefore(blankSection.element, elementStyleSection.element.nextSibling);
- var nodeName = node.nodeName.toLowerCase();
- if (nodeName === "input" && node.type)
- return nodeName + "[type=\"" + node.type + "\"]";
+ this.sections.splice(2, 0, blankSection);
- return nodeName;
+ return blankSection;
+ },
+
+ removeSection: function(section)
+ {
+ var index = this.sections.indexOf(section);
+ if (index === -1)
+ return;
+ this.sections.splice(index, 1);
+ if (section.element.parentNode)
+ section.element.parentNode.removeChild(section.element);
}
}
@@ -312,6 +375,7 @@ WebInspector.StylesSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.pr
WebInspector.StylePropertiesSection = function(styleRule, subtitle, computedStyle, usedProperties, editable)
{
WebInspector.PropertiesSection.call(this, styleRule.selectorText);
+
this.titleElement.addEventListener("click", function(e) { e.stopPropagation(); }, false);
this.titleElement.addEventListener("dblclick", this._dblclickSelector.bind(this), false);
this.element.addEventListener("dblclick", this._dblclickEmptySpace.bind(this), false);
@@ -322,8 +386,9 @@ WebInspector.StylePropertiesSection = function(styleRule, subtitle, computedStyl
this.editable = (editable && !computedStyle);
// Prevent editing the user agent and user rules.
- var isUserAgent = this.styleRule.isUserAgent;
- var isUser = this.styleRule.isUser;
+ var isUserAgent = this.rule && this.rule.isUserAgent;
+ var isUser = this.rule && this.rule.isUser;
+ var isViaInspector = this.rule && this.rule.isViaInspector;
if (isUserAgent || isUser)
this.editable = false;
@@ -366,7 +431,7 @@ WebInspector.StylePropertiesSection = function(styleRule, subtitle, computedStyl
subtitle = WebInspector.UIString("user agent stylesheet");
else if (isUser)
subtitle = WebInspector.UIString("user stylesheet");
- else if (this.styleRule.parentStyleSheet === WebInspector.panels.elements.stylesheet)
+ else if (isViaInspector)
subtitle = WebInspector.UIString("via inspector");
else
subtitle = WebInspector.UIString("inline stylesheet");
@@ -394,9 +459,6 @@ WebInspector.StylePropertiesSection.prototype = {
expand: function(dontRememberState)
{
- if (this._blank)
- return;
-
WebInspector.PropertiesSection.prototype.expand.call(this);
if (dontRememberState)
return;
@@ -559,8 +621,7 @@ WebInspector.StylePropertiesSection.prototype = {
if (WebInspector.isBeingEdited(element))
return;
- var context = this.styleRule.selectorText;
- WebInspector.startEditing(this.titleElement, this.editingSelectorCommitted.bind(this), this.editingSelectorCancelled.bind(this), context);
+ WebInspector.startEditing(this.titleElement, this.editingSelectorCommitted.bind(this), this.editingSelectorCancelled.bind(this), null);
window.getSelection().setBaseAndExtent(element, 0, element, 1);
},
@@ -583,10 +644,10 @@ WebInspector.StylePropertiesSection.prototype = {
return moveToNextIfNeeded.call(this);
var self = this;
- var callback = function(result) {
+ function callback(result)
+ {
if (!result) {
// Invalid Syntax for a Selector
- self.editingSelectorCancelled(element, context);
moveToNextIfNeeded.call(self);
return;
}
@@ -604,84 +665,61 @@ WebInspector.StylePropertiesSection.prototype = {
var newRule = WebInspector.CSSStyleDeclaration.parseRule(newRulePayload);
self.rule = newRule;
self.styleRule = { section: self, style: newRule.style, selectorText: newRule.selectorText, parentStyleSheet: newRule.parentStyleSheet, rule: newRule };
+
var oldIdentifier = this.identifier;
self.identifier = newRule.selectorText + ":" + self.subtitleElement.textContent;
- self.pane.update(null, true);
+
+ self.pane.update();
+
WebInspector.panels.elements.renameSelector(oldIdentifier, this.identifier, oldContent, newContent);
- moveToNextIfNeeded.call(self);
- };
- InspectorController.applyStyleRuleText(this.rule._id, newContent, this.pane.node, callback);
- },
+ moveToNextIfNeeded.call(self);
+ }
- editingSelectorCancelled: function(element, context)
- {
- element.textContent = context;
+ InjectedScriptAccess.applyStyleRuleText(this.rule.id, newContent, this.pane.node.id, callback);
},
- _doesSelectorAffectSelectedNode: function(selector)
+ editingSelectorCancelled: function()
{
- var selectedNode = this.pane.node;
- var nodes = selectedNode.ownerDocument.querySelectorAll(selector);
- for (var i = 0; i < nodes.length; ++i) {
- if (nodes[i] === selectedNode)
- return true;
- }
-
- return false;
+ // Do nothing, this is overridden by BlankStylePropertiesSection.
}
}
WebInspector.StylePropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;
-WebInspector.BlankStylePropertiesSection = function()
+WebInspector.BlankStylePropertiesSection = function(defaultSelectorText)
{
- WebInspector.PropertiesSection.call(this, WebInspector.UIString("Double-Click to Add"), null);
+ WebInspector.StylePropertiesSection.call(this, {selectorText: defaultSelectorText, rule: {isViaInspector: true}}, "", false, {}, false);
- this._blank = true;
- this._dblclickListener = this._dblclick.bind(this);
this.element.addStyleClass("blank-section");
- this.titleElement.addStyleClass("blank-title");
- this.titleElement.addEventListener("click", function(e) { e.stopPropagation(); }, false);
- this.titleElement.addEventListener("dblclick", this._dblclickListener, false);
}
WebInspector.BlankStylePropertiesSection.prototype = {
- _dblclick: function(event)
- {
- this.startEditing();
- },
-
- startEditing: function()
- {
- var element = this.titleElement;
- if (WebInspector.isBeingEdited(element))
- return;
-
- this.titleElement.textContent = this.pane.appropriateSelectorForNode();
- this.titleElement.removeStyleClass("blank-title");
- WebInspector.startEditing(this.titleElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), "");
- window.getSelection().setBaseAndExtent(element, 0, element, 1);
- },
-
- editingCancelled: function()
+ expand: function()
{
- this.titleElement.textContent = WebInspector.UIString("Double-Click to Add");
- this.titleElement.addStyleClass("blank-title");
+ // Do nothing, blank sections are not expandable.
},
- editingCommitted: function(element, newContent, oldContent, context)
+ editingSelectorCommitted: function(element, newContent, oldContent, context)
{
var self = this;
- var callback = function(styleRule) {
- if (!styleRule) {
+ function callback(result)
+ {
+ if (!result) {
// Invalid Syntax for a Selector
- self.editingCancelled();
+ self.editingSelectorCancelled();
return;
}
- self.makeNormal(WebInspector.CSSStyleDeclaration.parseRule(styleRule));
- if (!self._doesSelectorAffectSelectedNode(newContent)) {
+ var rule = result[0];
+ var doesSelectorAffectSelectedNode = result[1];
+
+ var styleRule = WebInspector.CSSStyleDeclaration.parseRule(rule);
+ styleRule.rule = rule;
+
+ self.makeNormal(styleRule);
+
+ if (!doesSelectorAffectSelectedNode) {
self.noAffect = true;
self.element.addStyleClass("no-affect");
}
@@ -689,31 +727,28 @@ WebInspector.BlankStylePropertiesSection.prototype = {
self.subtitleElement.textContent = WebInspector.UIString("via inspector");
self.expand();
- self.pane.addBlankSection();
self.addNewBlankProperty().startEditing();
- };
- InspectorController.addStyleSelector(newContent, callback);
+ }
+
+ InjectedScriptAccess.addStyleSelector(newContent, this.pane.node.id, callback);
+ },
+
+ editingSelectorCancelled: function()
+ {
+ this.pane.removeSection(this);
},
makeNormal: function(styleRule)
{
- this.titleElement.removeEventListener("dblclick", this._dblclickListener, false);
- this.titleElement.addEventListener("dblclick", this._dblclickSelector.bind(this), false);
- this.element.addEventListener("dblclick", this._dblclickEmptySpace.bind(this), false);
this.element.removeStyleClass("blank-section");
- delete this._blank;
- delete this._dblclick;
- delete this.startEditing;
- delete this.editingCancelled;
- delete this.editingCommitted;
- delete this._dblclickListener;
- delete this.makeNormal;
+
this.styleRule = styleRule;
this.rule = styleRule.rule;
this.computedStyle = false;
this.editable = true;
- this.identifier = styleRule.selectorText + ":inspector";
- // leftovers are: this.noAffect if applicable
+ this.identifier = styleRule.selectorText + ":via inspector";
+
+ this.__proto__ = WebInspector.StylePropertiesSection.prototype;
}
}
@@ -794,49 +829,14 @@ WebInspector.StylePropertyTreeElement.prototype = {
updateTitle: function()
{
- // "Nicknames" for some common values that are easier to read.
- var valueNicknames = {
- "rgb(0, 0, 0)": "black",
- "#000": "black",
- "#000000": "black",
- "rgb(255, 255, 255)": "white",
- "#fff": "white",
- "#ffffff": "white",
- "#FFF": "white",
- "#FFFFFF": "white",
- "rgba(0, 0, 0, 0)": "transparent",
- "rgb(255, 0, 0)": "red",
- "rgb(0, 255, 0)": "lime",
- "rgb(0, 0, 255)": "blue",
- "rgb(255, 255, 0)": "yellow",
- "rgb(255, 0, 255)": "magenta",
- "rgb(0, 255, 255)": "cyan"
- };
-
var priority = this.priority;
var value = this.value;
- var htmlValue = value;
if (priority && !priority.length)
delete priority;
if (priority)
priority = "!" + priority;
- if (value) {
- var urls = value.match(/url\([^)]+\)/);
- if (urls) {
- for (var i = 0; i < urls.length; ++i) {
- var url = urls[i].substring(4, urls[i].length - 1);
- htmlValue = htmlValue.replace(urls[i], "url(" + WebInspector.linkifyURL(url) + ")");
- }
- } else {
- if (value in valueNicknames)
- htmlValue = valueNicknames[value];
- htmlValue = htmlValue.escapeHTML();
- }
- } else
- htmlValue = value = "";
-
this.updateState();
var enabledCheckboxElement = document.createElement("input");
@@ -852,113 +852,156 @@ WebInspector.StylePropertyTreeElement.prototype = {
var valueElement = document.createElement("span");
valueElement.className = "value";
- valueElement.innerHTML = htmlValue;
this.valueElement = valueElement;
- if (priority) {
- var priorityElement = document.createElement("span");
- priorityElement.className = "priority";
- priorityElement.textContent = priority;
- }
-
- this.listItemElement.removeChildren();
-
- // Append the checkbox for root elements of an editable section.
- if (this.treeOutline.section && this.treeOutline.section.editable && this.parent.root)
- this.listItemElement.appendChild(enabledCheckboxElement);
- this.listItemElement.appendChild(nameElement);
- this.listItemElement.appendChild(document.createTextNode(": "));
- this.listItemElement.appendChild(valueElement);
+ if (value) {
+ function processValue(regex, processor, nextProcessor, valueText)
+ {
+ var container = document.createDocumentFragment();
+
+ var items = valueText.replace(regex, "\0$1\0").split("\0");
+ for (var i = 0; i < items.length; ++i) {
+ if ((i % 2) === 0) {
+ if (nextProcessor)
+ container.appendChild(nextProcessor(items[i]));
+ else
+ container.appendChild(document.createTextNode(items[i]));
+ } else {
+ var processedNode = processor(items[i]);
+ if (processedNode)
+ container.appendChild(processedNode);
+ }
+ }
- if (priorityElement) {
- this.listItemElement.appendChild(document.createTextNode(" "));
- this.listItemElement.appendChild(priorityElement);
- }
+ return container;
+ }
- this.listItemElement.appendChild(document.createTextNode(";"));
+ function linkifyURL(url)
+ {
+ var container = document.createDocumentFragment();
+ container.appendChild(document.createTextNode("url("));
+ container.appendChild(WebInspector.linkifyURLAsNode(url, url, null, (url in WebInspector.resourceURLMap)));
+ container.appendChild(document.createTextNode(")"));
+ return container;
+ }
- if (value) {
- // FIXME: this only covers W3C and CSS 16 valid color names
- var colors = value.match(/((rgb|hsl)a?\([^)]+\))|(#[0-9a-fA-F]{6})|(#[0-9a-fA-F]{3})|aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|purple|red|silver|teal|white|yellow|transparent/g);
- var swatch;
- if (colors) {
- var colorsLength = colors.length;
- for (var i = 0; i < colorsLength; ++i) {
- var swatchElement = document.createElement("span");
- swatchElement.className = "swatch";
- swatchElement.style.setProperty("background-color", colors[i]);
- this.listItemElement.appendChild(swatchElement);
- swatch = swatchElement;
+ function processColor(text)
+ {
+ try {
+ var color = new WebInspector.Color(text);
+ } catch (e) {
+ return document.createTextNode(text);
}
- }
- // Rotate through Color Representations by Clicking on the Swatch
- // Simple: rgb -> hsl -> nickname? -> shorthex? -> hex -> ...
- // Advanced: rgba -> hsla -> nickname? -> ...
- if (colors && colors.length === 1) {
- var color = new WebInspector.Color(htmlValue);
- swatch.addEventListener("click", changeColorDisplay, false);
- swatch.addEventListener("dblclick", function(event) {
- event.stopPropagation();
- }, false);
-
- var mode = color.mode;
- var valueElement = this.valueElement;
- function changeColorDisplay(event) {
-
- function changeTo(newMode, content) {
- mode = newMode;
- valueElement.textContent = content;
- }
+ var swatchElement = document.createElement("span");
+ swatchElement.title = WebInspector.UIString("Click to change color format");
+ swatchElement.className = "swatch";
+ swatchElement.style.setProperty("background-color", text);
+
+ swatchElement.addEventListener("click", changeColorDisplay, false);
+ swatchElement.addEventListener("dblclick", function(event) { event.stopPropagation() }, false);
+
+ var format;
+ if (Preferences.showColorNicknames && color.nickname)
+ format = "nickname";
+ else if (Preferences.colorFormat === "rgb")
+ format = (color.simple ? "rgb" : "rgba");
+ else if (Preferences.colorFormat === "hsl")
+ format = (color.simple ? "hsl" : "hsla");
+ else if (color.simple)
+ format = (color.hasShortHex() ? "shorthex" : "hex");
+ else
+ format = "rgba";
- switch (mode) {
+ var colorValueElement = document.createElement("span");
+ colorValueElement.textContent = color.toString(format);
+
+ function changeColorDisplay(event)
+ {
+ switch (format) {
case "rgb":
- changeTo("hsl", color.toHsl());
+ format = "hsl";
break;
case "shorthex":
- changeTo("hex", color.toHex());
+ format = "hex";
break;
case "hex":
- changeTo("rgb", color.toRgb());
+ format = "rgb";
break;
case "nickname":
if (color.simple) {
if (color.hasShortHex())
- changeTo("shorthex", color.toShortHex());
+ format = "shorthex";
else
- changeTo("hex", color.toHex());
- } else
- changeTo("rgba", color.toRgba());
+ format = "hex";
+ break;
+ }
+
+ format = "rgba";
break;
case "hsl":
if (color.nickname)
- changeTo("nickname", color.toNickname());
+ format = "nickname";
else if (color.hasShortHex())
- changeTo("shorthex", color.toShortHex());
+ format = "shorthex";
else
- changeTo("hex", color.toHex());
+ format = "hex";
break;
case "rgba":
- changeTo("hsla", color.toHsla());
+ format = "hsla";
break;
case "hsla":
if (color.nickname)
- changeTo("nickname", color.toNickname());
+ format = "nickname";
else
- changeTo("rgba", color.toRgba());
+ format = "rgba";
break;
}
+
+ colorValueElement.textContent = color.toString(format);
}
+
+ var container = document.createDocumentFragment();
+ container.appendChild(swatchElement);
+ container.appendChild(colorValueElement);
+ return container;
}
+
+ var colorRegex = /((?:rgb|hsl)a?\([^)]+\)|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3}|\b\w+\b)/g;
+ var colorProcessor = processValue.bind(window, colorRegex, processColor, null);
+
+ valueElement.appendChild(processValue(/url\(([^)]+)\)/g, linkifyURL, colorProcessor, value));
+ }
+
+ if (priority) {
+ var priorityElement = document.createElement("span");
+ priorityElement.className = "priority";
+ priorityElement.textContent = priority;
+ }
+
+ this.listItemElement.removeChildren();
+
+ // Append the checkbox for root elements of an editable section.
+ if (this.treeOutline.section && this.treeOutline.section.editable && this.parent.root)
+ this.listItemElement.appendChild(enabledCheckboxElement);
+ this.listItemElement.appendChild(nameElement);
+ this.listItemElement.appendChild(document.createTextNode(": "));
+ this.listItemElement.appendChild(valueElement);
+
+ if (priorityElement) {
+ this.listItemElement.appendChild(document.createTextNode(" "));
+ this.listItemElement.appendChild(priorityElement);
}
- this.tooltip = this.name + ": " + (valueNicknames[value] || value) + (priority ? " " + priority : "");
+ this.listItemElement.appendChild(document.createTextNode(";"));
+
+ this.tooltip = this.name + ": " + valueElement.textContent + (priority ? " " + priority : "");
},
updateAll: function(updateAllRules)
@@ -976,7 +1019,8 @@ WebInspector.StylePropertyTreeElement.prototype = {
var disabled = !event.target.checked;
var self = this;
- var callback = function(newPayload) {
+ function callback(newPayload)
+ {
if (!newPayload)
return;
@@ -991,8 +1035,9 @@ WebInspector.StylePropertyTreeElement.prototype = {
self.treeOutline.section.pane.dispatchEventToListeners("style property toggled");
self.updateAll(true);
- };
- InspectorController.toggleStyleEnabled(this.style._id, this.name, disabled, callback);
+ }
+
+ InjectedScriptAccess.toggleStyleEnabled(this.style.id, this.name, disabled, callback);
},
updateState: function()
@@ -1155,7 +1200,7 @@ WebInspector.StylePropertyTreeElement.prototype = {
} else {
// Restore the original CSS text before applying user changes. This is needed to prevent
// new properties from sticking around if the user adds one, then removes it.
- InspectorController.setStyleText(this.style, this.originalCSSText);
+ InjectedScriptAccess.setStyleText(this.style.id, this.originalCSSText);
}
this.applyStyleText(this.listItemElement.textContent);
@@ -1175,7 +1220,7 @@ WebInspector.StylePropertyTreeElement.prototype = {
if (this._newProperty)
this.treeOutline.removeChild(this);
else if (this.originalCSSText) {
- InspectorController.setStyleText(this.style, this.originalCSSText);
+ InjectedScriptAccess.setStyleText(this.style.id, this.originalCSSText);
if (this.treeOutline.section && this.treeOutline.section.pane)
this.treeOutline.section.pane.dispatchEventToListeners("style edited");
@@ -1210,7 +1255,8 @@ WebInspector.StylePropertyTreeElement.prototype = {
moveToNextCallback(this._newProperty, false, this.treeOutline.section, false);
// The Callback to start editing the next property
- function moveToNextCallback(alreadyNew, valueChanged, section) {
+ function moveToNextCallback(alreadyNew, valueChanged, section)
+ {
if (!moveDirection)
return;
@@ -1249,21 +1295,19 @@ WebInspector.StylePropertyTreeElement.prototype = {
var section = this.treeOutline.section;
var elementsPanel = WebInspector.panels.elements;
var styleTextLength = styleText.trimWhitespace().length;
- if (!styleTextLength) {
- if (updateInterface) {
+ if (!styleTextLength && updateInterface) {
+ if (this._newProperty) {
// The user deleted everything, so remove the tree element and update.
- if (!this._newProperty)
- delete section._afterUpdate;
- if (section && section.pane)
- section.pane.update();
this.parent.removeChild(this);
- elementsPanel.removeStyleChange(section.identifier, this.style, this.name);
+ return;
+ } else {
+ delete section._afterUpdate;
}
- return;
}
var self = this;
- var callback = function(result) {
+ function callback(result)
+ {
if (!result) {
// The user typed something, but it didn't parse. Just abort and restore
// the original title for this property. If this was a new attribute and
@@ -1281,10 +1325,16 @@ WebInspector.StylePropertyTreeElement.prototype = {
var changedProperties = result[1];
elementsPanel.removeStyleChange(section.identifier, self.style, self.name);
- self.style = WebInspector.CSSStyleDeclaration.parseStyle(newPayload);
- for (var i = 0; i < changedProperties.length; ++i)
- elementsPanel.addStyleChange(section.identifier, self.style, changedProperties[i]);
- self._styleRule.style = self.style;
+ if (!styleTextLength) {
+ // Do remove ourselves from UI when the property removal is confirmed.
+ self.parent.removeChild(self);
+ } else {
+ self.style = WebInspector.CSSStyleDeclaration.parseStyle(newPayload);
+ for (var i = 0; i < changedProperties.length; ++i)
+ elementsPanel.addStyleChange(section.identifier, self.style, changedProperties[i]);
+ self._styleRule.style = self.style;
+ }
+
if (section && section.pane)
section.pane.dispatchEventToListeners("style edited");
@@ -1293,8 +1343,9 @@ WebInspector.StylePropertyTreeElement.prototype = {
if (!self.rule)
WebInspector.panels.elements.treeOutline.update();
- };
- InspectorController.applyStyleText(this.style._id, styleText.trimWhitespace(), this.name, callback);
+ }
+
+ InjectedScriptAccess.applyStyleText(this.style.id, styleText.trimWhitespace(), this.name, callback);
}
}
diff --git a/WebCore/inspector/front-end/SummaryBar.js b/WebCore/inspector/front-end/SummaryBar.js
new file mode 100644
index 0000000..bbf2b1a
--- /dev/null
+++ b/WebCore/inspector/front-end/SummaryBar.js
@@ -0,0 +1,364 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Anthony Ricaud <rik@webkit.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.SummaryBar = function(categories)
+{
+ this.categories = categories;
+
+ this.element = document.createElement("div");
+ this.element.className = "summary-bar";
+
+ this.graphElement = document.createElement("canvas");
+ this.graphElement.setAttribute("width", "450");
+ this.graphElement.setAttribute("height", "38");
+ this.graphElement.className = "summary-graph";
+ this.element.appendChild(this.graphElement);
+
+ this.legendElement = document.createElement("div");
+ this.legendElement.className = "summary-graph-legend";
+ this.element.appendChild(this.legendElement);
+}
+
+WebInspector.SummaryBar.prototype = {
+
+ get calculator() {
+ return this._calculator;
+ },
+
+ set calculator(x) {
+ this._calculator = x;
+ },
+
+ reset: function()
+ {
+ this.legendElement.removeChildren();
+ this._drawSummaryGraph();
+ },
+
+ update: function(data)
+ {
+ var graphInfo = this.calculator.computeSummaryValues(data);
+
+ var fillSegments = [];
+
+ this.legendElement.removeChildren();
+
+ for (var category in this.categories) {
+ var size = graphInfo.categoryValues[category];
+ if (!size)
+ continue;
+
+ var color = this.categories[category].color;
+ var colorString = "rgb(" + color.r + ", " + color.g + ", " + color.b + ")";
+
+ var fillSegment = {color: colorString, value: size};
+ fillSegments.push(fillSegment);
+
+ var legendLabel = this._makeLegendElement(this.categories[category].title, this.calculator.formatValue(size), colorString);
+ this.legendElement.appendChild(legendLabel);
+ }
+
+ if (graphInfo.total) {
+ var totalLegendLabel = this._makeLegendElement(WebInspector.UIString("Total"), this.calculator.formatValue(graphInfo.total));
+ totalLegendLabel.addStyleClass("total");
+ this.legendElement.appendChild(totalLegendLabel);
+ }
+
+ this._drawSummaryGraph(fillSegments);
+ },
+
+ _drawSwatch: function(canvas, color)
+ {
+ var ctx = canvas.getContext("2d");
+
+ function drawSwatchSquare() {
+ ctx.fillStyle = color;
+ ctx.fillRect(0, 0, 13, 13);
+
+ var gradient = ctx.createLinearGradient(0, 0, 13, 13);
+ gradient.addColorStop(0.0, "rgba(255, 255, 255, 0.2)");
+ gradient.addColorStop(1.0, "rgba(255, 255, 255, 0.0)");
+
+ ctx.fillStyle = gradient;
+ ctx.fillRect(0, 0, 13, 13);
+
+ gradient = ctx.createLinearGradient(13, 13, 0, 0);
+ gradient.addColorStop(0.0, "rgba(0, 0, 0, 0.2)");
+ gradient.addColorStop(1.0, "rgba(0, 0, 0, 0.0)");
+
+ ctx.fillStyle = gradient;
+ ctx.fillRect(0, 0, 13, 13);
+
+ ctx.strokeStyle = "rgba(0, 0, 0, 0.6)";
+ ctx.strokeRect(0.5, 0.5, 12, 12);
+ }
+
+ ctx.clearRect(0, 0, 13, 24);
+
+ drawSwatchSquare();
+
+ ctx.save();
+
+ ctx.translate(0, 25);
+ ctx.scale(1, -1);
+
+ drawSwatchSquare();
+
+ ctx.restore();
+
+ this._fadeOutRect(ctx, 0, 13, 13, 13, 0.5, 0.0);
+ },
+
+ _drawSummaryGraph: function(segments)
+ {
+ if (!segments || !segments.length) {
+ segments = [{color: "white", value: 1}];
+ this._showingEmptySummaryGraph = true;
+ } else
+ delete this._showingEmptySummaryGraph;
+
+ // Calculate the total of all segments.
+ var total = 0;
+ for (var i = 0; i < segments.length; ++i)
+ total += segments[i].value;
+
+ // Calculate the percentage of each segment, rounded to the nearest percent.
+ var percents = segments.map(function(s) { return Math.max(Math.round(100 * s.value / total), 1) });
+
+ // Calculate the total percentage.
+ var percentTotal = 0;
+ for (var i = 0; i < percents.length; ++i)
+ percentTotal += percents[i];
+
+ // Make sure our percentage total is not greater-than 100, it can be greater
+ // if we rounded up for a few segments.
+ while (percentTotal > 100) {
+ for (var i = 0; i < percents.length && percentTotal > 100; ++i) {
+ if (percents[i] > 1) {
+ --percents[i];
+ --percentTotal;
+ }
+ }
+ }
+
+ // Make sure our percentage total is not less-than 100, it can be less
+ // if we rounded down for a few segments.
+ while (percentTotal < 100) {
+ for (var i = 0; i < percents.length && percentTotal < 100; ++i) {
+ ++percents[i];
+ ++percentTotal;
+ }
+ }
+
+ var ctx = this.graphElement.getContext("2d");
+
+ var x = 0;
+ var y = 0;
+ var w = 450;
+ var h = 19;
+ var r = (h / 2);
+
+ function drawPillShadow()
+ {
+ // This draws a line with a shadow that is offset away from the line. The line is stroked
+ // twice with different X shadow offsets to give more feathered edges. Later we erase the
+ // line with destination-out 100% transparent black, leaving only the shadow. This only
+ // works if nothing has been drawn into the canvas yet.
+
+ ctx.beginPath();
+ ctx.moveTo(x + 4, y + h - 3 - 0.5);
+ ctx.lineTo(x + w - 4, y + h - 3 - 0.5);
+ ctx.closePath();
+
+ ctx.save();
+
+ ctx.shadowBlur = 2;
+ ctx.shadowColor = "rgba(0, 0, 0, 0.5)";
+ ctx.shadowOffsetX = 3;
+ ctx.shadowOffsetY = 5;
+
+ ctx.strokeStyle = "white";
+ ctx.lineWidth = 1;
+
+ ctx.stroke();
+
+ ctx.shadowOffsetX = -3;
+
+ ctx.stroke();
+
+ ctx.restore();
+
+ ctx.save();
+
+ ctx.globalCompositeOperation = "destination-out";
+ ctx.strokeStyle = "rgba(0, 0, 0, 1)";
+ ctx.lineWidth = 1;
+
+ ctx.stroke();
+
+ ctx.restore();
+ }
+
+ function drawPill()
+ {
+ // Make a rounded rect path.
+ ctx.beginPath();
+ ctx.moveTo(x, y + r);
+ ctx.lineTo(x, y + h - r);
+ ctx.quadraticCurveTo(x, y + h, x + r, y + h);
+ ctx.lineTo(x + w - r, y + h);
+ ctx.quadraticCurveTo(x + w, y + h, x + w, y + h - r);
+ ctx.lineTo(x + w, y + r);
+ ctx.quadraticCurveTo(x + w, y, x + w - r, y);
+ ctx.lineTo(x + r, y);
+ ctx.quadraticCurveTo(x, y, x, y + r);
+ ctx.closePath();
+
+ // Clip to the rounded rect path.
+ ctx.save();
+ ctx.clip();
+
+ // Fill the segments with the associated color.
+ var previousSegmentsWidth = 0;
+ for (var i = 0; i < segments.length; ++i) {
+ var segmentWidth = Math.round(w * percents[i] / 100);
+ ctx.fillStyle = segments[i].color;
+ ctx.fillRect(x + previousSegmentsWidth, y, segmentWidth, h);
+ previousSegmentsWidth += segmentWidth;
+ }
+
+ // Draw the segment divider lines.
+ ctx.lineWidth = 1;
+ for (var i = 1; i < 20; ++i) {
+ ctx.beginPath();
+ ctx.moveTo(x + (i * Math.round(w / 20)) + 0.5, y);
+ ctx.lineTo(x + (i * Math.round(w / 20)) + 0.5, y + h);
+ ctx.closePath();
+
+ ctx.strokeStyle = "rgba(0, 0, 0, 0.2)";
+ ctx.stroke();
+
+ ctx.beginPath();
+ ctx.moveTo(x + (i * Math.round(w / 20)) + 1.5, y);
+ ctx.lineTo(x + (i * Math.round(w / 20)) + 1.5, y + h);
+ ctx.closePath();
+
+ ctx.strokeStyle = "rgba(255, 255, 255, 0.2)";
+ ctx.stroke();
+ }
+
+ // Draw the pill shading.
+ var lightGradient = ctx.createLinearGradient(x, y, x, y + (h / 1.5));
+ lightGradient.addColorStop(0.0, "rgba(220, 220, 220, 0.6)");
+ lightGradient.addColorStop(0.4, "rgba(220, 220, 220, 0.2)");
+ lightGradient.addColorStop(1.0, "rgba(255, 255, 255, 0.0)");
+
+ var darkGradient = ctx.createLinearGradient(x, y + (h / 3), x, y + h);
+ darkGradient.addColorStop(0.0, "rgba(0, 0, 0, 0.0)");
+ darkGradient.addColorStop(0.8, "rgba(0, 0, 0, 0.2)");
+ darkGradient.addColorStop(1.0, "rgba(0, 0, 0, 0.5)");
+
+ ctx.fillStyle = darkGradient;
+ ctx.fillRect(x, y, w, h);
+
+ ctx.fillStyle = lightGradient;
+ ctx.fillRect(x, y, w, h);
+
+ ctx.restore();
+ }
+
+ ctx.clearRect(x, y, w, (h * 2));
+
+ drawPillShadow();
+ drawPill();
+
+ ctx.save();
+
+ ctx.translate(0, (h * 2) + 1);
+ ctx.scale(1, -1);
+
+ drawPill();
+
+ ctx.restore();
+
+ this._fadeOutRect(ctx, x, y + h + 1, w, h, 0.5, 0.0);
+ },
+
+ _fadeOutRect: function(ctx, x, y, w, h, a1, a2)
+ {
+ ctx.save();
+
+ var gradient = ctx.createLinearGradient(x, y, x, y + h);
+ gradient.addColorStop(0.0, "rgba(0, 0, 0, " + (1.0 - a1) + ")");
+ gradient.addColorStop(0.8, "rgba(0, 0, 0, " + (1.0 - a2) + ")");
+ gradient.addColorStop(1.0, "rgba(0, 0, 0, 1.0)");
+
+ ctx.globalCompositeOperation = "destination-out";
+
+ ctx.fillStyle = gradient;
+ ctx.fillRect(x, y, w, h);
+
+ ctx.restore();
+ },
+
+ _makeLegendElement: function(label, value, color)
+ {
+ var legendElement = document.createElement("label");
+ legendElement.className = "summary-graph-legend-item";
+
+ if (color) {
+ var swatch = document.createElement("canvas");
+ swatch.className = "summary-graph-legend-swatch";
+ swatch.setAttribute("width", "13");
+ swatch.setAttribute("height", "24");
+
+ legendElement.appendChild(swatch);
+
+ this._drawSwatch(swatch, color);
+ }
+
+ var labelElement = document.createElement("div");
+ labelElement.className = "summary-graph-legend-label";
+ legendElement.appendChild(labelElement);
+
+ var headerElement = document.createElement("div");
+ headerElement.className = "summary-graph-legend-header";
+ headerElement.textContent = label;
+ labelElement.appendChild(headerElement);
+
+ var valueElement = document.createElement("div");
+ valueElement.className = "summary-graph-legend-value";
+ valueElement.textContent = value;
+ labelElement.appendChild(valueElement);
+
+ return legendElement;
+ }
+}
+
+WebInspector.SummaryBar.prototype.__proto__ = WebInspector.Object.prototype;
diff --git a/WebCore/inspector/front-end/TextPrompt.js b/WebCore/inspector/front-end/TextPrompt.js
index 5ff774f..f73ab0d 100644
--- a/WebCore/inspector/front-end/TextPrompt.js
+++ b/WebCore/inspector/front-end/TextPrompt.js
@@ -252,7 +252,7 @@ WebInspector.TextPrompt.prototype = {
foundNextText = true;
}
- node = node.traverseNextNode(false, this.element);
+ node = node.traverseNextNode(this.element);
}
return true;
diff --git a/WebCore/inspector/front-end/TimelineAgent.js b/WebCore/inspector/front-end/TimelineAgent.js
new file mode 100644
index 0000000..6d18732
--- /dev/null
+++ b/WebCore/inspector/front-end/TimelineAgent.js
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.TimelineAgent = function() {
+ // Not implemented.
+}
+
+// Must be kept in sync with TimelineItem.h
+WebInspector.TimelineAgent.ItemType = {
+ DOMDispatch : 0,
+ Layout : 1,
+ RecalculateStyles : 2,
+ Paint : 3,
+ ParseHTML : 4
+};
+
+WebInspector.addItemToTimeline = function(record) {
+ // Not implemented.
+}
+
+WebInspector.timelineWasEnabled = function() {
+ // Not implemented.
+}
+
+WebInspector.timelineWasDisabled = function() {
+ // Not implemented.
+}
diff --git a/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js b/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js
new file mode 100644
index 0000000..96a20ab
--- /dev/null
+++ b/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) IBM Corp. 2009 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 IBM Corp. 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.WatchExpressionsSidebarPane = function()
+{
+ WebInspector.SidebarPane.call(this, WebInspector.UIString("Watch Expressions"));
+
+ this.section = new WebInspector.WatchExpressionsSection();
+
+ this.bodyElement.appendChild(this.section.element);
+
+ var addElement = document.createElement("button");
+ addElement.setAttribute("type", "button");
+ addElement.textContent = WebInspector.UIString("Add");
+ addElement.addEventListener("click", this.section.addExpression.bind(this.section), false);
+
+ var refreshElement = document.createElement("button");
+ refreshElement.setAttribute("type", "button");
+ refreshElement.textContent = WebInspector.UIString("Refresh");
+ refreshElement.addEventListener("click", this.section.update.bind(this.section), false);
+
+ var centerElement = document.createElement("div");
+ centerElement.addStyleClass("watch-expressions-buttons-container");
+ centerElement.appendChild(addElement);
+ centerElement.appendChild(refreshElement);
+ this.bodyElement.appendChild(centerElement);
+
+ this.expanded = this.section.loadSavedExpressions().length > 0;
+ this.onexpand = this.refreshExpressions.bind(this);
+}
+
+WebInspector.WatchExpressionsSidebarPane.prototype = {
+ refreshExpressions: function()
+ {
+ this.section.update();
+ }
+}
+
+WebInspector.WatchExpressionsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
+
+WebInspector.WatchExpressionsSection = function()
+{
+ WebInspector.ObjectPropertiesSection.call(this);
+
+ this.watchExpressions = this.loadSavedExpressions();
+
+ this.headerElement.className = "hidden";
+ this.editable = true;
+ this.expanded = true;
+ this.propertiesElement.addStyleClass("watch-expressions");
+
+ this._watchObjectGroupId = "watch-group";
+}
+
+WebInspector.WatchExpressionsSection.NewWatchExpression = "\xA0";
+
+WebInspector.WatchExpressionsSection.prototype = {
+ update: function()
+ {
+ function appendResult(expression, watchIndex, result, exception)
+ {
+ if (exception) {
+ // Exception results are not wrappers, but text messages.
+ result = WebInspector.ObjectProxy.wrapPrimitiveValue(result);
+ } else if (result.type === "string") {
+ // Evaluation result is intentionally not abbreviated. However, we'd like to distinguish between null and "null"
+ result.description = "\"" + result.description + "\"";
+ }
+
+ var property = new WebInspector.ObjectPropertyProxy(expression, result);
+ property.watchIndex = watchIndex;
+ property.isException = exception;
+
+ // For newly added, empty expressions, set description to "",
+ // since otherwise you get DOMWindow
+ if (property.name === WebInspector.WatchExpressionsSection.NewWatchExpression)
+ property.value.description = "";
+
+ // To clarify what's going on here:
+ // In the outer function, we calculate the number of properties
+ // that we're going to be updating, and set that in the
+ // propertyCount variable.
+ // In this function, we test to see when we are processing the
+ // last property, and then call the superclass's updateProperties()
+ // method to get all the properties refreshed at once.
+ properties.push(property);
+
+ if (properties.length == propertyCount)
+ this.updateProperties(properties, WebInspector.WatchExpressionTreeElement, WebInspector.WatchExpressionsSection.CompareProperties);
+ }
+
+ InspectorController.releaseWrapperObjectGroup(this._watchObjectGroupId)
+ var properties = [];
+
+ // Count the properties, so we known when to call this.updateProperties()
+ // in appendResult()
+ var propertyCount = 0;
+ for (var i = 0; i < this.watchExpressions.length; ++i) {
+ if (!this.watchExpressions[i])
+ continue;
+ ++propertyCount;
+ }
+
+ // Now process all the expressions, since we have the actual count,
+ // which is checked in the appendResult inner function.
+ for (var i = 0; i < this.watchExpressions.length; ++i) {
+ var expression = this.watchExpressions[i];
+ if (!expression)
+ continue;
+
+ WebInspector.console.evalInInspectedWindow("(" + expression + ")", this._watchObjectGroupId, appendResult.bind(this, expression, i));
+ }
+
+ // note this is setting the expansion of the tree, not the section;
+ // with no expressions, and expanded tree, we get some extra vertical
+ // white space
+ // FIXME: should change to use header buttons instead of the buttons
+ // at the bottom of the section, then we can add a "No Watch Expressions
+ // element when there are no watch expressions, and this issue should
+ // go away.
+ this.expanded = (propertyCount != 0);
+ },
+
+ addExpression: function()
+ {
+ this.watchExpressions.push(WebInspector.WatchExpressionsSection.NewWatchExpression);
+ this.update();
+
+ // After update(), the new empty expression to be edited
+ // will be in the tree, but we have to find it.
+ treeElement = this.findAddedTreeElement();
+ if (treeElement)
+ treeElement.startEditing();
+ },
+
+ updateExpression: function(element, value)
+ {
+ this.watchExpressions[element.property.watchIndex] = value;
+ this.saveExpressions();
+ this.update();
+ },
+
+ findAddedTreeElement: function()
+ {
+ var children = this.propertiesTreeOutline.children;
+ for (var i = 0; i < children.length; ++i)
+ if (children[i].property.name === WebInspector.WatchExpressionsSection.NewWatchExpression)
+ return children[i];
+ },
+
+ loadSavedExpressions: function()
+ {
+ var json = InspectorController.setting("watchExpressions");
+ if (!json)
+ return [];
+
+ try {
+ json = JSON.parse(json);
+ } catch(e) {
+ return [];
+ }
+
+ return json.expressions || [];
+ },
+
+ saveExpressions: function()
+ {
+ var toSave = [];
+ for (var i = 0; i < this.watchExpressions.length; i++)
+ if (this.watchExpressions[i])
+ toSave.push(this.watchExpressions[i]);
+
+ var json = JSON.stringify({expressions: toSave});
+ InspectorController.setSetting("watchExpressions", json);
+
+ return toSave.length;
+ }
+}
+
+WebInspector.WatchExpressionsSection.prototype.__proto__ = WebInspector.ObjectPropertiesSection.prototype;
+
+WebInspector.WatchExpressionsSection.CompareProperties = function(propertyA, propertyB)
+{
+ if (propertyA.watchIndex == propertyB.watchIndex)
+ return 0;
+ else if (propertyA.watchIndex < propertyB.watchIndex)
+ return -1;
+ else
+ return 1;
+}
+
+WebInspector.WatchExpressionTreeElement = function(property)
+{
+ WebInspector.ObjectPropertyTreeElement.call(this, property);
+}
+
+WebInspector.WatchExpressionTreeElement.prototype = {
+ update: function()
+ {
+ WebInspector.ObjectPropertyTreeElement.prototype.update.call(this);
+
+ if (this.property.isException)
+ this.valueElement.addStyleClass("watch-expressions-error-level");
+
+ var deleteButton = document.createElement("input");
+ deleteButton.type = "button";
+ deleteButton.title = WebInspector.UIString("Delete watch expression.");
+ deleteButton.addStyleClass("enabled-button");
+ deleteButton.addStyleClass("delete-button");
+ deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false);
+
+ this.listItemElement.insertBefore(deleteButton, this.listItemElement.firstChild);
+ },
+
+ _deleteButtonClicked: function()
+ {
+ this.treeOutline.section.updateExpression(this, null);
+ },
+
+ startEditing: function()
+ {
+ if (WebInspector.isBeingEdited(this.nameElement) || !this.treeOutline.section.editable)
+ return;
+
+ this.nameElement.textContent = this.property.name.trimWhitespace();
+
+ var context = { expanded: this.expanded };
+
+ // collapse temporarily, if required
+ this.hasChildren = false;
+
+ this.listItemElement.addStyleClass("editing-sub-part");
+
+ WebInspector.startEditing(this.nameElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context);
+ },
+
+ editingCancelled: function(element, context)
+ {
+ if (!this.nameElement.textContent)
+ this.treeOutline.section.updateExpression(this, null);
+
+ this.update();
+ this.editingEnded(context);
+ },
+
+ applyExpression: function(expression, updateInterface)
+ {
+ expression = expression.trimWhitespace();
+
+ if (!expression)
+ expression = null;
+
+ this.property.name = expression;
+ this.treeOutline.section.updateExpression(this, expression);
+ }
+}
+
+WebInspector.WatchExpressionTreeElement.prototype.__proto__ = WebInspector.ObjectPropertyTreeElement.prototype;
diff --git a/WebCore/inspector/front-end/WebKit.qrc b/WebCore/inspector/front-end/WebKit.qrc
index c39c95b..c0f282c 100644
--- a/WebCore/inspector/front-end/WebKit.qrc
+++ b/WebCore/inspector/front-end/WebKit.qrc
@@ -9,9 +9,9 @@
<file>ChangesView.js</file>
<file>Color.js</file>
<file>ConsoleView.js</file>
+ <file>CookieItemsView.js</file>
<file>Database.js</file>
<file>DatabaseQueryView.js</file>
- <file>DatabasesPanel.js</file>
<file>DatabaseTableView.js</file>
<file>DataGrid.js</file>
<file>DOMAgent.js</file>
@@ -21,9 +21,11 @@
<file>Drawer.js</file>
<file>ElementsPanel.js</file>
<file>ElementsTreeOutline.js</file>
+ <file>EventListenersSidebarPane.js</file>
<file>FontView.js</file>
<file>ImageView.js</file>
<file>InjectedScript.js</file>
+ <file>InjectedScriptAccess.js</file>
<file>inspector.js</file>
<file>KeyboardShortcut.js</file>
<file>MetricsSidebarPane.js</file>
@@ -33,6 +35,7 @@
<file>Panel.js</file>
<file>PanelEnablerView.js</file>
<file>Placard.js</file>
+ <file>Popup.js</file>
<file>ProfileDataGridTree.js</file>
<file>ProfilesPanel.js</file>
<file>ProfileView.js</file>
@@ -50,20 +53,26 @@
<file>SidebarTreeElement.js</file>
<file>SourceFrame.js</file>
<file>SourceView.js</file>
+ <file>StatusBarButton.js</file>
+ <file>StoragePanel.js</file>
<file>StylesSidebarPane.js</file>
+ <file>SummaryBar.js</file>
<file>TextPrompt.js</file>
+ <file>TimelineAgent.js</file>
<file>TopDownProfileDataGridTree.js</file>
<file>treeoutline.js</file>
<file>utilities.js</file>
<file>View.js</file>
+ <file>WatchExpressionsSidebarPane.js</file>
<file>inspector.css</file>
+ <file>inspectorSyntaxHighlight.css</file>
<file>Images/back.png</file>
<file>Images/checker.png</file>
<file>Images/clearConsoleButtonGlyph.png</file>
<file>Images/closeButtons.png</file>
<file>Images/consoleButtonGlyph.png</file>
+ <file>Images/cookie.png</file>
<file>Images/database.png</file>
- <file>Images/databasesIcon.png</file>
<file>Images/databaseTable.png</file>
<file>Images/debuggerContinue.png</file>
<file>Images/debuggerPause.png</file>
@@ -80,12 +89,12 @@
<file>Images/disclosureTriangleSmallRightDownWhite.png</file>
<file>Images/disclosureTriangleSmallRightWhite.png</file>
<file>Images/dockButtonGlyph.png</file>
- <file>Images/domStorage.png</file>
<file>Images/elementsIcon.png</file>
<file>Images/enableOutlineButtonGlyph.png</file>
<file>Images/enableSolidButtonGlyph.png</file>
<file>Images/errorIcon.png</file>
<file>Images/errorMediumIcon.png</file>
+ <file>Images/errorRedDot.png</file>
<file>Images/excludeButtonGlyph.png</file>
<file>Images/focusButtonGlyph.png</file>
<file>Images/forward.png</file>
@@ -96,11 +105,14 @@
<file>Images/goArrow.png</file>
<file>Images/graphLabelCalloutLeft.png</file>
<file>Images/graphLabelCalloutRight.png</file>
+ <file>Images/grayConnectorPoint.png</file>
<file>Images/largerResourcesButtonGlyph.png</file>
+ <file>Images/localStorage.png</file>
<file>Images/nodeSearchButtonGlyph.png</file>
<file>Images/paneBottomGrow.png</file>
<file>Images/paneBottomGrowActive.png</file>
<file>Images/paneGrowHandleLine.png</file>
+ <file>Images/paneSettingsButtons.png</file>
<file>Images/pauseOnExceptionButtonGlyph.png</file>
<file>Images/percentButtonGlyph.png</file>
<file>Images/profileGroupIcon.png</file>
@@ -134,6 +146,7 @@
<file>Images/segmentHoverEnd.png</file>
<file>Images/segmentSelected.png</file>
<file>Images/segmentSelectedEnd.png</file>
+ <file>Images/sessionStorage.png</file>
<file>Images/splitviewDimple.png</file>
<file>Images/splitviewDividerBackground.png</file>
<file>Images/statusbarBackground.png</file>
@@ -143,6 +156,8 @@
<file>Images/statusbarMenuButtonSelected.png</file>
<file>Images/statusbarResizerHorizontal.png</file>
<file>Images/statusbarResizerVertical.png</file>
+ <file>Images/storageIcon.png</file>
+ <file>Images/successGreenDot.png</file>
<file>Images/timelineHollowPillBlue.png</file>
<file>Images/timelineHollowPillGray.png</file>
<file>Images/timelineHollowPillGreen.png</file>
@@ -174,6 +189,8 @@
<file>Images/userInputResultIcon.png</file>
<file>Images/warningIcon.png</file>
<file>Images/warningMediumIcon.png</file>
+ <file>Images/warningOrangeDot.png</file>
<file>Images/warningsErrors.png</file>
+ <file>Images/whiteConnectorPoint.png</file>
</qresource>
</RCC>
diff --git a/WebCore/inspector/front-end/inspector.css b/WebCore/inspector/front-end/inspector.css
index 51d626a..3d7c99a 100644
--- a/WebCore/inspector/front-end/inspector.css
+++ b/WebCore/inspector/front-end/inspector.css
@@ -94,6 +94,10 @@ body.attached #toolbar {
padding-left: 0;
}
+body.attached.platform-qt #toolbar {
+ cursor: auto;
+}
+
body.attached.inactive #toolbar {
border-top: 1px solid rgb(64%, 64%, 64%);
}
@@ -199,15 +203,15 @@ body.attached #search-results-matches {
background-image: url(Images/scriptsIcon.png);
}
-.toolbar-item.databases .toolbar-icon {
- background-image: url(Images/databasesIcon.png);
+.toolbar-item.storage .toolbar-icon {
+ background-image: url(Images/storageIcon.png);
}
.toolbar-item.profiles .toolbar-icon {
background-image: url(Images/profilesIcon.png);
}
-#close-button {
+#close-button-left, #close-button-right {
width: 14px;
height: 14px;
background-image: url(Images/closeButtons.png);
@@ -217,15 +221,27 @@ body.attached #search-results-matches {
margin: 5px 0;
}
-#close-button:hover {
+#close-button-left:hover, #close-button-right:hover {
background-position: 14px 0;
}
-#close-button:active {
+#close-button-left:active, #close-button-right:active {
background-position: 28px 0;
}
-body.detached .toolbar-item.close {
+body.detached .toolbar-item.close-left, body.detached .toolbar-item.close-right {
+ display: none;
+}
+
+body.attached.platform-qt .toolbar-item.close-left, body.attached.platform-qt .toolbar-item.close-right {
+ display: none;
+}
+
+body.platform-mac-tiger .toolbar-item.close-right, body.platform-mac-leopard .toolbar-item.close-right {
+ display: none;
+}
+
+body:not(.platform-mac-tiger):not(.platform-mac-leopard) .toolbar-item.close-left {
display: none;
}
@@ -372,6 +388,10 @@ body.detached #dock-status-bar-item .glyph {
-webkit-mask-image: url(Images/dockButtonGlyph.png);
}
+body.platform-qt #dock-status-bar-item {
+ display: none
+}
+
#console-status-bar-item .glyph {
-webkit-mask-image: url(Images/consoleButtonGlyph.png);
}
@@ -543,7 +563,7 @@ body.drawer-visible #drawer {
padding-left: 6px;
}
-.repeated-message.console-error-level::before, .repeated-message.console-warning-level:before {
+.repeated-message.console-error-level::before, .repeated-message.console-warning-level:before, .repeated-message.console-debug-level:before {
visibility: hidden;
}
@@ -574,6 +594,14 @@ body.drawer-visible #drawer {
color: red;
}
+.console-debug-level .console-message-text {
+ color: blue;
+}
+
+.console-debug-level::before {
+ background-image: url(Images/searchSmallBrightBlue.png);
+}
+
.console-error-level::before {
background-image: url(Images/errorIcon.png);
}
@@ -773,6 +801,10 @@ body.drawer-visible #drawer {
margin-right: 100px;
}
+.resource-view-headers .outline-disclosure .raw-form-data {
+ white-space:pre-wrap;
+}
+
.resource-view .resource-view-content {
position: absolute;
top: 0;
@@ -830,7 +862,7 @@ body.drawer-visible #drawer {
-webkit-user-select: text;
}
-.resource-view.image img {
+.resource-view.image img.resource-image-view {
max-width: 100%;
max-height: 1000px;
background-image: url(Images/checker.png);
@@ -839,6 +871,14 @@ body.drawer-visible #drawer {
-webkit-user-drag: auto;
}
+.resource-url {
+ vertical-align: middle;
+}
+
+.resource-status-image {
+ vertical-align: middle;
+}
+
.resource-view.image .title {
text-align: center;
font-size: 13px;
@@ -1190,10 +1230,22 @@ body.inactive .placard.selected {
margin-top: 1px;
}
-.section:nth-last-of-type(1) {
+.section:nth-last-of-type(1), .event-bar:nth-last-of-type(1) {
margin-bottom: 1px;
}
+.watch-expressions-buttons-container {
+ text-align: center;
+}
+
+.event-bar:first-child {
+ margin-top: 1px;
+}
+
+.event-bar:nth-last-of-type(1) .header {
+ border-bottom: 1px solid rgb(163, 163, 163);
+}
+
.section .header {
padding: 2px 8px 4px 18px;
border-top: 1px solid rgb(145, 160, 192);
@@ -1225,7 +1277,7 @@ body.inactive .placard.selected {
content: url(Images/treeDownTriangleWhite.png);
}
-.section .header .title {
+.section .header .title, .event-bar .header .title {
color: white;
font-weight: bold;
word-wrap: break-word;
@@ -1236,11 +1288,11 @@ body.inactive .placard.selected {
font-style: italic;
}
-.section .header label {
+.section .header label, .event-bar .header label {
display: none;
}
-.section.expanded .header label {
+.section.expanded .header label, .event-bar.expanded .header label {
display: inline;
}
@@ -1253,7 +1305,7 @@ body.inactive .placard.selected {
vertical-align: 2px;
}
-.section .header .subtitle {
+.section .header .subtitle, .event-bar .header .subtitle {
float: right;
font-size: 10px;
margin-left: 5px;
@@ -1267,7 +1319,7 @@ body.inactive .placard.selected {
color: inherit;
}
-.section .properties {
+.section .properties, .event-bar .event-properties {
display: none;
margin: 0;
padding: 2px 6px 3px;
@@ -1284,11 +1336,11 @@ body.inactive .placard.selected {
opacity: 1.0;
}
-.section.expanded .properties {
+.section.expanded .properties, .event-bar.expanded .event-properties {
display: block;
}
-.section .properties li {
+.section .properties li, .event-properties li {
margin-left: 12px;
white-space: nowrap;
text-overflow: ellipsis;
@@ -1297,22 +1349,22 @@ body.inactive .placard.selected {
cursor: auto;
}
-.section .properties li.parent {
+.section .properties li.parent, .event-properties li.parent {
margin-left: 1px;
}
-.section .properties ol {
+.section .properties ol, .event-properties ol {
display: none;
margin: 0;
-webkit-padding-start: 12px;
list-style: none;
}
-.section .properties ol.expanded {
+.section .properties ol.expanded, .event-properties ol.expanded {
display: block;
}
-.section .properties li.parent::before {
+.section .properties li.parent::before, .event-properties li.parent::before {
content: url(Images/treeRightTriangleBlack.png);
opacity: 0.75;
float: left;
@@ -1324,16 +1376,79 @@ body.inactive .placard.selected {
cursor: default;
}
-.section .properties li.parent.expanded::before {
+.section .properties li.parent.expanded::before, .event-properties li.parent.expanded::before {
content: url(Images/treeDownTriangleBlack.png);
margin-top: 1px;
}
-.section .properties li .info {
+.section .properties li .info, .event-properties li .info {
padding-top: 4px;
padding-bottom: 3px;
}
+.section .event-bars {
+ display: none;
+}
+
+.section.expanded .event-bars {
+ display: block;
+}
+
+.event-bar {
+ position: relative;
+}
+
+.event-bar-connector {
+ position: absolute;
+ left: 75%;
+ bottom: -7px;
+ margin-left: -7px;
+ content: url(Images/grayConnectorPoint.png);
+ z-index: 3;
+}
+
+.event-bar.expanded .event-bar-connector {
+ content: url(Images/whiteConnectorPoint.png);
+}
+
+.event-bars .event-bar .header {
+ padding: 2px 8px 4px 18px;
+ border-top: 1px solid rgb(163, 163, 163);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(243, 243, 243)), to(rgb(207, 207, 207)));
+ min-height: 18px;
+ white-space: nowrap;
+ -webkit-background-origin: padding;
+ -webkit-background-clip: padding;
+}
+
+.event-bars .event-bar.expanded .header {
+ border-bottom: 1px solid rgb(163, 163, 163);
+}
+
+.event-bars .event-bar .header .title {
+ font-weight: bold;
+ color: #333;
+ text-shadow: white 0 1px 0;
+}
+
+.event-bars .event-bar .header .subtitle {
+ color: rgba(90, 90, 90, 0.742188);
+}
+
+.event-bars .event-bar .header::before {
+ position: absolute;
+ top: 4px;
+ left: 7px;
+ width: 8px;
+ height: 8px;
+ opacity: 0.75;
+ content: url(Images/treeRightTriangleBlack.png);
+}
+
+.event-bars .event-bar.expanded .header::before {
+ content: url(Images/treeDownTriangleBlack.png);
+}
+
.editing {
-webkit-user-select: text;
-webkit-box-shadow: rgba(0, 0, 0, .5) 3px 3px 4px;
@@ -1360,10 +1475,23 @@ body.inactive .placard.selected {
text-overflow: clip;
}
-li.editing .swatch, li.editing .enabled-button {
+li.editing .swatch, li.editing .enabled-button, li.editing-sub-part .delete-button {
display: none !important;
}
+.watch-expressions > li.editing-sub-part .name {
+ display: block;
+ width: 100%;
+}
+
+.watch-expressions > li.editing-sub-part .value, .watch-expressions > li.editing-sub-part .separator {
+ display: none;
+}
+
+.watch-expressions-error-level {
+ color: red;
+}
+
.section .properties li.editing-sub-part {
padding: 3px 6px 8px 18px;
margin: -3px -6px -8px -6px;
@@ -1397,11 +1525,22 @@ li.editing .swatch, li.editing .enabled-button {
z-index: 1;
}
+/* FIXME: need a better icon (comment in bug 27514) */
+.section .properties .delete-button {
+ width: 10px;
+ height: 10px;
+ background-image: url(Images/errorIcon.png);
+ background-position: 0 0;
+ background-color: transparent;
+ background-repeat: no-repeat;
+ border: 0 none transparent;
+}
+
.section:hover .properties .enabled-button {
display: block;
}
-.section .properties .name {
+.section .properties .name, .event-properties .name {
color: rgb(136, 19, 145);
}
@@ -1409,7 +1548,7 @@ li.editing .swatch, li.editing .enabled-button {
color: rgb(100, 100, 100);
}
-.section .properties .number {
+.section .properties .number, .event-properties .number {
color: blue;
}
@@ -1417,22 +1556,27 @@ li.editing .swatch, li.editing .enabled-button {
color: rgb(128, 0, 0);
}
-.section .properties .keyword {
+.section .properties .keyword, .event-properties .keyword {
color: rgb(136, 19, 79);
}
-.section .properties .color {
+.section .properties .color, .event-properties .color {
color: rgb(118, 15, 21);
}
.swatch {
display: inline-block;
vertical-align: baseline;
- margin-left: 4px;
+ margin-left: 1px;
+ margin-right: 2px;
margin-bottom: -1px;
width: 1em;
height: 1em;
- border: 1px solid rgb(180, 180, 180);
+ border: 1px solid rgba(128, 128, 128, 0.6);
+}
+
+.swatch:hover {
+ border: 1px solid rgba(64, 64, 64, 0.8);
}
.pane:not(.expanded) + .pane, .pane:first-of-type {
@@ -1473,6 +1617,34 @@ li.editing .swatch, li.editing .enabled-button {
content: url(Images/disclosureTriangleSmallDownBlack.png);
}
+.pane > .title > select {
+ display: none;
+ float: right;
+ width: 23px;
+ height: 17px;
+ color: transparent;
+ background-color: transparent;
+ border: none;
+ background-image: url(Images/paneSettingsButtons.png);
+ background-repeat: no-repeat;
+ margin: 1px 0 0 0;
+ padding: 0;
+ -webkit-border-radius: 0;
+ -webkit-appearance: none;
+}
+
+.pane.expanded:hover > .title > select {
+ display: inline-block;
+}
+
+.pane > .title > select:hover {
+ background-position: -23px 0px;
+}
+
+.pane > .title > select:active {
+ background-position: -46px 0px;
+}
+
.pane > .body {
position: relative;
display: none;
@@ -1622,8 +1794,16 @@ body.inactive .sidebar {
content: url(Images/databaseTable.png);
}
-.domstorage-sidebar-tree-item .icon {
- content: url(Images/domStorage.png);
+.domstorage-sidebar-tree-item.local-storage .icon {
+ content: url(Images/localStorage.png);
+}
+
+.domstorage-sidebar-tree-item.session-storage .icon {
+ content: url(Images/sessionStorage.png);
+}
+
+.cookie-sidebar-tree-item .icon {
+ content: url(Images/cookie.png);
}
#storage-views {
@@ -1785,6 +1965,14 @@ body.inactive .sidebar {
overflow: hidden;
}
+.data-grid .centered div {
+ text-align: center;
+}
+
+.data-grid .right div {
+ text-align: right;
+}
+
.data-grid th.sortable div {
position: relative;
}
@@ -2091,7 +2279,7 @@ button.enable-toggle-status-bar-item.toggled-on .glyph {
-webkit-mask-image: url(Images/enableSolidButtonGlyph.png);
}
-#scripts-pause-on-exceptions-status-bar-item .glyph {
+.scripts-pause-on-exceptions-status-bar-item .glyph {
-webkit-mask-image: url(Images/pauseOnExceptionButtonGlyph.png);
}
@@ -2209,7 +2397,7 @@ button.enable-toggle-status-bar-item.toggled-on .glyph {
overflow: auto;
}
-#resources-larger-resources-status-bar-item .glyph {
+.resources-larger-resources-status-bar-item .glyph {
-webkit-mask-image: url(Images/largerResourcesButtonGlyph.png);
}
@@ -2221,7 +2409,13 @@ button.enable-toggle-status-bar-item.toggled-on .glyph {
overflow: hidden;
}
-#resources-filter li {
+#console-filter {
+ height: 24px;
+ padding: 2px 10px 0;
+ overflow: hidden;
+}
+
+#resources-filter li, #console-filter li {
display: inline-block;
margin: 1px 1px 0 0;
padding: 0 6px 3px;
@@ -2236,7 +2430,17 @@ button.enable-toggle-status-bar-item.toggled-on .glyph {
text-shadow: rgba(255, 255, 255, 0.5) 1px 1px 0;
}
-#resources-filter li.selected, #resources-filter li:hover, #resources-filter li:active {
+#console-filter div.divider {
+ margin-left: 5px;
+ margin-right: 5px;
+ /* Only want a border-left here because border on both sides
+ made the divider too thick */
+ border-left: 1px solid gray;
+ display: inline;
+}
+
+#resources-filter li.selected, #resources-filter li:hover, #resources-filter li:active,
+#console-filter li.selected, #console-filter li:hover, #console-filter li:active {
color: white;
text-shadow: rgb(80, 80, 80) 1px 1px 1px;
background: rgba(20, 20, 20, 0.4);
@@ -2244,13 +2448,15 @@ button.enable-toggle-status-bar-item.toggled-on .glyph {
-webkit-box-shadow: 0 1px 0px rgba(255, 255, 255, 0.5);
}
-#resources-filter li:hover {
+#resources-filter li:hover,
+#console-filter li:hover {
background: rgba(20, 20, 20, 0.4);
border-color: transparent;
-webkit-box-shadow: none;
}
-#resources-filter li:active {
+#resources-filter li:active,
+#console-filter li:active {
background: rgba(20, 20, 20, 0.6);
}
@@ -2316,36 +2522,36 @@ button.enable-toggle-status-bar-item.toggled-on .glyph {
-webkit-background-clip: padding;
}
-#resources-graph-legend {
+.summary-graph-legend {
margin-top: -10px;
padding-left: 15px;
}
-.resources-graph-legend-item {
+.summary-graph-legend-item {
display: inline-block;
font-weight: bold;
margin-right: 15px;
vertical-align: top;
}
-.resources-graph-legend-item.total {
+.summary-graph-legend-item.total {
margin-left: 10px;
}
-.resources-graph-legend-label {
+.summary-graph-legend-label {
display: inline-block;
text-align: left;
}
-.resources-graph-legend-header {
+.summary-graph-legend-header {
font-size: 12px;
}
-.resources-graph-legend-value {
+.summary-graph-legend-value {
font-size: 10px;
}
-.resources-graph-legend-swatch {
+.summary-graph-legend-swatch {
vertical-align: top;
margin-top: 1px;
margin-right: 3px;
@@ -2380,6 +2586,24 @@ button.enable-toggle-status-bar-item.toggled-on .glyph {
background-color: rgba(0, 0, 0, 0.1);
}
+.resources-onload-divider {
+ position: absolute;
+ width: 2px;
+ top: 0;
+ bottom: 0;
+ z-index: 300;
+ background-color: rgba(255, 0, 0, 0.5);
+}
+
+.resources-ondomcontent-divider {
+ position: absolute;
+ width: 2px;
+ top: 0;
+ bottom: 0;
+ z-index: 300;
+ background-color: rgba(0, 0, 255, 0.5);
+}
+
.resources-divider.last {
background-color: transparent;
}
@@ -2477,6 +2701,16 @@ button.enable-toggle-status-bar-item.toggled-on .glyph {
display: list-item;
}
+.console-warning-level, .console-error-level, .console-log-level {
+ display: none;
+}
+
+.filter-all .console-warning-level, .filter-warnings .console-warning-level,
+.filter-all .console-error-level, .filter-errors .console-error-level,
+.filter-all .console-log-level, .filter-logs .console-log-level {
+ display: block;
+}
+
.resources-graph-bar.waiting {
opacity: 0.35;
}
@@ -2970,6 +3204,10 @@ body.inactive .sidebar-tree-item.selected {
content: url(Images/resourceDocumentIconSmall.png);
}
+.bubble.debug, .console-debug-level .bubble {
+ background-color: rgb(0, 0, 255) !important;
+}
+
.bubble.warning, .console-warning-level .bubble {
background-color: rgb(232, 164, 0) !important;
}
@@ -3093,16 +3331,21 @@ body.inactive .sidebar-tree-item.selected .bubble.search-matches {
button.enable-toggle-status-bar-item .glyph {
}
-#record-profile-status-bar-item .glyph {
+.record-profile-status-bar-item .glyph {
-webkit-mask-image: url(Images/recordButtonGlyph.png);
}
-#record-profile-status-bar-item.toggled-on .glyph {
+.record-profile-status-bar-item.toggled-on .glyph {
-webkit-mask-image: url(Images/recordToggledButtonGlyph.png);
- background-color: rgb(216, 0, 0);
+ background-color: rgb(216, 0, 0) !important;
}
-#node-search-status-bar-item .glyph {
+/* FIXME: should have its own glyph. */
+.heap-snapshot-status-bar-item .glyph {
+ -webkit-mask-image: url(Images/focusButtonGlyph.png);
+}
+
+.node-search-status-bar-item .glyph {
-webkit-mask-image: url(Images/nodeSearchButtonGlyph.png);
}
@@ -3136,12 +3379,8 @@ button.enable-toggle-status-bar-item .glyph {
margin-left: -1px;
}
-.refresh-storage-status-bar-item {
- background-image: url(Images/reloadButtons.png) !important;
-}
-
-.refresh-storage-status-bar-item:active {
- background-position: 32px 0;
+.refresh-storage-status-bar-item .glyph {
+ -webkit-mask-image: url(Images/reloadButtonGlyph.png);
}
#storage-view-status-bar-items {
@@ -3191,3 +3430,7 @@ ol.breakpoint-list {
.breakpoint-list a:hover {
color: rgb(15%, 15%, 15%);
}
+
+.webkit-html-js-node, .webkit-html-css-node {
+ white-space: pre;
+}
diff --git a/WebCore/inspector/front-end/inspector.html b/WebCore/inspector/front-end/inspector.html
index a3dc407..db9bfd7 100644
--- a/WebCore/inspector/front-end/inspector.html
+++ b/WebCore/inspector/front-end/inspector.html
@@ -6,13 +6,13 @@ modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
+ notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
+ documentation and/or other materials provided with the distribution.
3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
+ from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@@ -30,12 +30,14 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="inspector.css">
+ <link rel="stylesheet" type="text/css" href="inspectorSyntaxHighlight.css">
<script type="text/javascript" src="utilities.js"></script>
<script type="text/javascript" src="treeoutline.js"></script>
<script type="text/javascript" src="inspector.js"></script>
<script type="text/javascript" src="Object.js"></script>
<script type="text/javascript" src="KeyboardShortcut.js"></script>
<script type="text/javascript" src="TextPrompt.js"></script>
+ <script type="text/javascript" src="Popup.js"></script>
<script type="text/javascript" src="Placard.js"></script>
<script type="text/javascript" src="View.js"></script>
<script type="text/javascript" src="Callback.js"></script>
@@ -49,6 +51,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<script type="text/javascript" src="DOMStorageItemsView.js"></script>
<script type="text/javascript" src="DataGrid.js"></script>
<script type="text/javascript" src="DOMStorageDataGrid.js"></script>
+ <script type="text/javascript" src="CookieItemsView.js"></script>
<script type="text/javascript" src="Script.js"></script>
<script type="text/javascript" src="Breakpoint.js"></script>
<script type="text/javascript" src="SidebarPane.js"></script>
@@ -60,16 +63,20 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<script type="text/javascript" src="BreakpointsSidebarPane.js"></script>
<script type="text/javascript" src="CallStackSidebarPane.js"></script>
<script type="text/javascript" src="ScopeChainSidebarPane.js"></script>
+ <script type="text/javascript" src="WatchExpressionsSidebarPane.js"></script>
<script type="text/javascript" src="MetricsSidebarPane.js"></script>
<script type="text/javascript" src="PropertiesSidebarPane.js"></script>
+ <script type="text/javascript" src="EventListenersSidebarPane.js"></script>
<script type="text/javascript" src="Color.js"></script>
<script type="text/javascript" src="StylesSidebarPane.js"></script>
<script type="text/javascript" src="Panel.js"></script>
<script type="text/javascript" src="PanelEnablerView.js"></script>
+ <script type="text/javascript" src="StatusBarButton.js"></script>
+ <script type="text/javascript" src="SummaryBar.js"></script>
<script type="text/javascript" src="ElementsPanel.js"></script>
<script type="text/javascript" src="ResourcesPanel.js"></script>
<script type="text/javascript" src="ScriptsPanel.js"></script>
- <script type="text/javascript" src="DatabasesPanel.js"></script>
+ <script type="text/javascript" src="StoragePanel.js"></script>
<script type="text/javascript" src="ProfilesPanel.js"></script>
<script type="text/javascript" src="ResourceView.js"></script>
<script type="text/javascript" src="SourceFrame.js"></script>
@@ -85,13 +92,16 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<script type="text/javascript" src="ProfileView.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>
+ <script type="text/javascript" src="TimelineAgent.js"></script>
</head>
<body class="detached">
<div id="toolbar">
- <div class="toolbar-item close"><button id="close-button"></button></div>
+ <div class="toolbar-item close-left"><button id="close-button-left"></button></div>
<div class="toolbar-item flexable-space"></div>
<div class="toolbar-item hidden" id="search-results-matches"></div>
<div class="toolbar-item"><input id="search" type="search" incremental results="0"><div id="search-toolbar-label" class="toolbar-label"></div></div>
+ <div class="toolbar-item close-right"><button id="close-button-right"></button></div>
</div>
<div id="main">
<div id="main-panels" tabindex="0" spellcheck="false"></div>
@@ -99,7 +109,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</div>
<div id="drawer">
<div id="console-view"><div id="console-messages"><div id="console-prompt" spellcheck="false"><br></div></div></div>
- <div id="drawer-status-bar" class="status-bar"><div id="other-drawer-status-bar-items"><button id="clear-console-status-bar-item" class="status-bar-item"><div class="glyph"></div><div class="glyph shadow"></div></button></div></div>
+ <div id="drawer-status-bar" class="status-bar"><div id="other-drawer-status-bar-items"><button id="clear-console-status-bar-item" class="status-bar-item"><div class="glyph"></div><div class="glyph shadow"></div></button><div id="console-filter" class="status-bar-item"></div></div></div>
</div>
</body>
</html>
diff --git a/WebCore/inspector/front-end/inspector.js b/WebCore/inspector/front-end/inspector.js
index aa21a86..f090d3a 100644
--- a/WebCore/inspector/front-end/inspector.js
+++ b/WebCore/inspector/front-end/inspector.js
@@ -8,13 +8,13 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
+ * documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@@ -29,7 +29,6 @@
*/
var Preferences = {
- ignoreWhitespace: true,
showUserAgentStyles: true,
maxInlineTextChildLength: 80,
minConsoleHeight: 75,
@@ -39,7 +38,12 @@ var Preferences = {
showInheritedComputedStyleProperties: false,
styleRulesExpandedState: {},
showMissingLocalizedStrings: false,
- useDOMAgent: false
+ heapProfilerPresent: false,
+ samplingCPUProfiler: false,
+ showColorNicknames: true,
+ colorFormat: "hex",
+ eventListenersFilter: "all",
+ resourcesLargeRows: true
}
var WebInspector = {
@@ -70,7 +74,7 @@ var WebInspector = {
// there isn't already a caret selection inside.
var selection = window.getSelection();
if (selection.isCollapsed && !this._currentFocusElement.isInsertionCaretInside()) {
- var selectionRange = document.createRange();
+ var selectionRange = this._currentFocusElement.ownerDocument.createRange();
selectionRange.setStart(this._currentFocusElement, 0);
selectionRange.setEnd(this._currentFocusElement, 0);
@@ -119,13 +123,13 @@ var WebInspector = {
}
}
}
-
+
for (var panelName in WebInspector.panels) {
if (WebInspector.panels[panelName] == x)
InspectorController.storeLastActivePanel(panelName);
}
},
-
+
_createPanels: function()
{
var hiddenPanels = (InspectorController.hiddenPanels() || "").split(',');
@@ -137,8 +141,23 @@ var WebInspector = {
this.panels.scripts = new WebInspector.ScriptsPanel();
if (hiddenPanels.indexOf("profiles") === -1)
this.panels.profiles = new WebInspector.ProfilesPanel();
- if (hiddenPanels.indexOf("databases") === -1)
- this.panels.databases = new WebInspector.DatabasesPanel();
+ if (hiddenPanels.indexOf("storage") === -1 && hiddenPanels.indexOf("databases") === -1)
+ this.panels.storage = new WebInspector.StoragePanel();
+ },
+
+ _loadPreferences: function()
+ {
+ var colorFormat = InspectorController.setting("color-format");
+ if (colorFormat)
+ Preferences.colorFormat = colorFormat;
+
+ var eventListenersFilter = InspectorController.setting("event-listeners-filter");
+ if (eventListenersFilter)
+ Preferences.eventListenersFilter = eventListenersFilter;
+
+ var resourcesLargeRows = InspectorController.setting("resources-large-rows");
+ if (typeof resourcesLargeRows !== "undefined")
+ Preferences.resourcesLargeRows = resourcesLargeRows;
},
get attached()
@@ -307,7 +326,7 @@ var WebInspector = {
set hoveredDOMNode(x)
{
- if (objectsAreSame(this._hoveredDOMNode, x))
+ if (this._hoveredDOMNode === x)
return;
this._hoveredDOMNode = x;
@@ -333,7 +352,7 @@ var WebInspector = {
}
if (this._hoveredDOMNode) {
- InspectorController.highlightDOMNode(this._hoveredDOMNode);
+ InspectorController.highlightDOMNode(this._hoveredDOMNode.id);
this.showingDOMNodeHighlight = true;
} else {
InspectorController.hideDOMNodeHighlight();
@@ -347,15 +366,15 @@ WebInspector.loaded = function()
var platform = InspectorController.platform();
document.body.addStyleClass("platform-" + platform);
+ this._loadPreferences();
+
this.drawer = new WebInspector.Drawer();
this.console = new WebInspector.ConsoleView(this.drawer);
// TODO: Uncomment when enabling the Changes Panel
// this.changes = new WebInspector.ChangesView(this.drawer);
// TODO: Remove class="hidden" from inspector.html on button#changes-status-bar-item
this.drawer.visibleView = this.console;
-
- if (Preferences.useDOMAgent)
- this.domAgent = new WebInspector.DOMAgent();
+ this.domAgent = new WebInspector.DOMAgent();
this.resourceCategories = {
documents: new WebInspector.ResourceCategory(WebInspector.UIString("Documents"), "documents"),
@@ -404,6 +423,7 @@ WebInspector.loaded = function()
document.addEventListener("keyup", this.documentKeyUp.bind(this), true);
document.addEventListener("beforecopy", this.documentCanCopy.bind(this), true);
document.addEventListener("copy", this.documentCopy.bind(this), true);
+ document.addEventListener("contextmenu", this.contextMenu.bind(this), true);
var mainPanelsElement = document.getElementById("main-panels");
mainPanelsElement.handleKeyEvent = this.mainKeyDown.bind(this);
@@ -438,10 +458,11 @@ WebInspector.loaded = function()
searchField.addEventListener("keyup", this.searchKeyUp.bind(this), false);
searchField.addEventListener("search", this.performSearch.bind(this), false); // when the search is emptied
- document.getElementById("toolbar").addEventListener("mousedown", this.toolbarDragStart, true);
- document.getElementById("close-button").addEventListener("click", this.close, true);
+ toolbarElement.addEventListener("mousedown", this.toolbarDragStart, true);
+ document.getElementById("close-button-left").addEventListener("click", this.close, true);
+ document.getElementById("close-button-right").addEventListener("click", this.close, true);
- InspectorController.loaded(Preferences.useDOMAgent);
+ InspectorController.loaded();
}
var windowLoaded = function()
@@ -658,6 +679,12 @@ WebInspector.documentCopy = function(event)
WebInspector[this.currentFocusElement.id + "Copy"](event);
}
+WebInspector.contextMenu = function(event)
+{
+ if (event.handled || event.target.hasStyleClass("popup-glasspane"))
+ event.preventDefault();
+}
+
WebInspector.mainKeyDown = function(event)
{
if (this.currentPanel && this.currentPanel.handleKeyEvent)
@@ -772,7 +799,7 @@ WebInspector.toggleAttach = function()
WebInspector.toolbarDragStart = function(event)
{
- if (!WebInspector.attached && InspectorController.platform() !== "mac-leopard")
+ if ((!WebInspector.attached && InspectorController.platform() !== "mac-leopard") || InspectorController.platform() == "qt")
return;
var target = event.target;
@@ -822,7 +849,7 @@ WebInspector.toolbarDrag = function(event)
event.preventDefault();
}
-WebInspector.elementDragStart = function(element, dividerDrag, elementDragEnd, event, cursor)
+WebInspector.elementDragStart = function(element, dividerDrag, elementDragEnd, event, cursor)
{
if (this._elementDraggingEventListener || this._elementEndDraggingEventListener)
this.elementDragEnd(event);
@@ -853,12 +880,12 @@ WebInspector.elementDragEnd = function(event)
WebInspector.showConsole = function()
{
- this.drawer.visibleView = this.console;
+ this.drawer.showView(this.console);
}
WebInspector.showChanges = function()
{
- this.drawer.visibleView = this.changes;
+ this.drawer.showView(this.changes);
}
WebInspector.showElementsPanel = function()
@@ -881,9 +908,9 @@ WebInspector.showProfilesPanel = function()
this.currentPanel = this.panels.profiles;
}
-WebInspector.showDatabasesPanel = function()
+WebInspector.showStoragePanel = function()
{
- this.currentPanel = this.panels.databases;
+ this.currentPanel = this.panels.storage;
}
WebInspector.addResource = function(identifier, payload)
@@ -896,19 +923,36 @@ WebInspector.addResource = function(identifier, payload)
payload.lastPathComponent,
identifier,
payload.isMainResource,
- payload.cached);
+ payload.cached,
+ payload.requestMethod,
+ payload.requestFormData);
this.resources[identifier] = resource;
this.resourceURLMap[resource.url] = resource;
- if (resource.mainResource) {
+ if (resource.mainResource)
this.mainResource = resource;
- this.panels.elements.reset();
- }
if (this.panels.resources)
this.panels.resources.addResource(resource);
}
+WebInspector.clearConsoleMessages = function()
+{
+ WebInspector.console.clearMessages(false);
+}
+
+WebInspector.selectDatabase = function(o)
+{
+ WebInspector.showStoragePanel();
+ WebInspector.panels.storage.selectDatabase(o);
+}
+
+WebInspector.selectDOMStorage = function(o)
+{
+ WebInspector.showStoragePanel();
+ WebInspector.panels.storage.selectDOMStorage(o);
+}
+
WebInspector.updateResource = function(identifier, payload)
{
var resource = this.resources[identifier];
@@ -922,6 +966,8 @@ WebInspector.updateResource = function(identifier, payload)
resource.lastPathComponent = payload.lastPathComponent;
resource.requestHeaders = payload.requestHeaders;
resource.mainResource = payload.mainResource;
+ resource.requestMethod = payload.requestMethod;
+ resource.requestFormData = payload.requestFormData;
}
if (payload.didResponseChange) {
@@ -936,7 +982,7 @@ WebInspector.updateResource = function(identifier, payload)
if (payload.didTypeChange) {
resource.type = payload.type;
}
-
+
if (payload.didLengthChange) {
resource.contentLength = payload.contentLength;
}
@@ -953,6 +999,21 @@ WebInspector.updateResource = function(identifier, payload)
resource.responseReceivedTime = payload.responseReceivedTime;
if (payload.endTime)
resource.endTime = payload.endTime;
+
+ if (payload.loadEventTime) {
+ // This loadEventTime is for the main resource, and we want to show it
+ // for all resources on this page. This means we want to set it as a member
+ // of the resources panel instead of the individual resource.
+ if (this.panels.resources)
+ this.panels.resources.mainResourceLoadTime = payload.loadEventTime;
+ }
+
+ if (payload.domContentEventTime) {
+ // This domContentEventTime is for the main resource, so it should go in
+ // the resources panel for the same reasons as above.
+ if (this.panels.resources)
+ this.panels.resources.mainResourceDOMContentTime = payload.domContentEventTime;
+ }
}
}
@@ -973,20 +1034,30 @@ WebInspector.removeResource = function(identifier)
WebInspector.addDatabase = function(payload)
{
var database = new WebInspector.Database(
- payload.database,
+ payload.id,
payload.domain,
payload.name,
payload.version);
- this.panels.databases.addDatabase(database);
+ this.panels.storage.addDatabase(database);
+}
+
+WebInspector.addCookieDomain = function(domain)
+{
+ this.panels.storage.addCookieDomain(domain);
}
WebInspector.addDOMStorage = function(payload)
{
var domStorage = new WebInspector.DOMStorage(
- payload.domStorage,
+ payload.id,
payload.host,
payload.isLocalStorage);
- this.panels.databases.addDOMStorage(domStorage);
+ this.panels.storage.addDOMStorage(domStorage);
+}
+
+WebInspector.updateDOMStorage = function(storageId)
+{
+ this.panels.storage.updateDOMStorage(storageId);
}
WebInspector.resourceTrackingWasEnabled = function()
@@ -1034,9 +1105,9 @@ WebInspector.failedToParseScriptSource = function(sourceURL, source, startingLin
this.panels.scripts.addScript(null, sourceURL, source, startingLine, errorLine, errorMessage);
}
-WebInspector.pausedScript = function()
+WebInspector.pausedScript = function(callFrames)
{
- this.panels.scripts.debuggerPaused();
+ this.panels.scripts.debuggerPaused(callFrames);
}
WebInspector.resumedScript = function()
@@ -1073,17 +1144,18 @@ WebInspector.reset = function()
this.console.clearMessages();
}
-WebInspector.inspectedWindowCleared = function(inspectedWindow)
-{
- this.panels.elements.inspectedWindowCleared(inspectedWindow);
-}
-
WebInspector.resourceURLChanged = function(resource, oldURL)
{
delete this.resourceURLMap[oldURL];
this.resourceURLMap[resource.url] = resource;
}
+WebInspector.didCommitLoad = function()
+{
+ // Cleanup elements panel early on inspected page refresh.
+ WebInspector.setDocument(null);
+}
+
WebInspector.addMessageToConsole = function(payload)
{
var consoleMessage = new WebInspector.ConsoleMessage(
@@ -1098,6 +1170,90 @@ WebInspector.addMessageToConsole = function(payload)
this.console.addMessage(consoleMessage);
}
+WebInspector.log = function(message)
+{
+ // remember 'this' for setInterval() callback
+ var self = this;
+
+ // return indication if we can actually log a message
+ function isLogAvailable()
+ {
+ return WebInspector.ConsoleMessage && WebInspector.ObjectProxy && self.console;
+ }
+
+ // flush the queue of pending messages
+ function flushQueue()
+ {
+ var queued = WebInspector.log.queued;
+ if (!queued)
+ return;
+
+ for (var i = 0; i < queued.length; ++i)
+ logMessage(queued[i]);
+
+ delete WebInspector.log.queued;
+ }
+
+ // flush the queue if it console is available
+ // - this function is run on an interval
+ function flushQueueIfAvailable()
+ {
+ if (!isLogAvailable())
+ return;
+
+ clearInterval(WebInspector.log.interval);
+ delete WebInspector.log.interval;
+
+ flushQueue();
+ }
+
+ // actually log the message
+ function logMessage(message)
+ {
+ var repeatCount = 1;
+ if (message == WebInspector.log.lastMessage)
+ repeatCount = WebInspector.log.repeatCount + 1;
+
+ WebInspector.log.lastMessage = message;
+ WebInspector.log.repeatCount = repeatCount;
+
+ // ConsoleMessage expects a proxy object
+ message = new WebInspector.ObjectProxy(null, [], 0, message, false);
+
+ // post the message
+ var msg = new WebInspector.ConsoleMessage(
+ WebInspector.ConsoleMessage.MessageSource.Other,
+ WebInspector.ConsoleMessage.MessageType.Log,
+ WebInspector.ConsoleMessage.MessageLevel.Debug,
+ -1,
+ null,
+ null,
+ repeatCount,
+ message);
+
+ self.console.addMessage(msg);
+ }
+
+ // if we can't log the message, queue it
+ if (!isLogAvailable()) {
+ if (!WebInspector.log.queued)
+ WebInspector.log.queued = [];
+
+ WebInspector.log.queued.push(message);
+
+ if (!WebInspector.log.interval)
+ WebInspector.log.interval = setInterval(flushQueueIfAvailable, 1000);
+
+ return;
+ }
+
+ // flush the pending queue if any
+ flushQueue();
+
+ // log the message
+ logMessage(message);
+}
+
WebInspector.addProfile = function(profile)
{
this.panels.profiles.addProfile(profile);
@@ -1117,7 +1273,7 @@ WebInspector.drawLoadingPieChart = function(canvas, percent) {
var r = 7;
g.beginPath();
- g.arc(cx, cy, r, 0, Math.PI * 2, false);
+ g.arc(cx, cy, r, 0, Math.PI * 2, false);
g.closePath();
g.lineWidth = 1;
@@ -1131,15 +1287,16 @@ WebInspector.drawLoadingPieChart = function(canvas, percent) {
g.beginPath();
g.moveTo(cx, cy);
- g.arc(cx, cy, r, startangle, endangle, false);
+ g.arc(cx, cy, r, startangle, endangle, false);
g.closePath();
g.fillStyle = darkColor;
g.fill();
}
-WebInspector.updateFocusedNode = function(node)
+WebInspector.updateFocusedNode = function(nodeId)
{
+ var node = WebInspector.domAgent.nodeForId(nodeId);
if (!node)
// FIXME: Should we deselect if null is passed in?
return;
@@ -1247,7 +1404,7 @@ WebInspector.linkifyURLAsNode = function(url, linkText, classes, isExternal)
a.title = url;
a.target = "_blank";
a.textContent = linkText;
-
+
return a;
}
@@ -1329,6 +1486,11 @@ WebInspector.performSearch = function(event)
this.currentPanel.performSearch(query);
}
+WebInspector.addNodesToSearchResult = function(nodeIds)
+{
+ WebInspector.panels.elements.addNodesToSearchResult(nodeIds);
+}
+
WebInspector.updateSearchMatchesCount = function(matches, panel)
{
if (!panel)
@@ -1385,7 +1547,7 @@ WebInspector.startEditing = function(element, committedCallback, cancelledCallba
return;
element.__editing = true;
- var oldText = element.textContent;
+ var oldText = getContent(element);
var oldHandleKeyEvent = element.handleKeyEvent;
var moveDirection = "";
@@ -1399,6 +1561,13 @@ WebInspector.startEditing = function(element, committedCallback, cancelledCallba
editingCommitted.call(element);
}
+ function getContent(element) {
+ if (element.tagName === "INPUT" && element.type === "text")
+ return element.value;
+ else
+ return element.textContent;
+ }
+
function cleanUpAfterEditing() {
delete this.__editing;
@@ -1415,17 +1584,22 @@ WebInspector.startEditing = function(element, committedCallback, cancelledCallba
}
function editingCancelled() {
- this.innerText = oldText;
+ if (this.tagName === "INPUT" && this.type === "text")
+ this.value = oldText;
+ else
+ this.textContent = oldText;
cleanUpAfterEditing.call(this);
- cancelledCallback(this, context);
+ if (cancelledCallback)
+ cancelledCallback(this, context);
}
function editingCommitted() {
cleanUpAfterEditing.call(this);
- committedCallback(this, this.textContent, oldText, context, moveDirection);
+ if (committedCallback)
+ committedCallback(this, getContent(this), oldText, context, moveDirection);
}
element.handleKeyEvent = function(event) {
@@ -1456,6 +1630,11 @@ WebInspector._toolbarItemClicked = function(event)
this.currentPanel = toolbarItem.panel;
}
+WebInspector.evaluateForTestInFrontend = function(callId, script)
+{
+ InspectorController.didEvaluateForTestInFrontend(callId, JSON.stringify(window.eval(script)));
+}
+
// This table maps MIME types to the Resource.Types which are valid for them.
// The following line:
// "text/html": {0: 1},
diff --git a/WebCore/inspector/front-end/inspectorSyntaxHighlight.css b/WebCore/inspector/front-end/inspectorSyntaxHighlight.css
new file mode 100644
index 0000000..2cbb3c5
--- /dev/null
+++ b/WebCore/inspector/front-end/inspectorSyntaxHighlight.css
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2009 Apple 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:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+.webkit-css-comment {
+ color: rgb(0, 116, 0);
+}
+
+.webkit-css-string, .webkit-css-keyword, .webkit-css-unit {
+ color: rgb(7, 144, 154);
+}
+
+.webkit-css-number {
+ color: rgb(50, 0, 255);
+}
+
+.webkit-css-property, .webkit-css-at-rule {
+ color: rgb(200, 0, 0);
+}
+
+.webkit-css-url {
+ color: rgb(0, 0, 0);
+}
+
+.webkit-css-selector {
+ color: rgb(0, 0, 0);
+}
+
+.webkit-css-pseudo-class {
+ color: rgb(128, 128, 128);
+}
+
+.webkit-javascript-comment {
+ color: rgb(0, 116, 0);
+}
+
+.webkit-javascript-keyword {
+ color: rgb(170, 13, 145);
+}
+
+.webkit-javascript-number {
+ color: rgb(28, 0, 207);
+}
+
+.webkit-javascript-string, .webkit-javascript-regexp {
+ color: rgb(196, 26, 22);
+}
diff --git a/WebCore/inspector/front-end/treeoutline.js b/WebCore/inspector/front-end/treeoutline.js
index 579e7fb..ecc322b 100644
--- a/WebCore/inspector/front-end/treeoutline.js
+++ b/WebCore/inspector/front-end/treeoutline.js
@@ -249,35 +249,40 @@ TreeOutline.prototype._forgetChildrenRecursive = function(parentElement)
}
}
-TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, getParent, equal)
+TreeOutline.prototype.getCachedTreeElement = function(representedObject)
{
if (!representedObject)
return null;
- if (!equal)
- equal = function(a, b) { return a === b };
-
if ("__treeElementIdentifier" in representedObject) {
// If this representedObject has a tree element identifier, and it is a known TreeElement
// in our tree we can just return that tree element.
var elements = this._knownTreeElements[representedObject.__treeElementIdentifier];
if (elements) {
for (var i = 0; i < elements.length; ++i)
- if (equal(elements[i].representedObject, representedObject))
+ if (elements[i].representedObject === representedObject)
return elements[i];
}
}
+ return null;
+}
- if (!isAncestor || !(isAncestor instanceof Function) || !getParent || !(getParent instanceof Function))
+TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, getParent)
+{
+ if (!representedObject)
return null;
+ var cachedElement = this.getCachedTreeElement(representedObject);
+ if (cachedElement)
+ return cachedElement;
+
// The representedObject isn't know, so we start at the top of the tree and work down to find the first
// tree element that represents representedObject or one of its ancestors.
var item;
var found = false;
for (var i = 0; i < this.children.length; ++i) {
item = this.children[i];
- if (equal(item.representedObject, representedObject) || isAncestor(item.representedObject, representedObject)) {
+ if (item.representedObject === representedObject || isAncestor(item.representedObject, representedObject)) {
found = true;
break;
}
@@ -292,7 +297,7 @@ TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor,
var currentObject = representedObject;
while (currentObject) {
ancestors.unshift(currentObject);
- if (equal(currentObject, item.representedObject))
+ if (currentObject === item.representedObject)
break;
currentObject = getParent(currentObject);
}
@@ -301,18 +306,16 @@ TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor,
for (var i = 0; i < ancestors.length; ++i) {
// Make sure we don't call findTreeElement with the same representedObject
// again, to prevent infinite recursion.
- if (equal(ancestors[i], representedObject))
+ if (ancestors[i] === representedObject)
continue;
// FIXME: we could do something faster than findTreeElement since we will know the next
// ancestor exists in the tree.
- item = this.findTreeElement(ancestors[i], isAncestor, getParent, equal);
+ item = this.findTreeElement(ancestors[i], isAncestor, getParent);
if (item && item.onpopulate)
item.onpopulate(item);
}
- // Now that all the ancestors are populated, try to find the representedObject again. This time
- // without the isAncestor and getParent functions to prevent an infinite recursion if it isn't found.
- return this.findTreeElement(representedObject, null, null, equal);
+ return this.getCachedTreeElement(representedObject);
}
TreeOutline.prototype.treeElementFromPoint = function(x, y)
diff --git a/WebCore/inspector/front-end/utilities.js b/WebCore/inspector/front-end/utilities.js
index eec0b87..6df23de 100644
--- a/WebCore/inspector/front-end/utilities.js
+++ b/WebCore/inspector/front-end/utilities.js
@@ -26,72 +26,16 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-Object.type = function(obj, win)
+Object.proxyType = function(objectProxy)
{
- if (obj === null)
+ if (objectProxy === null)
return "null";
- var type = typeof obj;
+ var type = typeof objectProxy;
if (type !== "object" && type !== "function")
return type;
- win = win || window;
-
- if (obj instanceof win.Node)
- return (obj.nodeType === undefined ? type : "node");
- if (obj instanceof win.String)
- return "string";
- if (obj instanceof win.Array)
- return "array";
- if (obj instanceof win.Boolean)
- return "boolean";
- if (obj instanceof win.Number)
- return "number";
- if (obj instanceof win.Date)
- return "date";
- if (obj instanceof win.RegExp)
- return "regexp";
- if (obj instanceof win.Error)
- return "error";
- return type;
-}
-
-Object.hasProperties = function(obj)
-{
- if (typeof obj === "undefined" || typeof obj === "null")
- return false;
- for (var name in obj)
- return true;
- return false;
-}
-
-Object.describe = function(obj, abbreviated)
-{
- var type1 = Object.type(obj);
- var type2 = Object.prototype.toString.call(obj).replace(/^\[object (.*)\]$/i, "$1");
-
- switch (type1) {
- case "object":
- case "node":
- return type2;
- case "array":
- return "[" + obj.toString() + "]";
- case "string":
- if (obj.length > 100)
- return "\"" + obj.substring(0, 100) + "\u2026\"";
- return "\"" + obj + "\"";
- case "function":
- var objectText = String(obj);
- if (!/^function /.test(objectText))
- objectText = (type2 == "object") ? type1 : type2;
- else if (abbreviated)
- objectText = /.*/.exec(obj)[0].replace(/ +$/g, "");
- return objectText;
- case "regexp":
- return String(obj).replace(/([\\\/])/g, "\\$1").replace(/\\(\/[gim]*)$/, "$1").substring(1);
- default:
- return String(obj);
- }
+ return objectProxy.type;
}
Object.properties = function(obj)
@@ -147,7 +91,7 @@ Node.prototype.rangeOfWord = function(offset, stopCharacters, stayWithinNode, di
if (startNode)
break;
- node = node.traversePreviousNode(false, stayWithinNode);
+ node = node.traversePreviousNode(stayWithinNode);
}
if (!startNode) {
@@ -182,7 +126,7 @@ Node.prototype.rangeOfWord = function(offset, stopCharacters, stayWithinNode, di
if (endNode)
break;
- node = node.traverseNextNode(false, stayWithinNode);
+ node = node.traverseNextNode(stayWithinNode);
}
if (!endNode) {
@@ -236,9 +180,15 @@ Element.prototype.hasStyleClass = function(className)
return regex.test(this.className);
}
+Element.prototype.positionAt = function(x, y)
+{
+ this.style.left = x + "px";
+ this.style.top = y + "px";
+}
+
Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = function(nameArray)
{
- for (var node = this; node && !objectsAreSame(node, this.ownerDocument); node = node.parentNode)
+ for (var node = this; node && node !== this.ownerDocument; node = node.parentNode)
for (var i = 0; i < nameArray.length; ++i)
if (node.nodeName.toLowerCase() === nameArray[i].toLowerCase())
return node;
@@ -252,7 +202,7 @@ Node.prototype.enclosingNodeOrSelfWithNodeName = function(nodeName)
Node.prototype.enclosingNodeOrSelfWithClass = function(className)
{
- for (var node = this; node && !objectsAreSame(node, this.ownerDocument); node = node.parentNode)
+ for (var node = this; node && node !== this.ownerDocument; node = node.parentNode)
if (node.nodeType === Node.ELEMENT_NODE && node.hasStyleClass(className))
return node;
return null;
@@ -301,18 +251,31 @@ Element.prototype.__defineGetter__("totalOffsetTop", function()
return total;
});
-Element.prototype.firstChildSkippingWhitespace = firstChildSkippingWhitespace;
-Element.prototype.lastChildSkippingWhitespace = lastChildSkippingWhitespace;
+Element.prototype.offsetRelativeToWindow = function(targetWindow)
+{
+ var elementOffset = {x: 0, y: 0};
+ var curElement = this;
+ var curWindow = this.ownerDocument.defaultView;
+ while (curWindow && curElement) {
+ elementOffset.x += curElement.totalOffsetLeft;
+ elementOffset.y += curElement.totalOffsetTop;
+ if (curWindow === targetWindow)
+ break;
+
+ curElement = curWindow.frameElement;
+ curWindow = curWindow.parent;
+ }
+
+ return elementOffset;
+}
Node.prototype.isWhitespace = isNodeWhitespace;
-Node.prototype.nodeTypeName = nodeTypeName;
Node.prototype.displayName = nodeDisplayName;
-Node.prototype.contentPreview = nodeContentPreview;
-Node.prototype.isAncestor = isAncestorNode;
+Node.prototype.isAncestor = function(node)
+{
+ return isAncestorNode(this, node);
+};
Node.prototype.isDescendant = isDescendantNode;
-Node.prototype.firstCommonAncestor = firstCommonNodeAncestor;
-Node.prototype.nextSiblingSkippingWhitespace = nextSiblingSkippingWhitespace;
-Node.prototype.previousSiblingSkippingWhitespace = previousSiblingSkippingWhitespace;
Node.prototype.traverseNextNode = traverseNextNode;
Node.prototype.traversePreviousNode = traversePreviousNode;
Node.prototype.onlyTextChild = onlyTextChild;
@@ -394,29 +357,6 @@ function isNodeWhitespace()
return this.nodeValue.match(/^[\s\xA0]+$/);
}
-function nodeTypeName()
-{
- if (!this)
- return "(unknown)";
-
- switch (this.nodeType) {
- case Node.ELEMENT_NODE: return "Element";
- case Node.ATTRIBUTE_NODE: return "Attribute";
- case Node.TEXT_NODE: return "Text";
- case Node.CDATA_SECTION_NODE: return "Character Data";
- case Node.ENTITY_REFERENCE_NODE: return "Entity Reference";
- case Node.ENTITY_NODE: return "Entity";
- case Node.PROCESSING_INSTRUCTION_NODE: return "Processing Instruction";
- case Node.COMMENT_NODE: return "Comment";
- case Node.DOCUMENT_NODE: return "Document";
- case Node.DOCUMENT_TYPE_NODE: return "Document Type";
- case Node.DOCUMENT_FRAGMENT_NODE: return "Document Fragment";
- case Node.NOTATION_NODE: return "Notation";
- }
-
- return "(unknown)";
-}
-
function nodeDisplayName()
{
if (!this)
@@ -491,277 +431,110 @@ function nodeDisplayName()
return this.nodeName.toLowerCase().collapseWhitespace();
}
-function nodeContentPreview()
+function isAncestorNode(ancestor, node)
{
- if (!this || !this.hasChildNodes || !this.hasChildNodes())
- return "";
-
- var limit = 0;
- var preview = "";
-
- // always skip whitespace here
- var currentNode = traverseNextNode.call(this, true, this);
- while (currentNode) {
- if (currentNode.nodeType === Node.TEXT_NODE)
- preview += currentNode.nodeValue.escapeHTML();
- else
- preview += nodeDisplayName.call(currentNode).escapeHTML();
-
- currentNode = traverseNextNode.call(currentNode, true, this);
-
- if (++limit > 4) {
- preview += "&#x2026;"; // ellipsis
- break;
- }
- }
-
- return preview.collapseWhitespace();
-}
-
-function objectsAreSame(a, b)
-{
- // FIXME: Make this more generic so is works with any wrapped object, not just nodes.
- // This function is used to compare nodes that might be JSInspectedObjectWrappers, since
- // JavaScript equality is not true for JSInspectedObjectWrappers of the same node wrapped
- // with different global ExecStates, we use isSameNode to compare them.
- if (a === b)
- return true;
- if (!a || !b)
- return false;
- if (a.isSameNode && b.isSameNode)
- return a.isSameNode(b);
- return false;
-}
-
-function isAncestorNode(ancestor)
-{
- if (!this || !ancestor)
+ if (!node || !ancestor)
return false;
- var currentNode = ancestor.parentNode;
+ var currentNode = node.parentNode;
while (currentNode) {
- if (objectsAreSame(this, currentNode))
+ if (ancestor === currentNode)
return true;
currentNode = currentNode.parentNode;
}
-
return false;
}
function isDescendantNode(descendant)
{
- return isAncestorNode.call(descendant, this);
-}
-
-function firstCommonNodeAncestor(node)
-{
- if (!this || !node)
- return;
-
- var node1 = this.parentNode;
- var node2 = node.parentNode;
-
- if ((!node1 || !node2) || !objectsAreSame(node1, node2))
- return null;
-
- while (node1 && node2) {
- if (!node1.parentNode || !node2.parentNode)
- break;
- if (!objectsAreSame(node1, node2))
- break;
-
- node1 = node1.parentNode;
- node2 = node2.parentNode;
- }
-
- return node1;
-}
-
-function nextSiblingSkippingWhitespace()
-{
- if (!this)
- return;
- var node = this.nextSibling;
- while (node && node.nodeType === Node.TEXT_NODE && isNodeWhitespace.call(node))
- node = node.nextSibling;
- return node;
+ return isAncestorNode(descendant, this);
}
-function previousSiblingSkippingWhitespace()
+function traverseNextNode(stayWithin)
{
if (!this)
return;
- var node = this.previousSibling;
- while (node && node.nodeType === Node.TEXT_NODE && isNodeWhitespace.call(node))
- node = node.previousSibling;
- return node;
-}
-function firstChildSkippingWhitespace()
-{
- if (!this)
- return;
var node = this.firstChild;
- while (node && node.nodeType === Node.TEXT_NODE && isNodeWhitespace.call(node))
- node = nextSiblingSkippingWhitespace.call(node);
- return node;
-}
-
-function lastChildSkippingWhitespace()
-{
- if (!this)
- return;
- var node = this.lastChild;
- while (node && node.nodeType === Node.TEXT_NODE && isNodeWhitespace.call(node))
- node = previousSiblingSkippingWhitespace.call(node);
- return node;
-}
-
-function traverseNextNode(skipWhitespace, stayWithin)
-{
- if (!this)
- return;
-
- var node = skipWhitespace ? firstChildSkippingWhitespace.call(this) : this.firstChild;
if (node)
return node;
- if (stayWithin && objectsAreSame(this, stayWithin))
+ if (stayWithin && this === stayWithin)
return null;
- node = skipWhitespace ? nextSiblingSkippingWhitespace.call(this) : this.nextSibling;
+ node = this.nextSibling;
if (node)
return node;
node = this;
- while (node && !(skipWhitespace ? nextSiblingSkippingWhitespace.call(node) : node.nextSibling) && (!stayWithin || !node.parentNode || !objectsAreSame(node.parentNode, stayWithin)))
+ while (node && !node.nextSibling && (!stayWithin || !node.parentNode || node.parentNode !== stayWithin))
node = node.parentNode;
if (!node)
return null;
- return skipWhitespace ? nextSiblingSkippingWhitespace.call(node) : node.nextSibling;
+ return node.nextSibling;
}
-function traversePreviousNode(skipWhitespace, stayWithin)
+function traversePreviousNode(stayWithin)
{
if (!this)
return;
- if (stayWithin && objectsAreSame(this, stayWithin))
+ if (stayWithin && this === stayWithin)
return null;
- var node = skipWhitespace ? previousSiblingSkippingWhitespace.call(this) : this.previousSibling;
- while (node && (skipWhitespace ? lastChildSkippingWhitespace.call(node) : node.lastChild) )
- node = skipWhitespace ? lastChildSkippingWhitespace.call(node) : node.lastChild;
+ var node = this.previousSibling;
+ while (node && node.lastChild)
+ node = node.lastChild;
if (node)
return node;
return this.parentNode;
}
-function onlyTextChild(ignoreWhitespace)
+function onlyTextChild()
{
if (!this)
return null;
- var firstChild = ignoreWhitespace ? firstChildSkippingWhitespace.call(this) : this.firstChild;
+ var firstChild = this.firstChild;
if (!firstChild || firstChild.nodeType !== Node.TEXT_NODE)
return null;
- var sibling = ignoreWhitespace ? nextSiblingSkippingWhitespace.call(firstChild) : firstChild.nextSibling;
+ var sibling = firstChild.nextSibling;
return sibling ? null : firstChild;
}
-function nodeTitleInfo(hasChildren, linkify)
+function appropriateSelectorForNode(node, justSelector)
{
- var info = {title: "", hasChildren: hasChildren};
-
- switch (this.nodeType) {
- case Node.DOCUMENT_NODE:
- info.title = "Document";
- break;
-
- case Node.ELEMENT_NODE:
- info.title = "<span class=\"webkit-html-tag\">&lt;" + this.nodeName.toLowerCase().escapeHTML();
-
- if (this.hasAttributes()) {
- for (var i = 0; i < this.attributes.length; ++i) {
- var attr = this.attributes[i];
- info.title += " <span class=\"webkit-html-attribute\"><span class=\"webkit-html-attribute-name\">" + attr.name.escapeHTML() + "</span>=&#8203;\"";
-
- var value = attr.value;
- if (linkify && (attr.name === "src" || attr.name === "href")) {
- var value = value.replace(/([\/;:\)\]\}])/g, "$1\u200B");
- info.title += linkify(attr.value, value, "webkit-html-attribute-value", this.nodeName.toLowerCase() == "a");
- } else {
- var value = value.escapeHTML();
- value = value.replace(/([\/;:\)\]\}])/g, "$1&#8203;");
- info.title += "<span class=\"webkit-html-attribute-value\">" + value + "</span>";
- }
- info.title += "\"</span>";
- }
- }
- info.title += "&gt;</span>&#8203;";
-
- // If this element only has a single child that is a text node,
- // just show that text and the closing tag inline rather than
- // create a subtree for them
-
- var textChild = onlyTextChild.call(this, Preferences.ignoreWhitespace);
- var showInlineText = textChild && textChild.textContent.length < Preferences.maxInlineTextChildLength;
-
- if (showInlineText) {
- info.title += "<span class=\"webkit-html-text-node\">" + textChild.nodeValue.escapeHTML() + "</span>&#8203;<span class=\"webkit-html-tag\">&lt;/" + this.nodeName.toLowerCase().escapeHTML() + "&gt;</span>";
- info.hasChildren = false;
- }
- break;
+ if (!node)
+ return "";
- case Node.TEXT_NODE:
- if (isNodeWhitespace.call(this))
- info.title = "(whitespace)";
- else
- info.title = "\"<span class=\"webkit-html-text-node\">" + this.nodeValue.escapeHTML() + "</span>\"";
- break
+ var lowerCaseName = node.localName || node.nodeName.toLowerCase();
- case Node.COMMENT_NODE:
- info.title = "<span class=\"webkit-html-comment\">&lt;!--" + this.nodeValue.escapeHTML() + "--&gt;</span>";
- break;
+ var id = node.getAttribute("id");
+ if (id) {
+ var selector = "#" + id;
+ return (justSelector ? selector : lowerCaseName + selector);
+ }
- case Node.DOCUMENT_TYPE_NODE:
- info.title = "<span class=\"webkit-html-doctype\">&lt;!DOCTYPE " + this.nodeName;
- if (this.publicId) {
- info.title += " PUBLIC \"" + this.publicId + "\"";
- if (this.systemId)
- info.title += " \"" + this.systemId + "\"";
- } else if (this.systemId)
- info.title += " SYSTEM \"" + this.systemId + "\"";
- if (this.internalSubset)
- info.title += " [" + this.internalSubset + "]";
- info.title += "&gt;</span>";
- break;
- default:
- info.title = this.nodeName.toLowerCase().collapseWhitespace().escapeHTML();
+ var className = node.getAttribute("class");
+ if (className) {
+ var selector = "." + className.replace(/\s+/, ".");
+ return (justSelector ? selector : lowerCaseName + selector);
}
- return info;
-}
+ if (lowerCaseName === "input" && node.getAttribute("type"))
+ return lowerCaseName + "[type=\"" + node.getAttribute("type") + "\"]";
-function getDocumentForNode(node) {
- return node.nodeType == Node.DOCUMENT_NODE ? node : node.ownerDocument;
+ return lowerCaseName;
}
-function parentNodeOrFrameElement(node) {
- var parent = node.parentNode;
- if (parent)
- return parent;
-
- return getDocumentForNode(node).defaultView.frameElement;
+function getDocumentForNode(node)
+{
+ return node.nodeType == Node.DOCUMENT_NODE ? node : node.ownerDocument;
}
-function isAncestorIncludingParentFrames(a, b) {
- if (objectsAreSame(a, b))
- return false;
- for (var node = b; node; node = getDocumentForNode(node).defaultView.frameElement)
- if (objectsAreSame(a, node) || isAncestorNode.call(a, node))
- return true;
- return false;
+function parentNode(node)
+{
+ return node.parentNode;
}
Number.secondsToString = function(seconds, formatterFunction, higherResolution)
@@ -790,20 +563,27 @@ Number.secondsToString = function(seconds, formatterFunction, higherResolution)
return formatterFunction("%.1f days", days);
}
-Number.bytesToString = function(bytes, formatterFunction)
+Number.bytesToString = function(bytes, formatterFunction, higherResolution)
{
if (!formatterFunction)
formatterFunction = String.sprintf;
+ if (typeof higherResolution === "undefined")
+ higherResolution = true;
if (bytes < 1024)
return formatterFunction("%.0fB", bytes);
var kilobytes = bytes / 1024;
- if (kilobytes < 1024)
+ if (higherResolution && kilobytes < 1024)
return formatterFunction("%.2fKB", kilobytes);
+ else if (kilobytes < 1024)
+ return formatterFunction("%.0fKB", kilobytes);
var megabytes = kilobytes / 1024;
- return formatterFunction("%.3fMB", megabytes);
+ if (higherResolution)
+ return formatterFunction("%.3fMB", megabytes);
+ else
+ return formatterFunction("%.0fMB", megabytes);
}
Number.constrain = function(num, min, max)
@@ -942,12 +722,16 @@ String.tokenizeFormatString = function(format)
String.standardFormatters = {
d: function(substitution)
{
+ if (typeof substitution == "object" && Object.proxyType(substitution) === "number")
+ substitution = substitution.description;
substitution = parseInt(substitution);
return !isNaN(substitution) ? substitution : 0;
},
f: function(substitution, token)
{
+ if (typeof substitution == "object" && Object.proxyType(substitution) === "number")
+ substitution = substitution.description;
substitution = parseFloat(substitution);
if (substitution && token.precision > -1)
substitution = substitution.toFixed(token.precision);
@@ -956,6 +740,8 @@ String.standardFormatters = {
s: function(substitution)
{
+ if (typeof substitution == "object" && Object.proxyType(substitution) !== "null")
+ substitution = substitution.description;
return substitution;
},
};