summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/WebKit/Source/devtools/front_end/sdk/InspectorBackend.js
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/WebKit/Source/devtools/front_end/sdk/InspectorBackend.js')
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/sdk/InspectorBackend.js877
1 files changed, 877 insertions, 0 deletions
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sdk/InspectorBackend.js b/chromium/third_party/WebKit/Source/devtools/front_end/sdk/InspectorBackend.js
new file mode 100644
index 00000000000..3c9f9558c31
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/sdk/InspectorBackend.js
@@ -0,0 +1,877 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+/**
+ * @constructor
+ */
+function InspectorBackendClass()
+{
+ this._connection = null;
+ this._agentPrototypes = {};
+ this._dispatcherPrototypes = {};
+ this._initialized = false;
+ this._enums = {};
+ this._initProtocolAgentsConstructor();
+}
+
+InspectorBackendClass.prototype = {
+
+ _initProtocolAgentsConstructor: function()
+ {
+ window.Protocol = {};
+
+ /**
+ * @constructor
+ * @param {!Object.<string, !Object>} agentsMap
+ */
+ window.Protocol.Agents = function(agentsMap) {
+ this._agentsMap = agentsMap;
+ };
+ },
+
+ /**
+ * @param {string} domain
+ */
+ _addAgentGetterMethodToProtocolAgentsPrototype: function(domain)
+ {
+ var upperCaseLength = 0;
+ while (upperCaseLength < domain.length && domain[upperCaseLength].toLowerCase() !== domain[upperCaseLength])
+ ++upperCaseLength;
+
+ var methodName = domain.substr(0, upperCaseLength).toLowerCase() + domain.slice(upperCaseLength) + "Agent";
+
+ /**
+ * @this {Protocol.Agents}
+ */
+ function agentGetter()
+ {
+ return this._agentsMap[domain];
+ }
+
+ window.Protocol.Agents.prototype[methodName] = agentGetter;
+
+ /**
+ * @this {Protocol.Agents}
+ */
+ function registerDispatcher(dispatcher)
+ {
+ this.registerDispatcher(domain, dispatcher)
+ }
+
+ window.Protocol.Agents.prototype["register" + domain + "Dispatcher"] = registerDispatcher;
+ },
+
+ /**
+ * @return {!InspectorBackendClass.Connection}
+ */
+ connection: function()
+ {
+ if (!this._connection)
+ throw "Main connection was not initialized";
+ return this._connection;
+ },
+
+ /**
+ * @param {!InspectorBackendClass.MainConnection} connection
+ */
+ setConnection: function(connection)
+ {
+ this._connection = connection;
+
+ this._connection.registerAgentsOn(window);
+ for (var type in this._enums) {
+ var domainAndMethod = type.split(".");
+ window[domainAndMethod[0] + "Agent"][domainAndMethod[1]] = this._enums[type];
+ }
+ },
+
+ /**
+ * @param {string} domain
+ * @return {!InspectorBackendClass.AgentPrototype}
+ */
+ _agentPrototype: function(domain)
+ {
+ if (!this._agentPrototypes[domain]) {
+ this._agentPrototypes[domain] = new InspectorBackendClass.AgentPrototype(domain);
+ this._addAgentGetterMethodToProtocolAgentsPrototype(domain);
+ }
+
+ return this._agentPrototypes[domain];
+ },
+
+ /**
+ * @param {string} domain
+ * @return {!InspectorBackendClass.DispatcherPrototype}
+ */
+ _dispatcherPrototype: function(domain)
+ {
+ if (!this._dispatcherPrototypes[domain])
+ this._dispatcherPrototypes[domain] = new InspectorBackendClass.DispatcherPrototype();
+ return this._dispatcherPrototypes[domain];
+ },
+
+ /**
+ * @param {string} method
+ * @param {!Array.<!Object>} signature
+ * @param {!Array.<string>} replyArgs
+ * @param {boolean} hasErrorData
+ */
+ registerCommand: function(method, signature, replyArgs, hasErrorData)
+ {
+ var domainAndMethod = method.split(".");
+ this._agentPrototype(domainAndMethod[0]).registerCommand(domainAndMethod[1], signature, replyArgs, hasErrorData);
+ this._initialized = true;
+ },
+
+ /**
+ * @param {string} type
+ * @param {!Object} values
+ */
+ registerEnum: function(type, values)
+ {
+ this._enums[type] = values;
+ this._initialized = true;
+ },
+
+ /**
+ * @param {string} eventName
+ * @param {!Object} params
+ */
+ registerEvent: function(eventName, params)
+ {
+ var domain = eventName.split(".")[0];
+ this._dispatcherPrototype(domain).registerEvent(eventName, params);
+ this._initialized = true;
+ },
+
+ /**
+ * @param {string} domain
+ * @param {!Object} dispatcher
+ */
+ registerDomainDispatcher: function(domain, dispatcher)
+ {
+ this._connection.registerDispatcher(domain, dispatcher);
+ },
+
+ /**
+ * @param {string} jsonUrl
+ */
+ loadFromJSONIfNeeded: function(jsonUrl)
+ {
+ if (this._initialized)
+ return;
+
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", jsonUrl, false);
+ xhr.send(null);
+
+ var schema = JSON.parse(xhr.responseText);
+ var code = InspectorBackendClass._generateCommands(schema);
+ eval(code);
+ },
+
+ /**
+ * @param {function(T)} clientCallback
+ * @param {string} errorPrefix
+ * @param {function(new:T,S)=} constructor
+ * @param {T=} defaultValue
+ * @return {function(?string, S)}
+ * @template T,S
+ */
+ wrapClientCallback: function(clientCallback, errorPrefix, constructor, defaultValue)
+ {
+ /**
+ * @param {?string} error
+ * @param {S} value
+ * @template S
+ */
+ function callbackWrapper(error, value)
+ {
+ if (error) {
+ console.error(errorPrefix + error);
+ clientCallback(defaultValue);
+ return;
+ }
+ if (constructor)
+ clientCallback(new constructor(value));
+ else
+ clientCallback(value);
+ }
+ return callbackWrapper;
+ }
+}
+
+/**
+ * @param {*} schema
+ * @return {string}
+ */
+InspectorBackendClass._generateCommands = function(schema) {
+ var jsTypes = { integer: "number", array: "object" };
+ var rawTypes = {};
+ var result = [];
+
+ var domains = schema["domains"] || [];
+ for (var i = 0; i < domains.length; ++i) {
+ var domain = domains[i];
+ for (var j = 0; domain.types && j < domain.types.length; ++j) {
+ var type = domain.types[j];
+ rawTypes[domain.domain + "." + type.id] = jsTypes[type.type] || type.type;
+ }
+ }
+
+ function toUpperCase(groupIndex, group0, group1)
+ {
+ return [group0, group1][groupIndex].toUpperCase();
+ }
+ function generateEnum(enumName, items)
+ {
+ var members = []
+ for (var m = 0; m < items.length; ++m) {
+ var value = items[m];
+ var name = value.replace(/-(\w)/g, toUpperCase.bind(null, 1)).toTitleCase();
+ name = name.replace(/HTML|XML|WML|API/ig, toUpperCase.bind(null, 0));
+ members.push(name + ": \"" + value +"\"");
+ }
+ return "InspectorBackend.registerEnum(\"" + enumName + "\", {" + members.join(", ") + "});";
+ }
+
+ for (var i = 0; i < domains.length; ++i) {
+ var domain = domains[i];
+
+ var types = domain["types"] || [];
+ for (var j = 0; j < types.length; ++j) {
+ var type = types[j];
+ if ((type["type"] === "string") && type["enum"])
+ result.push(generateEnum(domain.domain + "." + type.id, type["enum"]));
+ else if (type["type"] === "object") {
+ var properties = type["properties"] || [];
+ for (var k = 0; k < properties.length; ++k) {
+ var property = properties[k];
+ if ((property["type"] === "string") && property["enum"])
+ result.push(generateEnum(domain.domain + "." + type.id + property["name"].toTitleCase(), property["enum"]));
+ }
+ }
+ }
+
+ var commands = domain["commands"] || [];
+ for (var j = 0; j < commands.length; ++j) {
+ var command = commands[j];
+ var parameters = command["parameters"];
+ var paramsText = [];
+ for (var k = 0; parameters && k < parameters.length; ++k) {
+ var parameter = parameters[k];
+
+ var type;
+ if (parameter.type)
+ type = jsTypes[parameter.type] || parameter.type;
+ else {
+ var ref = parameter["$ref"];
+ if (ref.indexOf(".") !== -1)
+ type = rawTypes[ref];
+ else
+ type = rawTypes[domain.domain + "." + ref];
+ }
+
+ var text = "{\"name\": \"" + parameter.name + "\", \"type\": \"" + type + "\", \"optional\": " + (parameter.optional ? "true" : "false") + "}";
+ paramsText.push(text);
+ }
+
+ var returnsText = [];
+ var returns = command["returns"] || [];
+ for (var k = 0; k < returns.length; ++k) {
+ var parameter = returns[k];
+ returnsText.push("\"" + parameter.name + "\"");
+ }
+ var hasErrorData = String(Boolean(command.error));
+ result.push("InspectorBackend.registerCommand(\"" + domain.domain + "." + command.name + "\", [" + paramsText.join(", ") + "], [" + returnsText.join(", ") + "], " + hasErrorData + ");");
+ }
+
+ for (var j = 0; domain.events && j < domain.events.length; ++j) {
+ var event = domain.events[j];
+ var paramsText = [];
+ for (var k = 0; event.parameters && k < event.parameters.length; ++k) {
+ var parameter = event.parameters[k];
+ paramsText.push("\"" + parameter.name + "\"");
+ }
+ result.push("InspectorBackend.registerEvent(\"" + domain.domain + "." + event.name + "\", [" + paramsText.join(", ") + "]);");
+ }
+
+ result.push("InspectorBackend.register" + domain.domain + "Dispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, \"" + domain.domain + "\");");
+ }
+ return result.join("\n");
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.Object}
+ */
+InspectorBackendClass.Connection = function()
+{
+ this._lastMessageId = 1;
+ this._pendingResponsesCount = 0;
+ this._agents = {};
+ this._dispatchers = {};
+ this._callbacks = {};
+ this._initialize(InspectorBackend._agentPrototypes, InspectorBackend._dispatcherPrototypes);
+}
+
+InspectorBackendClass.Connection.Events = {
+ Disconnected: "Disconnected",
+}
+
+InspectorBackendClass.Connection.prototype = {
+
+ /**
+ * @param {!Object.<string, !InspectorBackendClass.AgentPrototype>} agentPrototypes
+ * @param {!Object.<string, !InspectorBackendClass.DispatcherPrototype>} dispatcherPrototypes
+ */
+ _initialize: function(agentPrototypes, dispatcherPrototypes)
+ {
+ for (var domain in agentPrototypes) {
+ this._agents[domain] = Object.create(agentPrototypes[domain]);
+ this._agents[domain].setConnection(this);
+ }
+
+ for (var domain in dispatcherPrototypes)
+ this._dispatchers[domain] = Object.create(dispatcherPrototypes[domain])
+
+ },
+
+ /**
+ * @param {!Object} object
+ */
+ registerAgentsOn: function(object)
+ {
+ for (var domain in this._agents)
+ object[domain + "Agent"] = this._agents[domain];
+ },
+
+ /**
+ * @return {number}
+ */
+ nextMessageId: function()
+ {
+ return this._lastMessageId++;
+ },
+
+ /**
+ * @param {string} domain
+ * @return {!InspectorBackendClass.AgentPrototype}
+ */
+ agent: function(domain)
+ {
+ return this._agents[domain];
+ },
+
+ /**
+ * @return {!Object.<string, !Object>}
+ */
+ agentsMap: function()
+ {
+ return this._agents;
+ },
+
+ /**
+ * @param {string} domain
+ * @param {string} method
+ * @param {?Object} params
+ * @param {?function(*)} callback
+ * @private
+ */
+ _wrapCallbackAndSendMessageObject: function(domain, method, params, callback)
+ {
+ var messageObject = {};
+
+ var messageId = this.nextMessageId();
+ messageObject.id = messageId;
+
+ messageObject.method = method;
+ if (params)
+ messageObject.params = params;
+
+ var wrappedCallback = this._wrap(callback, domain, method);
+
+ if (InspectorBackendClass.Options.dumpInspectorProtocolMessages)
+ this._dumpProtocolMessage("frontend: " + JSON.stringify(messageObject));
+
+ this.sendMessage(messageObject);
+ ++this._pendingResponsesCount;
+ this._callbacks[messageId] = wrappedCallback;
+ },
+
+ /**
+ * @param {?function(*)} callback
+ * @param {string} method
+ * @param {string} domain
+ * @return {!function(*)}
+ */
+ _wrap: function(callback, domain, method)
+ {
+ if (!callback)
+ callback = function() {};
+
+ callback.methodName = method;
+ callback.domain = domain;
+ if (InspectorBackendClass.Options.dumpInspectorTimeStats)
+ callback.sendRequestTime = Date.now();
+
+ return callback;
+ },
+
+ /**
+ * @param {!Object} messageObject
+ */
+ sendMessage: function(messageObject)
+ {
+ throw "Not implemented";
+ },
+
+ /**
+ * @param {!Object} messageObject
+ */
+ reportProtocolError: function(messageObject)
+ {
+ console.error("Protocol Error: the message with wrong id. Message = " + JSON.stringify(messageObject));
+ },
+
+ /**
+ * @param {!Object|string} message
+ */
+ dispatch: function(message)
+ {
+ if (InspectorBackendClass.Options.dumpInspectorProtocolMessages)
+ this._dumpProtocolMessage("backend: " + ((typeof message === "string") ? message : JSON.stringify(message)));
+
+ var messageObject = /** @type {!Object} */ ((typeof message === "string") ? JSON.parse(message) : message);
+
+ if ("id" in messageObject) { // just a response for some request
+
+ var callback = this._callbacks[messageObject.id];
+ if (!callback) {
+ this.reportProtocolError(messageObject);
+ return;
+ }
+
+ var processingStartTime;
+ if (InspectorBackendClass.Options.dumpInspectorTimeStats)
+ processingStartTime = Date.now();
+
+ this.agent(callback.domain).dispatchResponse(messageObject.id, messageObject, callback.methodName, callback);
+ --this._pendingResponsesCount;
+ delete this._callbacks[messageObject.id];
+
+ if (InspectorBackendClass.Options.dumpInspectorTimeStats)
+ console.log("time-stats: " + callback.methodName + " = " + (processingStartTime - callback.sendRequestTime) + " + " + (Date.now() - processingStartTime));
+
+ if (this._scripts && !this._pendingResponsesCount)
+ this.runAfterPendingDispatches();
+ return;
+ } else {
+ var method = messageObject.method.split(".");
+ var domainName = method[0];
+ if (!(domainName in this._dispatchers)) {
+ console.error("Protocol Error: the message " + messageObject.method + " is for non-existing domain '" + domainName + "'");
+ return;
+ }
+
+ this._dispatchers[domainName].dispatch(method[1], messageObject);
+
+ }
+
+ },
+
+ /**
+ * @param {string} domain
+ * @param {!Object} dispatcher
+ */
+ registerDispatcher: function(domain, dispatcher)
+ {
+ if (!this._dispatchers[domain])
+ return;
+
+ this._dispatchers[domain].setDomainDispatcher(dispatcher);
+ },
+
+ /**
+ * @param {string=} script
+ */
+ runAfterPendingDispatches: function(script)
+ {
+ if (!this._scripts)
+ this._scripts = [];
+
+ if (script)
+ this._scripts.push(script);
+
+ if (!this._pendingResponsesCount) {
+ var scripts = this._scripts;
+ this._scripts = []
+ for (var id = 0; id < scripts.length; ++id)
+ scripts[id].call(this);
+ }
+ },
+
+ /**
+ * @param {string} reason
+ */
+ fireDisconnected: function(reason)
+ {
+ this.dispatchEventToListeners(InspectorBackendClass.Connection.Events.Disconnected, {reason: reason});
+ },
+
+ _dumpProtocolMessage: function(message)
+ {
+ console.log(message);
+ },
+
+ __proto__: WebInspector.Object.prototype
+
+}
+
+/**
+ * @constructor
+ * @extends {InspectorBackendClass.Connection}
+ * @param {!function(!InspectorBackendClass.Connection)} onConnectionReady
+ */
+InspectorBackendClass.MainConnection = function(onConnectionReady)
+{
+ InspectorBackendClass.Connection.call(this);
+ onConnectionReady(this);
+}
+
+InspectorBackendClass.MainConnection.prototype = {
+
+ /**
+ * @param {!Object} messageObject
+ */
+ sendMessage: function(messageObject)
+ {
+ var message = JSON.stringify(messageObject);
+ InspectorFrontendHost.sendMessageToBackend(message);
+ },
+
+ __proto__: InspectorBackendClass.Connection.prototype
+}
+
+/**
+ * @constructor
+ * @extends {InspectorBackendClass.Connection}
+ * @param {string} url
+ * @param {!function(!InspectorBackendClass.Connection)} onConnectionReady
+ */
+InspectorBackendClass.WebSocketConnection = function(url, onConnectionReady)
+{
+ InspectorBackendClass.Connection.call(this);
+ this._socket = new WebSocket(url);
+ this._socket.onmessage = this._onMessage.bind(this);
+ this._socket.onerror = this._onError.bind(this);
+ this._socket.onopen = onConnectionReady.bind(null, this);
+ this._socket.onclose = this.fireDisconnected.bind(this, "websocket_closed");
+}
+
+InspectorBackendClass.WebSocketConnection.prototype = {
+
+ /**
+ * @param {!MessageEvent} message
+ */
+ _onMessage: function(message)
+ {
+ var data = /** @type {string} */ (message.data)
+ this.dispatch(data);
+ },
+
+ /**
+ * @param {!Event} error
+ */
+ _onError: function(error)
+ {
+ console.error(error);
+ },
+
+ /**
+ * @param {!Object} messageObject
+ */
+ sendMessage: function(messageObject)
+ {
+ var message = JSON.stringify(messageObject);
+ this._socket.send(message);
+ },
+
+ __proto__: InspectorBackendClass.Connection.prototype
+}
+
+
+/**
+ * @constructor
+ * @extends {InspectorBackendClass.Connection}
+ * @param {!function(!InspectorBackendClass.Connection)} onConnectionReady
+ */
+InspectorBackendClass.StubConnection = function(onConnectionReady)
+{
+ InspectorBackendClass.Connection.call(this);
+ onConnectionReady(this);
+}
+
+InspectorBackendClass.StubConnection.prototype = {
+
+ /**
+ * @param {!Object} messageObject
+ */
+ sendMessage: function(messageObject)
+ {
+ var message = JSON.stringify(messageObject);
+ setTimeout(this._echoResponse.bind(this, messageObject), 0);
+ },
+
+ /**
+ * @param {!Object} messageObject
+ */
+ _echoResponse: function(messageObject)
+ {
+ this.dispatch(messageObject)
+ },
+
+ __proto__: InspectorBackendClass.Connection.prototype
+}
+
+/**
+ * @constructor
+ * @param {string} domain
+ */
+InspectorBackendClass.AgentPrototype = function(domain)
+{
+ this._replyArgs = {};
+ this._hasErrorData = {};
+ this._domain = domain;
+}
+
+InspectorBackendClass.AgentPrototype.prototype = {
+
+ /**
+ * @param {!InspectorBackendClass.Connection} connection
+ */
+ setConnection: function(connection)
+ {
+ this._connection = connection;
+ },
+
+ /**
+ * @param {string} methodName
+ * @param {!Array.<!Object>} signature
+ * @param {!Array.<string>} replyArgs
+ * @param {boolean} hasErrorData
+ */
+ registerCommand: function(methodName, signature, replyArgs, hasErrorData)
+ {
+ var domainAndMethod = this._domain + "." + methodName;
+
+ /**
+ * @this {InspectorBackendClass.AgentPrototype}
+ */
+ function sendMessage(vararg)
+ {
+ var params = [domainAndMethod, signature].concat(Array.prototype.slice.call(arguments));
+ InspectorBackendClass.AgentPrototype.prototype._sendMessageToBackend.apply(this, params);
+ }
+
+ this[methodName] = sendMessage;
+
+ /**
+ * @this {InspectorBackendClass.AgentPrototype}
+ */
+ function invoke(vararg)
+ {
+ var params = [domainAndMethod].concat(Array.prototype.slice.call(arguments));
+ InspectorBackendClass.AgentPrototype.prototype._invoke.apply(this, params);
+ }
+
+ this["invoke_" + methodName] = invoke;
+
+ this._replyArgs[domainAndMethod] = replyArgs;
+ if (hasErrorData)
+ this._hasErrorData[domainAndMethod] = true;
+
+ },
+
+ /**
+ * @param {string} method
+ * @param {!Array.<!Object>} signature
+ * @param {*} vararg
+ * @private
+ */
+ _sendMessageToBackend: function(method, signature, vararg)
+ {
+ var args = Array.prototype.slice.call(arguments, 2);
+ var callback = (args.length && typeof args[args.length - 1] === "function") ? args.pop() : null;
+
+ var params = {};
+ var hasParams = false;
+ for (var i = 0; i < signature.length; ++i) {
+ var param = signature[i];
+ var paramName = param["name"];
+ var typeName = param["type"];
+ var optionalFlag = param["optional"];
+
+ if (!args.length && !optionalFlag) {
+ console.error("Protocol Error: Invalid number of arguments for method '" + method + "' call. It must have the following arguments '" + JSON.stringify(signature) + "'.");
+ return;
+ }
+
+ var value = args.shift();
+ if (optionalFlag && typeof value === "undefined") {
+ continue;
+ }
+
+ if (typeof value !== typeName) {
+ console.error("Protocol Error: Invalid type of argument '" + paramName + "' for method '" + method + "' call. It must be '" + typeName + "' but it is '" + typeof value + "'.");
+ return;
+ }
+
+ params[paramName] = value;
+ hasParams = true;
+ }
+
+ if (args.length === 1 && !callback && (typeof args[0] !== "undefined")) {
+ console.error("Protocol Error: Optional callback argument for method '" + method + "' call must be a function but its type is '" + typeof args[0] + "'.");
+ return;
+ }
+
+ this._connection._wrapCallbackAndSendMessageObject(this._domain, method, hasParams ? params : null, callback);
+ },
+
+ /**
+ * @param {string} method
+ * @param {?Object} args
+ * @param {?function(*)} callback
+ */
+ _invoke: function(method, args, callback)
+ {
+ this._connection._wrapCallbackAndSendMessageObject(this._domain, method, args, callback);
+ },
+
+ /**
+ * @param {number} messageId
+ * @param {!Object} messageObject
+ * @param {string} methodName
+ * @param {function(!Array.<*>)} callback
+ */
+ dispatchResponse: function(messageId, messageObject, methodName, callback)
+ {
+ if (messageObject.error && messageObject.error.code !== -32000)
+ console.error("Request with id = " + messageObject.id + " failed. " + JSON.stringify(messageObject.error));
+
+ var argumentsArray = [];
+ argumentsArray[0] = messageObject.error ? messageObject.error.message: null;
+
+ if (this._hasErrorData[methodName])
+ argumentsArray[1] = messageObject.error ? messageObject.error.data : null;
+
+ if (messageObject.result) {
+ var paramNames = this._replyArgs[methodName] || [];
+ for (var i = 0; i < paramNames.length; ++i)
+ argumentsArray.push(messageObject.result[paramNames[i]]);
+ }
+
+ callback.apply(null, argumentsArray);
+ }
+}
+
+/**
+ * @constructor
+ */
+InspectorBackendClass.DispatcherPrototype = function()
+{
+ this._eventArgs = {};
+ this._dispatcher = null;
+}
+
+InspectorBackendClass.DispatcherPrototype.prototype = {
+
+ /**
+ * @param {string} eventName
+ * @param {!Object} params
+ */
+ registerEvent: function(eventName, params)
+ {
+ this._eventArgs[eventName] = params
+ },
+
+ /**
+ * @param {!Object} dispatcher
+ */
+ setDomainDispatcher: function(dispatcher)
+ {
+ this._dispatcher = dispatcher;
+ },
+
+ /**
+ * @param {string} functionName
+ * @param {!Object} messageObject
+ */
+ dispatch: function(functionName, messageObject)
+ {
+ if (!this._dispatcher)
+ return;
+
+ if (!(functionName in this._dispatcher)) {
+ console.error("Protocol Error: Attempted to dispatch an unimplemented method '" + messageObject.method + "'");
+ return;
+ }
+
+ if (!this._eventArgs[messageObject.method]) {
+ console.error("Protocol Error: Attempted to dispatch an unspecified method '" + messageObject.method + "'");
+ return;
+ }
+
+ var params = [];
+ if (messageObject.params) {
+ var paramNames = this._eventArgs[messageObject.method];
+ for (var i = 0; i < paramNames.length; ++i)
+ params.push(messageObject.params[paramNames[i]]);
+ }
+
+ var processingStartTime;
+ if (InspectorBackendClass.Options.dumpInspectorTimeStats)
+ processingStartTime = Date.now();
+
+ this._dispatcher[functionName].apply(this._dispatcher, params);
+
+ if (InspectorBackendClass.Options.dumpInspectorTimeStats)
+ console.log("time-stats: " + messageObject.method + " = " + (Date.now() - processingStartTime));
+ }
+
+}
+
+InspectorBackendClass.Options = {
+ dumpInspectorTimeStats: false,
+ dumpInspectorProtocolMessages: false
+}
+
+InspectorBackend = new InspectorBackendClass();