summaryrefslogtreecommitdiffstats
path: root/webkit/glue/devtools/js
diff options
context:
space:
mode:
authorpfeldman@chromium.org <pfeldman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-29 13:07:14 +0000
committerpfeldman@chromium.org <pfeldman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-29 13:07:14 +0000
commitf6a2f61481761768352fafff68faca28c9a73bd1 (patch)
treee3f2f3aaf7d0b37203215d23de8248cb42416ab8 /webkit/glue/devtools/js
parent251d1dbb34d1e365c78f81bac17ed71ec32cd6c5 (diff)
downloadchromium_src-f6a2f61481761768352fafff68faca28c9a73bd1.zip
chromium_src-f6a2f61481761768352fafff68faca28c9a73bd1.tar.gz
chromium_src-f6a2f61481761768352fafff68faca28c9a73bd1.tar.bz2
DevTools: Implement styles toggle:
1. Split inject.js into injected object and the dispatch. 2. Surround utility function call with try/catch, pass potential exception all way to the client. 3. Fix user and user agent scripts detection 4. Introduce toggleStyle 5. Remove __defineGetter__ from the styles code: make things simple 6. Beautify code. Review URL: http://codereview.chromium.org/99184 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@14839 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/glue/devtools/js')
-rw-r--r--webkit/glue/devtools/js/devtools.js17
-rw-r--r--webkit/glue/devtools/js/devtools_host_stub.js22
-rw-r--r--webkit/glue/devtools/js/dom_agent.js163
-rw-r--r--webkit/glue/devtools/js/inject.js440
-rw-r--r--webkit/glue/devtools/js/inject_dispatch.js33
5 files changed, 445 insertions, 230 deletions
diff --git a/webkit/glue/devtools/js/devtools.js b/webkit/glue/devtools/js/devtools.js
index f263962..53581d1 100644
--- a/webkit/glue/devtools/js/devtools.js
+++ b/webkit/glue/devtools/js/devtools.js
@@ -549,7 +549,7 @@ WebInspector.ScopeChainSidebarPane.TreeElement.prototype.onpopulate =
/**
* Callback function used with the resolveChildren.
*/
- WebInspector.ScopeChainSidebarPane.TreeElement.prototype.didResolveChildren_ =
+WebInspector.ScopeChainSidebarPane.TreeElement.prototype.didResolveChildren_ =
function(object) {
this.removeChildren();
@@ -558,3 +558,18 @@ WebInspector.ScopeChainSidebarPane.TreeElement.prototype.onpopulate =
this.appendChild(new constructor(object, name));
}
};
+
+
+/**
+ * @override
+ */
+WebInspector.StylePropertyTreeElement.prototype.toggleEnabled =
+ function(event) {
+ var disabled = !event.target.checked;
+ var self = this;
+ devtools.tools.getDomAgent().toggleNodeStyleAsync(this.style, !disabled,
+ this.name,
+ function() {
+ WebInspector.panels.elements.updateStyles(true);
+ });
+};
diff --git a/webkit/glue/devtools/js/devtools_host_stub.js b/webkit/glue/devtools/js/devtools_host_stub.js
index 89885d5..60cf583 100644
--- a/webkit/glue/devtools/js/devtools_host_stub.js
+++ b/webkit/glue/devtools/js/devtools_host_stub.js
@@ -158,7 +158,7 @@ RemoteToolsAgentStub.prototype.ExecuteUtilityFunction = function(callId,
functionName, nodeId, args) {
setTimeout(function() {
var result = [];
- if (functionName == 'devtools$$getProperties') {
+ if (functionName == 'getProperties') {
result = [
'undefined', 'undefined_key', undefined,
'string', 'string_key', 'value',
@@ -168,28 +168,30 @@ RemoteToolsAgentStub.prototype.ExecuteUtilityFunction = function(callId,
'boolean', 'boolean_key', true,
'number', 'num_key', 911,
'date', 'date_key', new Date() ];
- } else if (functionName == 'devtools$$getPrototypes') {
+ } else if (functionName == 'getPrototypes') {
result = ['Proto1', 'Proto2', 'Proto3'];
- } else if (functionName == 'devtools$$getStyles') {
+ } else if (functionName == 'getStyles') {
result = {
- 'computedStyle' : [['display', false, false, '', 'none']],
- 'inlineStyle' : [['display', false, false, '', 'none']],
+ 'computedStyle' : [0, null, null, null, ['display', false, false, '', 'none']],
+ 'inlineStyle' : [1, null, null, null, ['display', false, false, '', 'none']],
'styleAttributes' : {
- attr: [['display', false, false, '', 'none']]
+ attr: [2, null, null, null, ['display', false, false, '', 'none']]
},
'matchedCSSRules' : [
{ 'selector' : 'S',
- 'style' : [['display', false, false, '', 'none']],
- 'parentStyleSheetHref' : 'http://localhost',
- 'parentStyleSheetOwnerNodeName' : 'DIV'
+ 'style' : [3, null, null, null, ['display', false, false, '', 'none']],
+ 'parentStyleSheet' : { 'href' : 'http://localhost',
+ 'ownerNodeName' : 'DIV' }
}
]
};
+ } else if (functionName == 'toggleNodeStyle') {
+ alert('toggleNodeStyle ' + args);
} else {
alert('Unexpected utility function:' + functionName);
}
RemoteToolsAgent.DidExecuteUtilityFunction(callId,
- goog.json.serialize(result));
+ goog.json.serialize(result), '');
}, 0);
};
diff --git a/webkit/glue/devtools/js/dom_agent.js b/webkit/glue/devtools/js/dom_agent.js
index ce7740e..d0c8f70 100644
--- a/webkit/glue/devtools/js/dom_agent.js
+++ b/webkit/glue/devtools/js/dom_agent.js
@@ -56,7 +56,6 @@ devtools.DomNode = function(doc, payload) {
this.firstChild = null;
this.parentNode = null;
- this.styles_ = null;
this.disabledStyleProperties_ = {};
if (payload.length > devtools.PayloadIndex.CHILD_NODES) {
@@ -64,6 +63,10 @@ devtools.DomNode = function(doc, payload) {
this.setChildrenPayload_(
payload[devtools.PayloadIndex.CHILD_NODES]);
}
+
+ this.computedStyle_ = null;
+ this.style = null;
+ this.matchedCSSRules_ = [];
};
@@ -222,13 +225,9 @@ devtools.DomNode.prototype.setAttribute = function(name, value) {
*/
devtools.DomNode.prototype.addAttribute_ = function(name, value) {
var attr = {
- 'name': name,
- 'value': value,
- node_: this,
- /* Must be called after node.setStyles_. */
- get style() {
- return this.node_.styles_.attributes[this.name];
- }
+ 'name': name,
+ 'value': value,
+ node_: this
};
this.attributesMap_[name] = attr;
@@ -255,15 +254,6 @@ devtools.DomNode.prototype.removeAttribute = function(name) {
/**
- * Returns inline style (if styles has loaded). Must be called after
- * node.setStyles_.
- */
-devtools.DomNode.prototype.__defineGetter__('style', function() {
- return this.styles_.inlineStyle;
-});
-
-
-/**
* Makes available the following methods and properties:
* - node.style property
* - node.document.defaultView.getComputedStyles(node)
@@ -281,40 +271,37 @@ devtools.DomNode.prototype.__defineGetter__('style', function() {
*/
devtools.DomNode.prototype.setStyles = function(computedStyle, inlineStyle,
styleAttributes, matchedCSSRules) {
- var styles = {};
- styles.computedStyle = this.makeStyle_(computedStyle);
- styles.inlineStyle = this.makeStyle_(inlineStyle);
+ this.computedStyle_ = this.makeStyle_(computedStyle);
+ this.style = this.makeStyle_(inlineStyle);
- styles.attributes = {};
for (var name in styleAttributes) {
- var style = this.makeStyle_(styleAttributes[name]);
- styles.attributes[name] = style;
+ if (this.attributesMap_[name]) {
+ this.attributesMap_[name].style =
+ this.makeStyle_(styleAttributes[name]);
+ }
}
- styles.matchedCSSRules = [];
+ this.matchedCSSRules_ = [];
for (var i = 0; i < matchedCSSRules.length; i++) {
var descr = matchedCSSRules[i];
- var selector = descr.selector;
- var style = this.makeStyle_(descr.style);
- var parentStyleSheet = undefined;
- if (descr.parentStyleSheetHref) {
- parentStyleSheet = {href: descr.parentStyleSheetHref};
-
- if (descr.parentStyleSheetOwnerNodeName) {
- parentStyleSheet.ownerNode =
- {nodeName: descr.parentStyleSheetOwnerNodeName};
+ var rule = {};
+ rule.selectorText = descr['selector'];
+ rule.style = this.makeStyle_(descr['style']);
+
+ if (descr['parentStyleSheet']) {
+ var parentStyleMock = {};
+ parentStyleMock.href = descr['parentStyleSheet']['href'];
+ var nodeName = descr['parentStyleSheet']['ownerNodeName'];
+ if (nodeName) {
+ parentStyleMock.ownerNode = {
+ 'nodeName': nodeName
+ };
}
+ rule.parentStyleSheet = parentStyleMock;
}
-
- styles.matchedCSSRules.push({
- 'selectorText': selector,
- 'style': style,
- 'parentStyleSheet': parentStyleSheet
- });
+ this.matchedCSSRules_.push(rule);
}
-
- this.styles_ = styles;
};
@@ -325,17 +312,24 @@ devtools.DomNode.prototype.setStyles = function(computedStyle, inlineStyle,
* @see devtools.CSSStyleDeclaration
*/
devtools.DomNode.prototype.makeStyle_ = function(payload) {
- return payload && new devtools.CSSStyleDeclaration(payload);
+ var style = new devtools.CSSStyleDeclaration(payload);
+ style.nodeId_ = this.id_;
+ return style;
};
/**
* Remove references to the style information to release
* resources when styles are not going to be used.
- * @see setStyles_.
+ * @see setStyles.
*/
devtools.DomNode.prototype.clearStyles = function() {
- this.styles_ = null;
+ this.computedStyle = null;
+ this.style = null;
+ for (var name in this.attributesMap_) {
+ this.attributesMap_[name].style = null;
+ }
+ this.matchedCSSRules_ = null;
};
@@ -450,19 +444,17 @@ devtools.DomWindow.prototype.Object = function() {
/**
- * Simulates the DOM interface for styles. Must be called after
- * node.setStyles_.
+ * Simulates the DOM interface for styles.
* @param {devtools.DomNode} node
* @return {CSSStyleDescription}
*/
devtools.DomWindow.prototype.getComputedStyle = function(node) {
- return node.styles_.computedStyle;
+ return node.computedStyle_;
};
/**
- * Simulates the DOM interface for styles. Must be called after
- * node.setStyles_.
+ * Simulates the DOM interface for styles.
* @param {devtools.DomNode} nodeStyles
* @param {string} pseudoElement assumed to be empty string.
* @param {boolean} authorOnly assumed to be equal to authorOnly argument of
@@ -471,7 +463,7 @@ devtools.DomWindow.prototype.getComputedStyle = function(node) {
*/
devtools.DomWindow.prototype.getMatchedCSSRules = function(node,
pseudoElement, authorOnly) {
- return node.styles_.matchedCSSRules;
+ return node.matchedCSSRules_;
};
@@ -837,9 +829,11 @@ devtools.DomAgent.prototype.getSearchResultNode = function(index) {
*/
devtools.DomAgent.prototype.getNodePropertiesAsync = function(nodeId,
path, protoDepth, callback) {
- var callbackId = devtools.Callback.wrap(callback);
+ var mycallback =
+ goog.bind(this.utilityFunctionCallbackWrapper_, this, callback);
+ var callbackId = devtools.Callback.wrap(mycallback);
RemoteToolsAgent.ExecuteUtilityFunction(callbackId,
- 'devtools$$getProperties', nodeId,
+ 'getProperties', nodeId,
goog.json.serialize([path, protoDepth]));
};
@@ -851,9 +845,11 @@ devtools.DomAgent.prototype.getNodePropertiesAsync = function(nodeId,
*/
devtools.DomAgent.prototype.getNodePrototypesAsync = function(nodeId,
callback) {
- var callbackId = devtools.Callback.wrap(callback);
+ var mycallback =
+ goog.bind(this.utilityFunctionCallbackWrapper_, this, callback);
+ var callbackId = devtools.Callback.wrap(mycallback);
RemoteToolsAgent.ExecuteUtilityFunction(callbackId,
- 'devtools$$getPrototypes', nodeId, '');
+ 'getPrototypes', nodeId, '[]');
};
@@ -865,37 +861,76 @@ devtools.DomAgent.prototype.getNodePrototypesAsync = function(nodeId,
*/
devtools.DomAgent.prototype.getNodeStylesAsync = function(node,
authorOnly, callback) {
- var callbackId = devtools.Callback.wrap(callback);
+ var mycallback =
+ goog.bind(this.utilityFunctionCallbackWrapper_, this, callback);
+ var callbackId = devtools.Callback.wrap(mycallback);
RemoteToolsAgent.ExecuteUtilityFunction(callbackId,
- 'devtools$$getStyles',
+ 'getStyles',
node.id_,
- goog.json.serialize(authorOnly));
+ goog.json.serialize([authorOnly]));
+};
+
+
+/**
+ * Toggles style with given id on/off.
+ * @param {devtools.CSSStyleDeclaration} style Style to toggle.
+ * @param {boolean} enabled True if style should be enabled.
+ * @param {string} name Style name.
+ * @param {Function} callback.
+ */
+devtools.DomAgent.prototype.toggleNodeStyleAsync = function(
+ style, enabled, name, callback) {
+ var mycallback =
+ goog.bind(this.utilityFunctionCallbackWrapper_, this, callback);
+ var callbackId = devtools.Callback.wrap(mycallback);
+ RemoteToolsAgent.ExecuteUtilityFunction(callbackId,
+ 'toggleNodeStyle',
+ style.nodeId_,
+ goog.json.serialize([style.id_, enabled, name]));
+};
+
+
+/**
+ * Dumps exception if something went wrong in ExecuteUtilityFunction.
+ */
+devtools.DomAgent.prototype.utilityFunctionCallbackWrapper_ =
+ function(callback, result, exception) {
+ if (exception && exception.length) {
+ debugPrint('Exception in ExecuteUtilityFunction styles:' + exception);
+ return;
+ }
+ callback(result);
};
/**
* Represents remote CSSStyleDeclaration for using in StyleSidebarPane.
- * @param {Array<Object>} payload built by devtools$$getStyle from the injected
- * js.
- * @consctuctor
+ * @param {id, Array<Object>} payload built by inject's getStyle from the
+ * injected js.
+ * @constructor
*/
devtools.CSSStyleDeclaration = function(payload) {
- this.length = payload.length;
+ this.id_ = payload[0];
+ this.__disabledProperties = payload[1];
+ this.__disabledPropertyValues = payload[2];
+ this.__disabledPropertyPriorities = payload[3];
+
+ this.length = payload.length - 4;
this.priority_ = {};
this.implicit_ = {};
this.shorthand_ = {};
this.value_ = {};
- for (var i = 0; i < payload.length; ++i) {
+ for (var i = 4; i < payload.length; ++i) {
var p = payload[i];
var name = p[0];
-
+
this.priority_[name] = p[1];
this.implicit_[name] = p[2];
this.shorthand_[name] = p[3];
this.value_[name] = p[4];
- this[i] = name;
+ this[i - 4] = name;
}
};
diff --git a/webkit/glue/devtools/js/inject.js b/webkit/glue/devtools/js/inject.js
index 5cbb1a8..f19e470 100644
--- a/webkit/glue/devtools/js/inject.js
+++ b/webkit/glue/devtools/js/inject.js
@@ -1,155 +1,285 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview Javascript that is being injected into the inspectable page
- * while debugging.
- */
-goog.require('goog.json');
-
-/**
- * Returns JSON-serialized array of properties for a given node
- * on a given path.
- * @param {Node} node Node to get property value for.
- * @param {string} args JSON-serialized {Array.<string>} Path to the
- * nested object, {number} Depth to the actual proto to inspect].
- * @return {string} JSON-serialized array where each property is represented
- * by the tree entryies [{string} type, {string} name, {Object} value].
- */
-function devtools$$getProperties(node, args) {
- // Parse parameters.
- var parsedArgs = goog.json.parse(args);
- var path = parsedArgs[0];
- var protoDepth = parsedArgs[1];
-
- var result = [];
- var obj = node;
-
- // Follow the path.
- for (var i = 0; obj && i < path.length; ++i) {
- obj = obj[path[i]];
- }
-
- if (!obj) {
- return '[]';
- }
-
- // Get to the necessary proto layer.
- for (var i = 0; obj && i < protoDepth; ++i) {
- obj = obj.__proto__;
- }
-
- if (!obj) {
- return '[]';
- }
-
- // Go over properties, prepare results.
- for (var name in obj) {
- if (protoDepth != -1 && 'hasOwnProperty' in obj &&
- !obj.hasOwnProperty(name)) {
- continue;
- }
- var type = typeof obj[name];
- result.push(type);
- result.push(name);
- if (type == 'string') {
- var str = obj[name];
- result.push(str.length > 99 ? str.substr(0, 99) + '...' : str);
- } else if (type != 'object' && type != 'array' &&
- type != 'function') {
- result.push(obj[name]);
- } else {
- result.push(undefined);
- }
- }
- return goog.json.serialize(result);
-}
-
-
-/**
- * Returns JSON-serialized array of prototypes for a given node.
- * @param {Node} node Node to get prorotypes for.
- * @return {string} JSON-serialized array where each item is a proto name.
- */
-function devtools$$getPrototypes(node, args) {
- var result = [];
- for (var prototype = node; prototype; prototype = prototype.__proto__) {
- var description = Object.prototype.toString.call(prototype);
- result.push(description.replace(/^\[object (.*)\]$/i, '$1'));
- }
- return goog.json.serialize(result);
-}
-
-
-/**
- * Returns JSON-serialized style information that is used in devtools.js.
- * @param {Node} node Node to get prorotypes for.
- * @param {string} args JSON-serialized boolean authorOnly that determines
- * whether only author styles need to be added.
- * @return {string} JSON-serialized style collection descriptor.
- */
-function devtools$$getStyles(node, args) {
- var authorOnly = goog.json.parse(args);
- if (!node.nodeType == Node.ELEMENT_NODE) {
- return '{}';
- }
- var matchedRules = window.getMatchedCSSRules(node, '', authorOnly);
- var matchedCSSRulesObj = [];
- for (var i = 0; matchedRules && i < matchedRules.length; ++i) {
- var rule = matchedRules[i];
- var style = devtools$$serializeStyle_(rule.style);
- var parentStyleSheetHref = (rule.parentStyleSheet ?
- rule.parentStyleSheet.href : undefined);
- var parentStyleSheetOwnerNodeName;
- if (rule.parentStyleSheet && rule.parentStyleSheet.ownerNode) {
- parentStyleSheetOwnerNodeName = rule.parentStyleSheet.ownerNode.name;
- }
- matchedCSSRulesObj.push({
- 'selector' : rule.selectorText,
- 'style' : style,
- 'parentStyleSheetHref' : parentStyleSheetHref,
- 'parentStyleSheetOwnerNodeName' : parentStyleSheetOwnerNodeName
- });
- }
-
- var attributeStyles = {};
- var attributes = node.attributes;
- for (var i = 0; attributes && i < attributes.length; ++i) {
- if (attributes[i].style) {
- attributeStyles[attributes[i].name] =
- devtools$$serializeStyle_(attributes[i].style);
- }
- }
-
- var result = {
- 'inlineStyle' : devtools$$serializeStyle_(node.style),
- 'computedStyle' : devtools$$serializeStyle_(
- window.getComputedStyle(node, '')),
- 'matchedCSSRules' : matchedCSSRulesObj,
- 'styleAttributes' : attributeStyles
- };
- return goog.json.serialize(result);
-}
-
-
-/**
- * Converts given style into serializable object.
- * @param {CSSStyleDeclaration} style Style to serialize.
- * @return {Array<Object>} Serializable object.
- * @private
- */
-function devtools$$serializeStyle_(style) {
- var result = [];
- for (var i = 0; style && i < style.length; ++i) {
- var name = style[i];
- result.push([
- name,
- style.getPropertyPriority(name),
- style.isPropertyImplicit(name),
- style.getPropertyShorthand(name),
- style.getPropertyValue(name)
- ]);
- }
- return result;
-}
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Javascript that is being injected into the inspectable page
+ * while debugging.
+ */
+goog.require('goog.json');
+goog.provide('devtools.Injected');
+
+
+/**
+ * Main injected object.
+ * @constructor.
+ */
+devtools.Injected = function() {
+ /**
+ * Unique style id generator.
+ * @type {number}
+ * @private
+ */
+ this.lastStyleId_ = 1;
+};
+
+
+/**
+ * Returns array of properties for a given node on a given path.
+ * @param {Node} node Node to get property value for.
+ * @param {Array.<string>} path Path to the nested object.
+ * @param {number} protoDepth Depth of the actual proto to inspect.
+ * @return {Array.<Object>} Array where each property is represented
+ * by the tree entries [{string} type, {string} name, {Object} value].
+ */
+devtools.Injected.prototype.getProperties = function(node, path, protoDepth) {
+ var result = [];
+ var obj = node;
+
+ // Follow the path.
+ for (var i = 0; obj && i < path.length; ++i) {
+ obj = obj[path[i]];
+ }
+
+ if (!obj) {
+ return [];
+ }
+
+ // Get to the necessary proto layer.
+ for (var i = 0; obj && i < protoDepth; ++i) {
+ obj = obj.__proto__;
+ }
+
+ if (!obj) {
+ return [];
+ }
+
+ // Go over properties, prepare results.
+ for (var name in obj) {
+ if (protoDepth != -1 && 'hasOwnProperty' in obj &&
+ !obj.hasOwnProperty(name)) {
+ continue;
+ }
+ var type = typeof obj[name];
+ result.push(type);
+ result.push(name);
+ if (type == 'string') {
+ var str = obj[name];
+ result.push(str.length > 99 ? str.substr(0, 99) + '...' : str);
+ } else if (type != 'object' && type != 'array' &&
+ type != 'function') {
+ result.push(obj[name]);
+ } else {
+ result.push(undefined);
+ }
+ }
+ return result;
+};
+
+
+/**
+ * Returns array of prototypes for a given node.
+ * @param {Node} node Node to get prorotypes for.
+ * @return {Array<string>} Array of proto names.
+ */
+devtools.Injected.prototype.getPrototypes = function(node) {
+ var result = [];
+ for (var prototype = node; prototype; prototype = prototype.__proto__) {
+ var description = Object.prototype.toString.call(prototype);
+ result.push(description.replace(/^\[object (.*)\]$/i, '$1'));
+ }
+ return result;
+};
+
+
+/**
+ * Returns style information that is used in devtools.js.
+ * @param {Node} node Node to get prorotypes for.
+ * @param {boolean} authorOnly Determines whether only author styles need to
+ * be added.
+ * @return {string} Style collection descriptor.
+ */
+devtools.Injected.prototype.getStyles = function(node, authorOnly) {
+ if (!node.nodeType == Node.ELEMENT_NODE) {
+ return {};
+ }
+ var matchedRules = window.getMatchedCSSRules(node, '', authorOnly);
+ var matchedCSSRulesObj = [];
+ for (var i = 0; matchedRules && i < matchedRules.length; ++i) {
+ var rule = matchedRules[i];
+ var style = this.serializeStyle_(rule.style);
+ var ruleValue = {
+ 'selector' : rule.selectorText,
+ 'style' : style
+ };
+ if (rule.parentStyleSheet) {
+ ruleValue['parentStyleSheet'] = {
+ 'href' : rule.parentStyleSheet.href,
+ 'ownerNodeName' : rule.parentStyleSheet.ownerNode ?
+ rule.parentStyleSheet.ownerNode.name : null
+ };
+ }
+ var parentStyleSheetHref = (rule.parentStyleSheet ?
+ rule.parentStyleSheet.href : undefined);
+ var parentStyleSheetOwnerNodeName;
+ if (rule.parentStyleSheet && rule.parentStyleSheet.ownerNode) {
+ parentStyleSheetOwnerNodeName = rule.parentStyleSheet.ownerNode.name;
+ }
+ matchedCSSRulesObj.push(ruleValue);
+ }
+
+ var attributeStyles = {};
+ var attributes = node.attributes;
+ for (var i = 0; attributes && i < attributes.length; ++i) {
+ if (attributes[i].style) {
+ attributeStyles[attributes[i].name] =
+ this.serializeStyle_(attributes[i].style);
+ }
+ }
+
+ var result = {
+ 'inlineStyle' : this.serializeStyle_(node.style),
+ 'computedStyle' : this.serializeStyle_(
+ window.getComputedStyle(node, '')),
+ 'matchedCSSRules' : matchedCSSRulesObj,
+ 'styleAttributes' : attributeStyles
+ };
+ return result;
+};
+
+
+/**
+ * Returns style decoration object for given id.
+ * @param {Node} node Node to get prorotypes for.
+ * @param {number} id Style id.
+ * @return {Object} Style object.
+ * @private
+ */
+devtools.Injected.prototype.getStyleForId_ = function(node, id) {
+ var matchedRules = window.getMatchedCSSRules(node, '', false);
+ for (var i = 0; matchedRules && i < matchedRules.length; ++i) {
+ var rule = matchedRules[i];
+ if (rule.style.__id == id) {
+ return rule.style;
+ }
+ }
+ var attributes = node.attributes;
+ for (var i = 0; attributes && i < attributes.length; ++i) {
+ if (attributes[i].style && attributes[i].style.__id == id) {
+ return attributes[i].style;
+ }
+ }
+ if (node.style.__id == id) {
+ return node.style;
+ }
+ return null;
+};
+
+
+
+
+/**
+ * Converts given style into serializable object.
+ * @param {CSSStyleDeclaration} style Style to serialize.
+ * @return {Array<Object>} Serializable object.
+ * @private
+ */
+devtools.Injected.prototype.serializeStyle_ = function(style) {
+ if (!style) {
+ return [];
+ }
+ if (!style.__id) {
+ style.__id = this.lastStyleId_++;
+ }
+ var result = [
+ style.__id,
+ style.__disabledProperties,
+ style.__disabledPropertyValues,
+ style.__disabledPropertyPriorities
+ ];
+ for (var i = 0; i < style.length; ++i) {
+ var name = style[i];
+ result.push([
+ name,
+ style.getPropertyPriority(name),
+ style.isPropertyImplicit(name),
+ style.getPropertyShorthand(name),
+ style.getPropertyValue(name)
+ ]);
+ }
+ return result;
+};
+
+
+/**
+ * Toggles style with given id on/off.
+ * @param {Node} node Node to get prorotypes for.
+ * @param {number} styleId Id of style to toggle.
+ * @param {boolean} enabled Determines value to toggle to,
+ * @param {string} name Name of the property.
+ */
+devtools.Injected.prototype.toggleNodeStyle = function(node, styleId, enabled,
+ name) {
+ var style = this.getStyleForId_(node, styleId);
+ if (!style) {
+ return false;
+ }
+
+ if (!enabled) {
+ if (!style.__disabledPropertyValues ||
+ !style.__disabledPropertyPriorities) {
+ style.__disabledProperties = {};
+ style.__disabledPropertyValues = {};
+ style.__disabledPropertyPriorities = {};
+ }
+
+ style.__disabledPropertyValues[name] = style.getPropertyValue(name);
+ style.__disabledPropertyPriorities[name] = style.getPropertyPriority(name);
+
+ if (style.getPropertyShorthand(name)) {
+ var longhandProperties = this.getLonghandProperties_(style, name);
+ for (var i = 0; i < longhandProperties.length; ++i) {
+ style.__disabledProperties[longhandProperties[i]] = true;
+ style.removeProperty(longhandProperties[i]);
+ }
+ } else {
+ style.__disabledProperties[name] = true;
+ style.removeProperty(name);
+ }
+ } else if (style.__disabledProperties &&
+ style.__disabledProperties[name]) {
+ var value = style.__disabledPropertyValues[name];
+ var priority = style.__disabledPropertyPriorities[name];
+ style.setProperty(name, value, priority);
+
+ delete style.__disabledProperties[name];
+ delete style.__disabledPropertyValues[name];
+ delete style.__disabledPropertyPriorities[name];
+ }
+ return true;
+};
+
+
+/**
+ * Returns longhand proeprties for a given shorthand one.
+ * @param {CSSStyleDeclaration} style Style declaration to use for lookup.
+ * @param {string} shorthandProperty Shorthand property to get longhands for.
+ * @return {Array.<string>} Array with longhand properties.
+ * @private
+ */
+devtools.Injected.prototype.getLonghandProperties_ = function(style,
+ shorthandProperty) {
+ var properties = [];
+ var foundProperties = {};
+
+ for (var i = 0; i < style.length; ++i) {
+ var individualProperty = style[i];
+ if (individualProperty in foundProperties ||
+ style.getPropertyShorthand(individualProperty) != shorthandProperty) {
+ continue;
+ }
+ foundProperties[individualProperty] = true;
+ properties.push(individualProperty);
+ }
+ return properties;
+};
diff --git a/webkit/glue/devtools/js/inject_dispatch.js b/webkit/glue/devtools/js/inject_dispatch.js
new file mode 100644
index 0000000..0b5df80
--- /dev/null
+++ b/webkit/glue/devtools/js/inject_dispatch.js
@@ -0,0 +1,33 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Injects 'injected' object into the inspectable page.
+ */
+
+/**
+ * Dispatches host calls into the injected function calls.
+ */
+goog.require('devtools.Injected');
+
+
+/**
+ * Injected singleton.
+ */
+var devtools$$obj = new devtools.Injected();
+
+
+/**
+ * Main dispatch method, all calls from the host go through this one.
+ * @param {string} functionName Function to call
+ * @param {Node} node Node context of the call.
+ * @param {string} json_args JSON-serialized call parameters.
+ * @return {string} JSON-serialized result of the dispatched call.
+ */
+function devtools$$dispatch(functionName, node, json_args) {
+ var params = goog.json.parse(json_args);
+ params.splice(0, 0, node);
+ var result = devtools$$obj[functionName].apply(devtools$$obj, params);
+ return goog.json.serialize(result);
+};