| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 clientCallback(new constructor(value)); | 195 clientCallback(new constructor(value)); |
| 196 else | 196 else |
| 197 clientCallback(value); | 197 clientCallback(value); |
| 198 } | 198 } |
| 199 return callbackWrapper; | 199 return callbackWrapper; |
| 200 } | 200 } |
| 201 } | 201 } |
| 202 | 202 |
| 203 /** | 203 /** |
| 204 * @constructor | 204 * @constructor |
| 205 * @extends {WebInspector.Object} | 205 * @param {!InspectorBackendClass.Channel} channel |
| 206 * @param {function(string)} disconnectedCallback |
| 206 */ | 207 */ |
| 207 InspectorBackendClass.Connection = function() | 208 InspectorBackendClass.Connection = function(channel, disconnectedCallback) |
| 208 { | 209 { |
| 210 this._channel = channel; |
| 211 this._disconnectedCallback = disconnectedCallback; |
| 209 this._lastMessageId = 1; | 212 this._lastMessageId = 1; |
| 210 this._pendingResponsesCount = 0; | 213 this._pendingResponsesCount = 0; |
| 211 this._agents = {}; | 214 this._agents = {}; |
| 212 this._dispatchers = {}; | 215 this._dispatchers = {}; |
| 213 this._callbacks = {}; | 216 this._callbacks = {}; |
| 214 this._initialize(InspectorBackend._agentPrototypes, InspectorBackend._dispat
cherPrototypes); | 217 this._initialize(InspectorBackend._agentPrototypes, InspectorBackend._dispat
cherPrototypes); |
| 215 this._isConnected = true; | 218 this._isConnected = true; |
| 219 this._eventListeners = [ |
| 220 this._channel.addEventListener(InspectorBackendClass.Channel.Events.Chan
nelClosed, this._channelClosed, this), |
| 221 this._channel.addEventListener(InspectorBackendClass.Channel.Events.Mess
ageReceived, this._messageReceived, this) |
| 222 ]; |
| 223 if (!InspectorBackendClass.mainConnectionForTesting) |
| 224 InspectorBackendClass.mainConnectionForTesting = this; |
| 216 } | 225 } |
| 217 | 226 |
| 218 /** @enum {symbol} */ | 227 /** @type {?InspectorBackendClass.Connection} */ |
| 219 InspectorBackendClass.Connection.Events = { | 228 InspectorBackendClass.mainConnectionForTesting = null; |
| 220 Disconnected: Symbol("Disconnected") | |
| 221 } | |
| 222 | 229 |
| 223 InspectorBackendClass.Connection.prototype = { | 230 InspectorBackendClass.Connection.prototype = { |
| 224 /** | 231 /** |
| 232 * @return {!Object.<string, !Object>} |
| 233 */ |
| 234 agentsMap: function() |
| 235 { |
| 236 return this._agents; |
| 237 }, |
| 238 |
| 239 /** |
| 240 * @param {string} domain |
| 241 * @param {!Object} dispatcher |
| 242 */ |
| 243 registerDispatcher: function(domain, dispatcher) |
| 244 { |
| 245 if (!this._dispatchers[domain]) |
| 246 return; |
| 247 |
| 248 this._dispatchers[domain].setDomainDispatcher(dispatcher); |
| 249 }, |
| 250 |
| 251 /** |
| 225 * @param {!Object.<string, !InspectorBackendClass.AgentPrototype>} agentPro
totypes | 252 * @param {!Object.<string, !InspectorBackendClass.AgentPrototype>} agentPro
totypes |
| 226 * @param {!Object.<string, !InspectorBackendClass.DispatcherPrototype>} dis
patcherPrototypes | 253 * @param {!Object.<string, !InspectorBackendClass.DispatcherPrototype>} dis
patcherPrototypes |
| 227 */ | 254 */ |
| 228 _initialize: function(agentPrototypes, dispatcherPrototypes) | 255 _initialize: function(agentPrototypes, dispatcherPrototypes) |
| 229 { | 256 { |
| 230 for (var domain in agentPrototypes) { | 257 for (var domain in agentPrototypes) { |
| 231 this._agents[domain] = Object.create(agentPrototypes[domain]); | 258 this._agents[domain] = Object.create(agentPrototypes[domain]); |
| 232 this._agents[domain].setConnection(this); | 259 this._agents[domain].setConnection(this); |
| 233 } | 260 } |
| 234 | 261 |
| 235 for (var domain in dispatcherPrototypes) | 262 for (var domain in dispatcherPrototypes) |
| 236 this._dispatchers[domain] = Object.create(dispatcherPrototypes[domai
n]); | 263 this._dispatchers[domain] = Object.create(dispatcherPrototypes[domai
n]); |
| 237 }, | 264 }, |
| 238 | 265 |
| 239 /** | 266 /** |
| 240 * @return {number} | 267 * @return {number} |
| 241 */ | 268 */ |
| 242 nextMessageId: function() | 269 _nextMessageId: function() |
| 243 { | 270 { |
| 244 return this._lastMessageId++; | 271 return this._lastMessageId++; |
| 245 }, | 272 }, |
| 246 | 273 |
| 247 /** | 274 /** |
| 248 * @param {string} domain | 275 * @param {string} domain |
| 249 * @return {!InspectorBackendClass.AgentPrototype} | 276 * @return {!InspectorBackendClass.AgentPrototype} |
| 250 */ | 277 */ |
| 251 agent: function(domain) | 278 _agent: function(domain) |
| 252 { | 279 { |
| 253 return this._agents[domain]; | 280 return this._agents[domain]; |
| 254 }, | 281 }, |
| 255 | 282 |
| 256 /** | 283 /** |
| 257 * @return {!Object.<string, !Object>} | |
| 258 */ | |
| 259 agentsMap: function() | |
| 260 { | |
| 261 return this._agents; | |
| 262 }, | |
| 263 | |
| 264 /** | |
| 265 * @param {string} domain | 284 * @param {string} domain |
| 266 * @param {string} method | 285 * @param {string} method |
| 267 * @param {?Object} params | 286 * @param {?Object} params |
| 268 * @param {?function(*)} callback | 287 * @param {?function(*)} callback |
| 269 */ | 288 */ |
| 270 _wrapCallbackAndSendMessageObject: function(domain, method, params, callback
) | 289 _wrapCallbackAndSendMessageObject: function(domain, method, params, callback
) |
| 271 { | 290 { |
| 272 if (!this._isConnected && callback) { | 291 if (!this._isConnected) { |
| 273 this._dispatchConnectionErrorResponse(domain, method, callback); | 292 if (callback) |
| 293 this._dispatchConnectionErrorResponse(domain, method, callback); |
| 274 return; | 294 return; |
| 275 } | 295 } |
| 276 | 296 |
| 277 var messageObject = {}; | 297 var messageObject = {}; |
| 278 var messageId = this.nextMessageId(); | 298 var messageId = this._nextMessageId(); |
| 279 messageObject.id = messageId; | 299 messageObject.id = messageId; |
| 280 messageObject.method = method; | 300 messageObject.method = method; |
| 281 if (params) | 301 if (params) |
| 282 messageObject.params = params; | 302 messageObject.params = params; |
| 283 | 303 |
| 284 var wrappedCallback = this._wrap(callback, domain, method); | 304 var wrappedCallback = this._wrap(callback, domain, method); |
| 285 | 305 |
| 286 if (InspectorBackendClass.Options.dumpInspectorProtocolMessages) | 306 if (InspectorBackendClass.Options.dumpInspectorProtocolMessages) |
| 287 this._dumpProtocolMessage("frontend: " + JSON.stringify(messageObjec
t)); | 307 this._dumpProtocolMessage("frontend: " + JSON.stringify(messageObjec
t)); |
| 288 | 308 |
| 289 this.sendMessage(messageObject); | 309 this._channel.sendMessage(JSON.stringify(messageObject)); |
| 290 ++this._pendingResponsesCount; | 310 ++this._pendingResponsesCount; |
| 291 this._callbacks[messageId] = wrappedCallback; | 311 this._callbacks[messageId] = wrappedCallback; |
| 292 }, | 312 }, |
| 293 | 313 |
| 294 /** | 314 /** |
| 295 * @param {?function(*)} callback | 315 * @param {?function(*)} callback |
| 296 * @param {string} method | 316 * @param {string} method |
| 297 * @param {string} domain | 317 * @param {string} domain |
| 298 * @return {function(*)} | 318 * @return {function(*)} |
| 299 */ | 319 */ |
| 300 _wrap: function(callback, domain, method) | 320 _wrap: function(callback, domain, method) |
| 301 { | 321 { |
| 302 if (!callback) | 322 if (!callback) |
| 303 callback = function() {}; | 323 callback = function() {}; |
| 304 | 324 |
| 305 callback.methodName = method; | 325 callback.methodName = method; |
| 306 callback.domain = domain; | 326 callback.domain = domain; |
| 307 if (InspectorBackendClass.Options.dumpInspectorTimeStats) | 327 if (InspectorBackendClass.Options.dumpInspectorTimeStats) |
| 308 callback.sendRequestTime = Date.now(); | 328 callback.sendRequestTime = Date.now(); |
| 309 | 329 |
| 310 return callback; | 330 return callback; |
| 311 }, | 331 }, |
| 312 | 332 |
| 313 /** | 333 /** |
| 314 * @param {!Object} messageObject | |
| 315 */ | |
| 316 sendMessage: function(messageObject) | |
| 317 { | |
| 318 throw "Not implemented"; | |
| 319 }, | |
| 320 | |
| 321 /** | |
| 322 * @param {string} method | 334 * @param {string} method |
| 323 * @param {?Object} params | 335 * @param {?Object} params |
| 324 * @param {?function(...*)} callback | 336 * @param {?function(...*)} callback |
| 325 */ | 337 */ |
| 326 sendRawMessageForTesting: function(method, params, callback) | 338 _sendRawMessageForTesting: function(method, params, callback) |
| 327 { | 339 { |
| 328 var domain = method.split(".")[0]; | 340 var domain = method.split(".")[0]; |
| 329 this._wrapCallbackAndSendMessageObject(domain, method, params, callback)
; | 341 this._wrapCallbackAndSendMessageObject(domain, method, params, callback)
; |
| 330 }, | 342 }, |
| 331 | 343 |
| 332 /** | 344 /** |
| 333 * @param {!Object|string} message | 345 * @param {!WebInspector.Event} event |
| 334 */ | 346 */ |
| 335 dispatch: function(message) | 347 _messageReceived: function(event) |
| 336 { | 348 { |
| 349 var message = /** @type {!Object|string} */ (event.data); |
| 337 if (InspectorBackendClass.Options.dumpInspectorProtocolMessages) | 350 if (InspectorBackendClass.Options.dumpInspectorProtocolMessages) |
| 338 this._dumpProtocolMessage("backend: " + ((typeof message === "string
") ? message : JSON.stringify(message))); | 351 this._dumpProtocolMessage("backend: " + ((typeof message === "string
") ? message : JSON.stringify(message))); |
| 339 | 352 |
| 340 var messageObject = /** @type {!Object} */ ((typeof message === "string"
) ? JSON.parse(message) : message); | 353 var messageObject = /** @type {!Object} */ ((typeof message === "string"
) ? JSON.parse(message) : message); |
| 341 | 354 |
| 342 if ("id" in messageObject) { // just a response for some request | 355 if ("id" in messageObject) { // just a response for some request |
| 343 var callback = this._callbacks[messageObject.id]; | 356 var callback = this._callbacks[messageObject.id]; |
| 344 if (!callback) { | 357 if (!callback) { |
| 345 InspectorBackendClass.reportProtocolError("Protocol Error: the m
essage with wrong id", messageObject); | 358 InspectorBackendClass.reportProtocolError("Protocol Error: the m
essage with wrong id", messageObject); |
| 346 return; | 359 return; |
| 347 } | 360 } |
| 348 | 361 |
| 349 var processingStartTime; | 362 var processingStartTime; |
| 350 if (InspectorBackendClass.Options.dumpInspectorTimeStats) | 363 if (InspectorBackendClass.Options.dumpInspectorTimeStats) |
| 351 processingStartTime = Date.now(); | 364 processingStartTime = Date.now(); |
| 352 | 365 |
| 353 this.agent(callback.domain).dispatchResponse(messageObject, callback
.methodName, callback); | 366 this._agent(callback.domain).dispatchResponse(messageObject, callbac
k.methodName, callback); |
| 354 --this._pendingResponsesCount; | 367 --this._pendingResponsesCount; |
| 355 delete this._callbacks[messageObject.id]; | 368 delete this._callbacks[messageObject.id]; |
| 356 | 369 |
| 357 if (InspectorBackendClass.Options.dumpInspectorTimeStats) | 370 if (InspectorBackendClass.Options.dumpInspectorTimeStats) |
| 358 console.log("time-stats: " + callback.methodName + " = " + (proc
essingStartTime - callback.sendRequestTime) + " + " + (Date.now() - processingSt
artTime)); | 371 console.log("time-stats: " + callback.methodName + " = " + (proc
essingStartTime - callback.sendRequestTime) + " + " + (Date.now() - processingSt
artTime)); |
| 359 | 372 |
| 360 if (this._scripts && !this._pendingResponsesCount) | 373 if (this._scripts && !this._pendingResponsesCount) |
| 361 this.deprecatedRunAfterPendingDispatches(); | 374 this.deprecatedRunAfterPendingDispatches(); |
| 362 return; | |
| 363 } else { | 375 } else { |
| 376 if (!("method" in messageObject)) { |
| 377 InspectorBackendClass.reportProtocolError("Protocol Error: the m
essage without method", messageObject); |
| 378 return; |
| 379 } |
| 380 |
| 364 var method = messageObject.method.split("."); | 381 var method = messageObject.method.split("."); |
| 365 var domainName = method[0]; | 382 var domainName = method[0]; |
| 366 if (!(domainName in this._dispatchers)) { | 383 if (!(domainName in this._dispatchers)) { |
| 367 InspectorBackendClass.reportProtocolError("Protocol Error: the m
essage " + messageObject.method + " is for non-existing domain '" + domainName +
"'", messageObject); | 384 InspectorBackendClass.reportProtocolError("Protocol Error: the m
essage " + messageObject.method + " is for non-existing domain '" + domainName +
"'", messageObject); |
| 368 return; | 385 return; |
| 369 } | 386 } |
| 370 | 387 |
| 371 this._dispatchers[domainName].dispatch(method[1], messageObject); | 388 this._dispatchers[domainName].dispatch(method[1], messageObject); |
| 372 } | 389 } |
| 373 | |
| 374 }, | 390 }, |
| 375 | 391 |
| 376 /** | 392 /** |
| 377 * @param {string} domain | |
| 378 * @param {!Object} dispatcher | |
| 379 */ | |
| 380 registerDispatcher: function(domain, dispatcher) | |
| 381 { | |
| 382 if (!this._dispatchers[domain]) | |
| 383 return; | |
| 384 | |
| 385 this._dispatchers[domain].setDomainDispatcher(dispatcher); | |
| 386 }, | |
| 387 | |
| 388 /** | |
| 389 * @param {function()=} script | 393 * @param {function()=} script |
| 390 */ | 394 */ |
| 391 deprecatedRunAfterPendingDispatches: function(script) | 395 deprecatedRunAfterPendingDispatches: function(script) |
| 392 { | 396 { |
| 393 if (!this._scripts) | 397 if (!this._scripts) |
| 394 this._scripts = []; | 398 this._scripts = []; |
| 395 | 399 |
| 396 if (script) | 400 if (script) |
| 397 this._scripts.push(script); | 401 this._scripts.push(script); |
| 398 | 402 |
| 399 // Execute all promises. | 403 // Execute all promises. |
| 400 setTimeout(function() { | 404 setTimeout(function() { |
| 401 if (!this._pendingResponsesCount) | 405 if (!this._pendingResponsesCount) |
| 402 this._executeAfterPendingDispatches(); | 406 this._executeAfterPendingDispatches(); |
| 403 else | 407 else |
| 404 this.deprecatedRunAfterPendingDispatches(); | 408 this.deprecatedRunAfterPendingDispatches(); |
| 405 }.bind(this), 0); | 409 }.bind(this), 0); |
| 406 }, | 410 }, |
| 407 | 411 |
| 408 _executeAfterPendingDispatches: function() | 412 _executeAfterPendingDispatches: function() |
| 409 { | 413 { |
| 410 if (!this._pendingResponsesCount) { | 414 if (!this._pendingResponsesCount) { |
| 411 var scripts = this._scripts; | 415 var scripts = this._scripts; |
| 412 this._scripts = []; | 416 this._scripts = []; |
| 413 for (var id = 0; id < scripts.length; ++id) | 417 for (var id = 0; id < scripts.length; ++id) |
| 414 scripts[id].call(this); | 418 scripts[id].call(this); |
| 415 } | 419 } |
| 416 }, | 420 }, |
| 417 | 421 |
| 422 /** |
| 423 * @param {!Object|string} message |
| 424 */ |
| 418 _dumpProtocolMessage: function(message) | 425 _dumpProtocolMessage: function(message) |
| 419 { | 426 { |
| 420 console.log(message); | 427 console.log(message); |
| 421 }, | 428 }, |
| 422 | 429 |
| 423 close: function() | 430 /** |
| 431 * @param {!WebInspector.Event} event |
| 432 */ |
| 433 _channelClosed: function(event) |
| 424 { | 434 { |
| 425 this.forceClose(); | 435 WebInspector.EventTarget.removeEventListeners(this._eventListeners); |
| 426 this.connectionClosed("force close"); | 436 var reason = /** @type {string} */ (event.data); |
| 427 }, | |
| 428 | |
| 429 /** | |
| 430 * @protected | |
| 431 */ | |
| 432 forceClose: function() | |
| 433 { | |
| 434 }, | |
| 435 | |
| 436 /** | |
| 437 * @protected | |
| 438 * @param {string} reason | |
| 439 */ | |
| 440 connectionClosed: function(reason) | |
| 441 { | |
| 442 this._isConnected = false; | 437 this._isConnected = false; |
| 443 this._runPendingCallbacks(); | 438 this._runPendingCallbacks(); |
| 444 this.dispatchEventToListeners(InspectorBackendClass.Connection.Events.Di
sconnected, {reason: reason}); | 439 this._disconnectedCallback.call(null, reason); |
| 440 this._disconnectedCallback = null; |
| 445 }, | 441 }, |
| 446 | 442 |
| 447 _runPendingCallbacks: function() | 443 _runPendingCallbacks: function() |
| 448 { | 444 { |
| 449 var keys = Object.keys(this._callbacks).map(function(num) { return parse
Int(num, 10); }); | 445 var keys = Object.keys(this._callbacks).map(function(num) { return parse
Int(num, 10); }); |
| 450 for (var i = 0; i < keys.length; ++i) { | 446 for (var i = 0; i < keys.length; ++i) { |
| 451 var callback = this._callbacks[keys[i]]; | 447 var callback = this._callbacks[keys[i]]; |
| 452 this._dispatchConnectionErrorResponse(callback.domain, callback.meth
odName, callback); | 448 this._dispatchConnectionErrorResponse(callback.domain, callback.meth
odName, callback); |
| 453 } | 449 } |
| 454 this._callbacks = {}; | 450 this._callbacks = {}; |
| 455 }, | 451 }, |
| 456 | 452 |
| 457 /** | 453 /** |
| 458 * @param {string} domain | 454 * @param {string} domain |
| 459 * @param {string} methodName | 455 * @param {string} methodName |
| 460 * @param {function(*)} callback | 456 * @param {function(*)} callback |
| 461 */ | 457 */ |
| 462 _dispatchConnectionErrorResponse: function(domain, methodName, callback) | 458 _dispatchConnectionErrorResponse: function(domain, methodName, callback) |
| 463 { | 459 { |
| 464 var error = { message: "Connection is closed, can't dispatch pending " +
methodName, code: InspectorBackendClass._DevToolsErrorCode, data: null}; | 460 var error = { message: "Connection is closed, can't dispatch pending " +
methodName, code: InspectorBackendClass._DevToolsErrorCode, data: null}; |
| 465 var messageObject = {error: error}; | 461 var messageObject = {error: error}; |
| 466 setTimeout(InspectorBackendClass.AgentPrototype.prototype.dispatchRespon
se.bind(this.agent(domain), messageObject, methodName, callback), 0); | 462 setTimeout(InspectorBackendClass.AgentPrototype.prototype.dispatchRespon
se.bind(this._agent(domain), messageObject, methodName, callback), 0); |
| 467 }, | 463 } |
| 464 } |
| 465 |
| 466 |
| 467 /** |
| 468 * @interface |
| 469 * @extends {WebInspector.EventTarget} |
| 470 */ |
| 471 InspectorBackendClass.Channel = function() |
| 472 { |
| 473 } |
| 474 |
| 475 /** @enum {symbol} */ |
| 476 InspectorBackendClass.Channel.Events = { |
| 477 MessageReceived: Symbol("MessageReceived"), |
| 478 ChannelClosed: Symbol("ChannelClosed") |
| 479 } |
| 480 |
| 481 InspectorBackendClass.Channel.prototype = { |
| 482 /** |
| 483 * @param {string} message |
| 484 */ |
| 485 sendMessage: function(message) { }, |
| 468 | 486 |
| 469 /** | 487 /** |
| 470 * @return {boolean} | 488 * @param {function()} callback |
| 471 */ | 489 */ |
| 472 isClosed: function() | 490 reconnect: function(callback) { }, |
| 473 { | 491 } |
| 474 return !this._isConnected; | |
| 475 }, | |
| 476 | 492 |
| 477 /** | |
| 478 * @param {!Array.<string>} domains | |
| 479 */ | |
| 480 suppressErrorsForDomains: function(domains) | |
| 481 { | |
| 482 domains.forEach(function(domain) { this._agents[domain].suppressErrorLog
ging(); }, this); | |
| 483 }, | |
| 484 | |
| 485 __proto__: WebInspector.Object.prototype | |
| 486 | |
| 487 } | |
| 488 | 493 |
| 489 /** | 494 /** |
| 490 * @constructor | 495 * @constructor |
| 491 * @param {string} domain | 496 * @param {string} domain |
| 492 */ | 497 */ |
| 493 InspectorBackendClass.AgentPrototype = function(domain) | 498 InspectorBackendClass.AgentPrototype = function(domain) |
| 494 { | 499 { |
| 495 this._replyArgs = {}; | 500 this._replyArgs = {}; |
| 496 this._hasErrorData = {}; | 501 this._hasErrorData = {}; |
| 497 this._domain = domain; | 502 this._domain = domain; |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 } | 752 } |
| 748 } | 753 } |
| 749 | 754 |
| 750 InspectorBackendClass.Options = { | 755 InspectorBackendClass.Options = { |
| 751 dumpInspectorTimeStats: false, | 756 dumpInspectorTimeStats: false, |
| 752 dumpInspectorProtocolMessages: false, | 757 dumpInspectorProtocolMessages: false, |
| 753 suppressRequestErrors: false | 758 suppressRequestErrors: false |
| 754 } | 759 } |
| 755 | 760 |
| 756 InspectorBackend = new InspectorBackendClass(); | 761 InspectorBackend = new InspectorBackendClass(); |
| 762 |
| 763 /** |
| 764 * @param {string} method |
| 765 * @param {?Object} params |
| 766 * @return {!Promise} |
| 767 */ |
| 768 WebInspector.sendOverProtocol = function(method, params) |
| 769 { |
| 770 var connection = InspectorBackendClass.mainConnectionForTesting; |
| 771 return new Promise((resolve, reject) => { |
| 772 connection._sendRawMessageForTesting(method, params, (err, result) => { |
| 773 if (err) |
| 774 return reject(err); |
| 775 return resolve(result); |
| 776 }); |
| 777 }); |
| 778 } |
| OLD | NEW |