Commit ea8b4707 authored by Dmitry Gozman's avatar Dmitry Gozman Committed by Commit Bot

[DevTools] Switch frontend to flatten protocol

Introducing SessionRouter - a common router on top of raw connection
which routes messages between multiple sessions based on sessionId.

A couple of cleanups along the way.

Bug: 775132
Change-Id: I3f773f7ead4d1729d9b936c69b4cdda2d6d20996
Reviewed-on: https://chromium-review.googlesource.com/c/1321854
Commit-Queue: Dmitry Gozman <dgozman@chromium.org>
Reviewed-by: default avatarAlexei Filippov <alph@chromium.org>
Reviewed-by: default avatarPavel Feldman <pfeldman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#607286}
parent b751b6f3
......@@ -27,7 +27,7 @@
var backendCallCount = 0;
var nodeId;
function onBackendCall(domain, method, params) {
function onBackendCall(sessionId, domain, method, params) {
if (method === 'CSS.getComputedStyleForNode' && params.nodeId === nodeId)
++backendCallCount;
}
......@@ -35,7 +35,7 @@
function step1(node) {
var callsLeft = 2;
nodeId = node.id;
TestRunner.addSniffer(Protocol.TargetBase.prototype, '_wrapCallbackAndSendMessageObject', onBackendCall, true);
TestRunner.addSniffer(Protocol.SessionRouter.prototype, 'sendMessage', onBackendCall, true);
TestRunner.cssModel.computedStylePromise(nodeId).then(styleCallback);
TestRunner.cssModel.computedStylePromise(nodeId).then(styleCallback);
function styleCallback() {
......
......@@ -5,7 +5,7 @@
(async function() {
TestRunner.addResult(`Tests correctness of promisified protocol commands.\n`);
Protocol.InspectorBackend.Options.suppressRequestErrors = false;
Protocol.test.suppressRequestErrors = false;
function dumpArgument(name, value) {
TestRunner.addResult(name + ' result: ' + (typeof value === 'string' ? value : JSON.stringify(value)));
}
......
......@@ -7,7 +7,7 @@ frontend: {"id":<number>,"method":"Overlay.setPausedInDebuggerMessage"}
frontend: {"id":<number>,"method":"DOM.disable"}
frontend: {"id":<number>,"method":"CSS.disable"}
frontend: {"id":<number>,"method":"Overlay.setSuspended","params":{"suspended":true}}
frontend: {"id":<number>,"method":"Target.setAutoAttach","params":{"autoAttach":true,"waitForDebuggerOnStart":false}}
frontend: {"id":<number>,"method":"Target.setAutoAttach","params":{"autoAttach":true,"waitForDebuggerOnStart":false,"flatten":true}}
--> SDK.targetManager.resumeAllTargets();
frontend: {"id":<number>,"method":"Debugger.enable"}
......@@ -16,7 +16,7 @@ frontend: {"id":<number>,"method":"Debugger.setAsyncCallStackDepth","params":{"m
frontend: {"id":<number>,"method":"DOM.enable"}
frontend: {"id":<number>,"method":"CSS.enable"}
frontend: {"id":<number>,"method":"Overlay.setSuspended","params":{"suspended":false}}
frontend: {"id":<number>,"method":"Target.setAutoAttach","params":{"autoAttach":true,"waitForDebuggerOnStart":true}}
frontend: {"id":<number>,"method":"Target.setAutoAttach","params":{"autoAttach":true,"waitForDebuggerOnStart":true,"flatten":true}}
--> done
......@@ -9,8 +9,7 @@
function collectMessages(message) {
messages.push(message);
}
Protocol.TargetBase.prototype._dumpProtocolMessage = collectMessages;
Protocol.InspectorBackend.Options.dumpInspectorProtocolMessages = 1;
Protocol.test.dumpProtocol = collectMessages;
messages.push('--> SDK.targetManager.suspendAllTargets();');
await SDK.targetManager.suspendAllTargets();
messages.push('');
......@@ -18,7 +17,7 @@
await SDK.targetManager.resumeAllTargets();
messages.push('');
messages.push('--> done');
Protocol.InspectorBackend.Options.dumpInspectorProtocolMessages = 0;
Protocol.test.dumpProtocol = null;
for (var i = 0; i < messages.length; ++i) {
var message = messages[i];
if (message.startsWith('backend'))
......
......@@ -17,8 +17,8 @@
TestRunner.RuntimeAgent.evaluate('true', 'test');
TestRunner.RuntimeAgent.evaluate('true', 'test', function() {});
TestRunner.RuntimeAgent.evaluate('true', 'test', undefined, function() {});
TestRunner.mainTarget._onMessage('{"method": "wrongDomain.something-strange", "params": {}}');
TestRunner.mainTarget._onMessage('{"method": "Inspector.something-strange", "params": {}}');
TestRunner.mainTarget._router._onMessage('{"method": "wrongDomain.something-strange", "params": {}}');
TestRunner.mainTarget._router._onMessage('{"method": "Inspector.something-strange", "params": {}}');
TestRunner.completeTest();
})();
......@@ -8,7 +8,7 @@
await TestRunner.navigatePromise('resources/screen-orientation-resource.html');
Protocol.InspectorBackend.Options.suppressRequestErrors = false;
Protocol.test.suppressRequestErrors = false;
function addDumpResult(next) {
TestRunner.evaluateInPage('dump()', dumpCallback);
......
......@@ -2,40 +2,14 @@ Tests the way service workers don't enable DOM agent and does enable Debugger ag
Debugger-related command should be issued: {
"id": "<id>",
"method": "Target.sendMessageToTarget",
"params": {
"message": {
"id": "<id>",
"method": "Target.sendMessageToTarget",
"params": {
"message": {
"id": "<id>",
"method": "Debugger.enable"
},
"sessionId": "<id>"
}
},
"sessionId": "<id>"
}
"method": "Debugger.enable",
"sessionId": "<id>"
}
Suspending targets.
Resuming targets.
Debugger-related command should be issued: {
"id": "<id>",
"method": "Target.sendMessageToTarget",
"params": {
"message": {
"id": "<id>",
"method": "Target.sendMessageToTarget",
"params": {
"message": {
"id": "<id>",
"method": "Debugger.enable"
},
"sessionId": "<id>"
}
},
"sessionId": "<id>"
}
"method": "Debugger.enable",
"sessionId": "<id>"
}
......@@ -15,7 +15,7 @@
TestRunner.addSniffer(SDK.MainConnection.prototype, 'sendRawMessage', function(messageString) {
var message = JSON.parse(messageString);
if (!messageString.includes('Target.sendMessageToTarget'))
if (!message.sessionId)
return;
if (messageString.includes('DOM.'))
TestRunner.addResult('DOM-related command should NOT be issued: ' + messageString);
......
......@@ -52,7 +52,10 @@
}
function expandAndDumpConsoleMessages() {
ConsoleTestRunner.expandConsoleMessages(dumpConsoleMessages);
ConsoleTestRunner.expandConsoleMessages(() => {
// This is to handle asynchronous console message rendering through runtime extensions.
setTimeout(dumpConsoleMessages, 0);
});
}
function dumpConsoleMessages() {
......
......@@ -565,7 +565,7 @@
this._waitForTargets(2, callback.bind(this));
function callback() {
Protocol.InspectorBackend.deprecatedRunAfterPendingDispatches(this.releaseControl.bind(this));
Protocol.test.deprecatedRunAfterPendingDispatches(this.releaseControl.bind(this));
}
};
......@@ -1178,7 +1178,7 @@
browserContextIds.push(browserContextId);
const {targetId} = await targetAgent.invoke_createTarget({url: 'about:blank', browserContextId});
await targetAgent.invoke_attachToTarget({targetId});
await targetAgent.invoke_attachToTarget({targetId, flatten: true});
const target = SDK.targetManager.targets().find(target => target.id() === targetId);
const pageAgent = target.pageAgent();
......
......@@ -5,7 +5,7 @@
Audits2.ProtocolService = class extends Common.Object {
constructor() {
super();
/** @type {?Protocol.InspectorBackend.Connection} */
/** @type {?Protocol.Connection} */
this._rawConnection = null;
/** @type {?Services.ServiceManager.Service} */
this._backend = null;
......@@ -19,7 +19,7 @@ Audits2.ProtocolService = class extends Common.Object {
* @return {!Promise<undefined>}
*/
attach() {
return InspectorMain.interceptMainConnection(this._dispatchProtocolMessage.bind(this)).then(rawConnection => {
return SDK.interceptMainConnection(this._dispatchProtocolMessage.bind(this)).then(rawConnection => {
this._rawConnection = rawConnection;
});
}
......@@ -53,7 +53,7 @@ Audits2.ProtocolService = class extends Common.Object {
}
/**
* @param {string} message
* @param {!Object|string} message
*/
_dispatchProtocolMessage(message) {
this._send('dispatchProtocolMessage', {message: message});
......
......@@ -6,18 +6,15 @@
* @implements {Common.Runnable}
*/
InspectorMain.InspectorMain = class extends Common.Object {
constructor() {
super();
/** @type {!Protocol.InspectorBackend.Connection} */
this._mainConnection;
}
/**
* @override
*/
run() {
this._connectAndCreateMainTarget();
InspectorFrontendHost.connectionReady();
SDK.initMainConnection(() => {
const type = Runtime.queryParam('v8only') ? SDK.Target.Type.Node : SDK.Target.Type.Frame;
const target = SDK.targetManager.createTarget('main', Common.UIString('Main'), type, null);
target.runtimeAgent().runIfWaitingForDebugger();
}, Components.TargetDetachedDialog.webSocketConnectionLost);
new InspectorMain.InspectedNodeRevealer();
new InspectorMain.SourcesPanelIndicator();
......@@ -29,40 +26,6 @@ InspectorMain.InspectorMain = class extends Common.Object {
SDK.ResourceTreeModel.reloadAllPages(hard);
});
}
_connectAndCreateMainTarget() {
const type = Runtime.queryParam('v8only') ? SDK.Target.Type.Node : SDK.Target.Type.Frame;
const target = SDK.targetManager.createTarget(
'main', Common.UIString('Main'), type, this._createMainConnection.bind(this), null);
target.runtimeAgent().runIfWaitingForDebugger();
}
/**
* @param {!Protocol.InspectorBackend.Connection.Params} params
* @return {!Protocol.InspectorBackend.Connection}
*/
_createMainConnection(params) {
this._mainConnection =
SDK.createMainConnection(params, () => Components.TargetDetachedDialog.webSocketConnectionLost());
return this._mainConnection;
}
/**
* @param {function(string)} onMessage
* @return {!Promise<!Protocol.InspectorBackend.Connection>}
*/
_interceptMainConnection(onMessage) {
const params = {onMessage: onMessage, onDisconnect: this._connectAndCreateMainTarget.bind(this)};
return this._mainConnection.disconnect().then(this._createMainConnection.bind(this, params));
}
};
/**
* @param {function(string)} onMessage
* @return {!Promise<!Protocol.InspectorBackend.Connection>}
*/
InspectorMain.interceptMainConnection = function(onMessage) {
return self.runtime.sharedInstance(InspectorMain.InspectorMain)._interceptMainConnection(onMessage);
};
/**
......
......@@ -11,17 +11,9 @@ JsMain.JsMain = class extends Common.Object {
*/
run() {
Host.userMetrics.actionTaken(Host.UserMetrics.Action.ConnectToNodeJSDirectly);
const target = SDK.targetManager.createTarget(
'main', Common.UIString('Main'), SDK.Target.Type.Node, this._createMainConnection.bind(this), null);
target.runtimeAgent().runIfWaitingForDebugger();
InspectorFrontendHost.connectionReady();
}
/**
* @param {!Protocol.InspectorBackend.Connection.Params} params
* @return {!Protocol.InspectorBackend.Connection}
*/
_createMainConnection(params) {
return SDK.createMainConnection(params, () => Components.TargetDetachedDialog.webSocketConnectionLost());
SDK.initMainConnection(() => {
const target = SDK.targetManager.createTarget('main', ls`Main`, SDK.Target.Type.Node, null);
target.runtimeAgent().runIfWaitingForDebugger();
}, Components.TargetDetachedDialog.webSocketConnectionLost);
}
};
......@@ -615,7 +615,7 @@ Main.Main.PauseListener = class {
*/
Main.sendOverProtocol = function(method, params) {
return new Promise((resolve, reject) => {
Protocol.InspectorBackend.sendRawMessageForTesting(method, params, (err, ...results) => {
Protocol.test.sendRawMessage(method, params, (err, ...results) => {
if (err)
return reject(err);
return resolve(results);
......
......@@ -11,10 +11,10 @@ NodeMain.NodeMain = class extends Common.Object {
*/
run() {
Host.userMetrics.actionTaken(Host.UserMetrics.Action.ConnectToNodeJSFromFrontend);
const target = SDK.targetManager.createTarget(
'main', Common.UIString('Main'), SDK.Target.Type.Browser, params => new SDK.MainConnection(params), null);
target.setInspectedURL('Node.js');
InspectorFrontendHost.connectionReady();
SDK.initMainConnection(() => {
const target = SDK.targetManager.createTarget('main', Common.UIString('Main'), SDK.Target.Type.Browser, null);
target.setInspectedURL('Node.js');
}, Components.TargetDetachedDialog.webSocketConnectionLost);
}
};
......@@ -30,8 +30,8 @@ NodeMain.NodeChildTargetManager = class extends SDK.SDKModel {
this._targetManager = parentTarget.targetManager();
this._parentTarget = parentTarget;
this._targetAgent = parentTarget.targetAgent();
/** @type {!Map<string, !SDK.ChildConnection>} */
this._childConnections = new Map();
/** @type {!Map<string, !SDK.Target>} */
this._childTargets = new Map();
parentTarget.registerTargetDispatcher(this);
this._targetAgent.setDiscoverTargets(true);
......@@ -63,7 +63,7 @@ NodeMain.NodeChildTargetManager = class extends SDK.SDKModel {
InspectorFrontendHost.events.removeEventListener(
InspectorFrontendHostAPI.Events.DevicesDiscoveryConfigChanged, this._devicesDiscoveryConfigChanged, this);
for (const sessionId of this._childConnections.keys())
for (const sessionId of this._childTargets.keys())
this.detachedFromTarget(sessionId, undefined);
}
......@@ -73,7 +73,7 @@ NodeMain.NodeChildTargetManager = class extends SDK.SDKModel {
*/
targetCreated(targetInfo) {
if (targetInfo.type === 'node' && !targetInfo.attached)
this._targetAgent.attachToTarget(targetInfo.targetId);
this._targetAgent.attachToTarget(targetInfo.targetId, true /* flatten */);
}
/**
......@@ -97,9 +97,10 @@ NodeMain.NodeChildTargetManager = class extends SDK.SDKModel {
* @param {boolean} waitingForDebugger
*/
attachedToTarget(sessionId, targetInfo, waitingForDebugger) {
const name = ls`Node.js: ${targetInfo.url}`;
const target = this._targetManager.createTarget(
targetInfo.targetId, Common.UIString('Node.js: %s', targetInfo.url), SDK.Target.Type.Node,
this._createChildConnection.bind(this, this._targetAgent, sessionId), this._parentTarget);
targetInfo.targetId, name, SDK.Target.Type.Node, this._parentTarget, sessionId);
this._childTargets.set(sessionId, target);
target.runtimeAgent().runIfWaitingForDebugger();
}
......@@ -109,8 +110,8 @@ NodeMain.NodeChildTargetManager = class extends SDK.SDKModel {
* @param {string=} childTargetId
*/
detachedFromTarget(sessionId, childTargetId) {
this._childConnections.get(sessionId).onDisconnect.call(null, 'target terminated');
this._childConnections.delete(sessionId);
this._childTargets.get(sessionId).dispose('target terminated');
this._childTargets.delete(sessionId);
}
/**
......@@ -120,21 +121,7 @@ NodeMain.NodeChildTargetManager = class extends SDK.SDKModel {
* @param {string=} childTargetId
*/
receivedMessageFromTarget(sessionId, message, childTargetId) {
const connection = this._childConnections.get(sessionId);
if (connection)
connection.onMessage.call(null, message);
}
/**
* @param {!Protocol.TargetAgent} agent
* @param {string} sessionId
* @param {!Protocol.InspectorBackend.Connection.Params} params
* @return {!Protocol.InspectorBackend.Connection}
*/
_createChildConnection(agent, sessionId, params) {
const connection = new SDK.ChildConnection(agent, sessionId, params);
this._childConnections.set(sessionId, connection);
return connection;
// We use flatten protocol.
}
};
......
......@@ -6,7 +6,6 @@ ProtocolMonitor.ProtocolMonitor = class extends UI.VBox {
constructor() {
super(true);
this._nodes = [];
this._recordingListeners = null;
this._started = false;
this._startTime = 0;
this._nodeForId = {};
......@@ -151,22 +150,16 @@ ProtocolMonitor.ProtocolMonitor = class extends UI.VBox {
* @param {boolean} recording
*/
_setRecording(recording) {
if (this._recordingListeners) {
Common.EventTarget.removeEventListeners(this._recordingListeners);
this._recordingListeners = null;
}
if (recording) {
this._recordingListeners = [
SDK.targetManager.mainTarget().addEventListener(
Protocol.TargetBase.Events.MessageReceived, this._messageRecieved, this),
SDK.targetManager.mainTarget().addEventListener(Protocol.TargetBase.Events.MessageSent, this._messageSent, this)
];
Protocol.test.onMessageSent = this._messageSent.bind(this);
Protocol.test.onMessageReceived = this._messageRecieved.bind(this);
} else {
Protocol.test.onMessageSent = null;
Protocol.test.onMessageReceived = null;
}
}
_messageRecieved(event) {
const message = event.data.message;
_messageRecieved(message) {
if ('id' in message) {
const node = this._nodeForId[message.id];
if (!node)
......@@ -189,8 +182,7 @@ ProtocolMonitor.ProtocolMonitor = class extends UI.VBox {
this._dataGrid.insertChild(node);
}
_messageSent(event) {
const message = event.data;
_messageSent(message) {
const node = new ProtocolMonitor.ProtocolMonitor.ProtocolNode({
method: message.method,
direction: 'sent',
......
......@@ -17,13 +17,13 @@ SDK.ChildTargetManager = class extends SDK.SDKModel {
/** @type {!Map<string, !Protocol.Target.TargetInfo>} */
this._targetInfos = new Map();
/** @type {!Map<string, !SDK.ChildConnection>} */
this._childConnections = new Map();
/** @type {!Map<string, !SDK.Target>} */
this._childTargets = new Map();
parentTarget.registerTargetDispatcher(this);
this._targetAgent.invoke_setAutoAttach({autoAttach: true, waitForDebuggerOnStart: true});
this._targetAgent.invoke_setAutoAttach({autoAttach: true, waitForDebuggerOnStart: true, flatten: true});
if (!parentTarget.parentTarget()) {
if (!parentTarget.parentTarget() && !Host.isUnderTest()) {
this._targetAgent.setDiscoverTargets(true);
this._targetAgent.setRemoteLocations([{host: 'localhost', port: 9229}]);
}
......@@ -42,7 +42,7 @@ SDK.ChildTargetManager = class extends SDK.SDKModel {
* @return {!Promise}
*/
suspendModel() {
return this._targetAgent.invoke_setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false});
return this._targetAgent.invoke_setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false, flatten: true});
}
/**
......@@ -50,14 +50,14 @@ SDK.ChildTargetManager = class extends SDK.SDKModel {
* @return {!Promise}
*/
resumeModel() {
return this._targetAgent.invoke_setAutoAttach({autoAttach: true, waitForDebuggerOnStart: true});
return this._targetAgent.invoke_setAutoAttach({autoAttach: true, waitForDebuggerOnStart: true, flatten: true});
}
/**
* @override
*/
dispose() {
for (const sessionId of this._childConnections.keys())
for (const sessionId of this._childTargets.keys())
this.detachedFromTarget(sessionId, undefined);
}
......@@ -124,10 +124,9 @@ SDK.ChildTargetManager = class extends SDK.SDKModel {
else if (targetInfo.type === 'service_worker')
type = SDK.Target.Type.ServiceWorker;
const target = this._targetManager.createTarget(
targetInfo.targetId, targetName, type, this._createChildConnection.bind(this, this._targetAgent, sessionId),
this._parentTarget);
const target =
this._targetManager.createTarget(targetInfo.targetId, targetName, type, this._parentTarget, sessionId);
this._childTargets.set(sessionId, target);
if (SDK.ChildTargetManager._attachCallback) {
SDK.ChildTargetManager._attachCallback({target, waitingForDebugger}).then(() => {
......@@ -144,8 +143,8 @@ SDK.ChildTargetManager = class extends SDK.SDKModel {
* @param {string=} childTargetId
*/
detachedFromTarget(sessionId, childTargetId) {
this._childConnections.get(sessionId).onDisconnect.call(null, 'target terminated');
this._childConnections.delete(sessionId);
this._childTargets.get(sessionId).dispose('target terminated');
this._childTargets.delete(sessionId);
}
/**
......@@ -155,21 +154,7 @@ SDK.ChildTargetManager = class extends SDK.SDKModel {
* @param {string=} childTargetId
*/
receivedMessageFromTarget(sessionId, message, childTargetId) {
const connection = this._childConnections.get(sessionId);
if (connection)
connection.onMessage.call(null, message);
}
/**
* @param {!Protocol.TargetAgent} agent
* @param {string} sessionId
* @param {!Protocol.InspectorBackend.Connection.Params} params
* @return {!Protocol.InspectorBackend.Connection}
*/
_createChildConnection(agent, sessionId, params) {
const connection = new SDK.ChildConnection(agent, sessionId, params);
this._childConnections.set(sessionId, connection);
return connection;
// We use flatten protocol.
}
};
......
......@@ -3,17 +3,14 @@
// found in the LICENSE file.
/**
* @unrestricted
* @implements {Protocol.Connection}
*/
SDK.MainConnection = class extends Protocol.InspectorBackend.Connection {
/**
* @param {!Protocol.InspectorBackend.Connection.Params} params
*/
constructor(params) {
super();
this._onMessage = params.onMessage;
this._onDisconnect = params.onDisconnect;
this._disconnected = false;
SDK.MainConnection = class {
constructor() {
this._onMessage = null;
this._onDisconnect = null;
this._messageBuffer = '';
this._messageSize = 0;
this._eventListeners = [
InspectorFrontendHost.events.addEventListener(
InspectorFrontendHostAPI.Events.DispatchMessage, this._dispatchMessage, this),
......@@ -22,12 +19,28 @@ SDK.MainConnection = class extends Protocol.InspectorBackend.Connection {
];
}
/**
* @override
* @param {function((!Object|string))} onMessage
*/
setOnMessage(onMessage) {
this._onMessage = onMessage;
}
/**
* @override
* @param {function(string)} onDisconnect
*/
setOnDisconnect(onDisconnect) {
this._onDisconnect = onDisconnect;
}
/**
* @override
* @param {string} message
*/
sendRawMessage(message) {
if (!this._disconnected)
if (this._onMessage)
InspectorFrontendHost.sendMessageToBackend(message);
}
......@@ -35,7 +48,8 @@ SDK.MainConnection = class extends Protocol.InspectorBackend.Connection {
* @param {!Common.Event} event
*/
_dispatchMessage(event) {
this._onMessage.call(null, /** @type {string} */ (event.data));
if (this._onMessage)
this._onMessage.call(null, /** @type {string} */ (event.data));
}
/**
......@@ -65,12 +79,12 @@ SDK.MainConnection = class extends Protocol.InspectorBackend.Connection {
Common.EventTarget.removeEventListeners(this._eventListeners);
this._onDisconnect = null;
this._onMessage = null;
this._disconnected = true;
let fulfill;
const promise = new Promise(f => fulfill = f);
InspectorFrontendHost.reattach(() => {
onDisconnect.call(null, 'force disconnect');
if (onDisconnect)
onDisconnect.call(null, 'force disconnect');
fulfill();
});
return promise;
......@@ -78,28 +92,46 @@ SDK.MainConnection = class extends Protocol.InspectorBackend.Connection {
};
/**
* @unrestricted
* @implements {Protocol.Connection}
*/
SDK.WebSocketConnection = class extends Protocol.InspectorBackend.Connection {
SDK.WebSocketConnection = class {
/**
* @param {string} url
* @param {function()} onWebSocketDisconnect
* @param {!Protocol.InspectorBackend.Connection.Params} params
*/
constructor(url, onWebSocketDisconnect, params) {
super();
constructor(url, onWebSocketDisconnect) {
this._socket = new WebSocket(url);
this._socket.onerror = this._onError.bind(this);
this._socket.onopen = this._onOpen.bind(this);
this._socket.onmessage = messageEvent => params.onMessage.call(null, /** @type {string} */ (messageEvent.data));
this._socket.onmessage = messageEvent => {
if (this._onMessage)
this._onMessage.call(null, /** @type {string} */ (messageEvent.data));
};
this._socket.onclose = this._onClose.bind(this);
this._onDisconnect = params.onDisconnect;
this._onMessage = null;
this._onDisconnect = null;
this._onWebSocketDisconnect = onWebSocketDisconnect;
this._connected = false;
this._messages = [];
}
/**
* @override
* @param {function((!Object|string))} onMessage
*/
setOnMessage(onMessage) {
this._onMessage = onMessage;
}
/**
* @override
* @param {function(string)} onDisconnect
*/
setOnDisconnect(onDisconnect) {
this._onDisconnect = onDisconnect;
}
_onError() {
this._onWebSocketDisconnect.call(null);
// This is called if error occurred while connecting.
......@@ -153,7 +185,8 @@ SDK.WebSocketConnection = class extends Protocol.InspectorBackend.Connection {
let fulfill;
const promise = new Promise(f => fulfill = f);
this._close(() => {
this._onDisconnect.call(null, 'force disconnect');
if (this._onDisconnect)
this._onDisconnect.call(null, 'force disconnect');
fulfill();
});
return promise;
......@@ -161,16 +194,28 @@ SDK.WebSocketConnection = class extends Protocol.InspectorBackend.Connection {
};
/**
* @unrestricted
* @implements {Protocol.Connection}
*/
SDK.StubConnection = class extends Protocol.InspectorBackend.Connection {
SDK.StubConnection = class {
constructor() {
this._onMessage = null;
this._onDisconnect = null;
}
/**
* @param {!Protocol.InspectorBackend.Connection.Params} params
* @override
* @param {function((!Object|string))} onMessage
*/
constructor(params) {
super();
this._onMessage = params.onMessage;
this._onDisconnect = params.onDisconnect;
setOnMessage(onMessage) {
this._onMessage = onMessage;
}
/**
* @override
* @param {function(string)} onDisconnect
*/
setOnDisconnect(onDisconnect) {
this._onDisconnect = onDisconnect;
}
/**
......@@ -188,10 +233,11 @@ SDK.StubConnection = class extends Protocol.InspectorBackend.Connection {
const messageObject = JSON.parse(message);
const error = {
message: 'This is a stub connection, can\'t dispatch message.',
code: Protocol.InspectorBackend.DevToolsStubErrorCode,
code: Protocol.DevToolsStubErrorCode,
data: messageObject
};
this._onMessage.call(null, {id: messageObject.id, error: error});
if (this._onMessage)
this._onMessage.call(null, {id: messageObject.id, error: error});
}
/**
......@@ -199,59 +245,60 @@ SDK.StubConnection = class extends Protocol.InspectorBackend.Connection {
* @return {!Promise}
*/
disconnect() {
this._onDisconnect.call(null, 'force disconnect');
if (this._onDisconnect)
this._onDisconnect.call(null, 'force disconnect');
this._onDisconnect = null;
this._onMessage = null;
return Promise.resolve();
}
};
SDK.ChildConnection = class extends Protocol.InspectorBackend.Connection {
/**
* @param {!Protocol.TargetAgent} agent
* @param {string} sessionId
* @param {!Protocol.InspectorBackend.Connection.Params} params
*/
constructor(agent, sessionId, params) {
super();
this._agent = agent;
this._sessionId = sessionId;
this.onMessage = params.onMessage;
this.onDisconnect = params.onDisconnect;
}
/**
* @override
* @param {string} message
*/
sendRawMessage(message) {
this._agent.sendMessageToTarget(message, this._sessionId);
}
/**
* @override
* @return {!Promise}
*/
disconnect() {
throw 'Not implemented';
}
/**
* @param {function()} createMainTarget
* @param {function()} websocketConnectionLost
*/
SDK.initMainConnection = function(createMainTarget, websocketConnectionLost) {
SDK._websocketConnectionLost = websocketConnectionLost;
SDK._createMainTarget = createMainTarget;
Protocol.Connection.setFactory(SDK._createMainConnection);
SDK._createMainTarget();
InspectorFrontendHost.connectionReady();
};
/**
* @param {!Protocol.InspectorBackend.Connection.Params} params
* @param {function()} connectionLostCallback
* @return {!Protocol.InspectorBackend.Connection}
* @return {!Protocol.Connection}
*/
SDK.createMainConnection = function(params, connectionLostCallback) {
SDK._createMainConnection = function() {
const wsParam = Runtime.queryParam('ws');
const wssParam = Runtime.queryParam('wss');
if (wsParam || wssParam) {
const ws = wsParam ? `ws://${wsParam}` : `wss://${wssParam}`;
return new SDK.WebSocketConnection(ws, connectionLostCallback, params);
SDK._mainConnection = new SDK.WebSocketConnection(ws, SDK._websocketConnectionLost);
} else if (InspectorFrontendHost.isHostedMode()) {
SDK._mainConnection = new SDK.StubConnection();
} else {
SDK._mainConnection = new SDK.MainConnection();
}
return SDK._mainConnection;
};
/** @type {!Protocol.Connection} */
SDK._mainConnection;
if (InspectorFrontendHost.isHostedMode())
return new SDK.StubConnection(params);
return new SDK.MainConnection(params);
/** @type {function()} */
SDK._createMainTarget;
/** @type {function()} */
SDK._websocketConnectionLost;
/**
* @param {function((!Object|string))} onMessage
* @return {!Promise<!Protocol.Connection>}
*/
SDK.interceptMainConnection = async function(onMessage) {
await SDK._mainConnection.disconnect();
const connection = SDK._createMainConnection();
connection.setOnMessage(onMessage);
connection.setOnDisconnect(SDK._createMainTarget);
return connection;
};
......@@ -13,13 +13,13 @@ SDK.Target = class extends Protocol.TargetBase {
* @param {string} id
* @param {string} name
* @param {!SDK.Target.Type} type
* @param {!Protocol.InspectorBackend.Connection.Factory} connectionFactory
* @param {?SDK.Target} parentTarget
* @param {string} sessionId
* @param {boolean} suspended
*/
constructor(targetManager, id, name, type, connectionFactory, parentTarget, suspended) {
constructor(targetManager, id, name, type, parentTarget, sessionId, suspended) {
const needsNodeJSPatching = type === SDK.Target.Type.Node;
super(connectionFactory, needsNodeJSPatching);
super(needsNodeJSPatching, parentTarget, sessionId);
this._targetManager = targetManager;
this._name = name;
this._inspectedURL = '';
......@@ -135,8 +135,10 @@ SDK.Target = class extends Protocol.TargetBase {
/**
* @override
* @param {string} reason
*/
dispose() {
dispose(reason) {
super.dispose(reason);
this._targetManager.removeTarget(this);
for (const model of this._modelByConstructor.valuesArray())
model.dispose();
......
......@@ -169,12 +169,12 @@ SDK.TargetManager = class extends Common.Object {
* @param {string} id
* @param {string} name
* @param {!SDK.Target.Type} type
* @param {!Protocol.InspectorBackend.Connection.Factory} connectionFactory
* @param {?SDK.Target} parentTarget
* @param {string=} sessionId
* @return {!SDK.Target}
*/
createTarget(id, name, type, connectionFactory, parentTarget) {
const target = new SDK.Target(this, id, name, type, connectionFactory, parentTarget, this._isSuspended);
createTarget(id, name, type, parentTarget, sessionId) {
const target = new SDK.Target(this, id, name, type, parentTarget, sessionId || '', this._isSuspended);
target.createModels(new Set(this._modelObservers.keysArray()));
this._targets.push(target);
......
......@@ -18,6 +18,7 @@ SDKTestRunner.PageMock = class {
this._url = url;
this._type = SDK.Target.Type.Frame;
this._enabledDomains = new Set();
this._children = new Map();
this._mainFrame =
{id: nextId(), loaderId: nextId(), mimeType: 'text/html', securityOrigin: this._url, url: this._url};
......@@ -44,31 +45,43 @@ SDKTestRunner.PageMock = class {
connectAsMainTarget(targetName) {
Bindings.debuggerWorkspaceBinding._resetForTest(TestRunner.mainTarget);
Bindings.resourceMapping._resetForTest(TestRunner.mainTarget);
this._enabledDomains.clear();
SDK.targetManager._targets = [];
const target = SDK.targetManager.createTarget(nextId('mock-target-'), targetName, this._type, params => {
this._enabledDomains.clear();
this._connection = new MockPageConnection(this, params);
const oldFactory = Protocol.Connection._factory;
Protocol.Connection._factory = () => {
this._connection = new MockPageConnection(this);
return this._connection;
});
};
const target = SDK.targetManager.createTarget(nextId('mock-target-'), targetName, this._type, null);
Protocol.Connection._factory = oldFactory;
this._target = target;
return target;
}
connectAsChildTarget(targetName, parentMock) {
const target = SDK.targetManager.createTarget(nextId('mock-target-'), targetName, this._type, params => {
this._enabledDomains.clear();
this._connection = new MockPageConnection(this, params);
return this._connection;
}, parentMock._target);
this._enabledDomains.clear();
this._sessionId = nextId('mock-target-');
this._root = parentMock._root || parentMock;
this._root._children.set(this._sessionId, this);
const target =
SDK.targetManager.createTarget(this._sessionId, targetName, this._type, parentMock._target, this._sessionId);
this._target = target;
return target;
}
disconnect() {
this._connection.disconnect();
if (this._root) {
this._root._children.delete(this._sessionId);
this._target.dispose();
this._root = null;
this._sessionId = null;
} else {
this._connection.disconnect();
this._connection = null;
}
this._target = null;
}
evalScript(url, content, isContentScript) {
......@@ -141,13 +154,6 @@ SDKTestRunner.PageMock = class {
this._fireEvent('Page.domContentEventFired', {timestamp: Date.now() / 1000});
}
close() {
if (this._connection) {
this._connection.disconnect();
this._connection = null;
}
}
_createExecutionContext(frame, isContentScript) {
return {
id: nextId(),
......@@ -207,21 +213,31 @@ SDKTestRunner.PageMock = class {
return true;
}
_dispatch(id, methodName, params) {
_dispatch(sessionId, id, methodName, params) {
if (sessionId) {
const child = this._children.get(sessionId);
if (child)
child._dispatch('', id, methodName, params);
return;
}
const handler = (this._isSupportedDomain(methodName) ? this._dispatchMap[methodName] : null);
if (handler)
return handler.call(this, id, params);
this._sendResponse(
id, undefined,
{message: 'Can\'t handle command ' + methodName, code: Protocol.InspectorBackend.DevToolsStubErrorCode});
id, undefined, {message: 'Can\'t handle command ' + methodName, code: Protocol.DevToolsStubErrorCode});
}
_sendResponse(id, result, error) {
const message = {id: id, result: result, error: error};
this._connection.sendMessageToDevTools(message);
if (this._root) {
message.sessionId = this._sessionId;
this._root._connection.sendMessageToDevTools(message);
} else {
this._connection.sendMessageToDevTools(message);
}
}
_fireEvent(methodName, params) {
......@@ -231,24 +247,35 @@ SDKTestRunner.PageMock = class {
return;
const message = {method: methodName, params: params};
this._connection.sendMessageToDevTools(message);
if (this._root) {
message.sessionId = this._sessionId;
this._root._connection.sendMessageToDevTools(message);
} else {
this._connection.sendMessageToDevTools(message);
}
}
};
MockPageConnection = class {
constructor(page, params) {
constructor(page) {
this._page = page;
this._onMessage = params.onMessage;
this._onDisconnect = params.onDisconnect;
}
setOnMessage(onMessage) {
this._onMessage = onMessage;
}
setOnDisconnect(onDisconnect) {
this._onDisconnect = onDisconnect;
}
sendMessageToDevTools(message) {
setTimeout(() => this._onMessage.call(null, JSON.stringify(message)), 0);
}
sendMessage(domain, message) {
this._page._dispatch(message.id, message.method, message.params);
sendRawMessage(messageString) {
const message = JSON.parse(messageString);
this._page._dispatch(message.sessionId, message.id, message.method, message.params || {});
}
disconnect() {
......
......@@ -504,9 +504,7 @@ TestRunner.check = function(passCondition, failureText) {
* @param {!Function} callback
*/
TestRunner.deprecatedRunAfterPendingDispatches = function(callback) {
const targets = SDK.targetManager.targets();
const promises = targets.map(target => new Promise(resolve => target._deprecatedRunAfterPendingDispatches(resolve)));
Promise.all(promises).then(TestRunner.safeWrap(callback));
Protocol.test.deprecatedRunAfterPendingDispatches(callback);
};
/**
......@@ -641,11 +639,7 @@ TestRunner.markStep = function(title) {
};
TestRunner.startDumpingProtocolMessages = function() {
// TODO(chenwilliam): stop abusing Closure interface which is why
// we need to opt out of type checking here
const untypedConnection = /** @type {*} */ (Protocol.InspectorBackend.Connection);
untypedConnection.prototype._dumpProtocolMessage = self.testRunner.logToStderr.bind(self.testRunner);
Protocol.InspectorBackend.Options.dumpInspectorProtocolMessages = 1;
Protocol.test.dumpProtocol = self.testRunner.logToStderr.bind(self.testRunner);
};
/**
......
......@@ -10,19 +10,11 @@ WorkerMain.WorkerMain = class extends Common.Object {
* @override
*/
run() {
SDK.targetManager.createTarget(
'main', Common.UIString('Main'), SDK.Target.Type.ServiceWorker, this._createMainConnection.bind(this), null);
InspectorFrontendHost.connectionReady();
SDK.initMainConnection(() => {
SDK.targetManager.createTarget('main', ls`Main`, SDK.Target.Type.ServiceWorker, null);
}, Components.TargetDetachedDialog.webSocketConnectionLost);
new MobileThrottling.NetworkPanelIndicator();
}
/**
* @param {!Protocol.InspectorBackend.Connection.Params} params
* @return {!Protocol.InspectorBackend.Connection}
*/
_createMainConnection(params) {
return SDK.createMainConnection(params, () => Components.TargetDetachedDialog.webSocketConnectionLost());
}
};
SDK.ChildTargetManager.install(async ({target, waitingForDebugger}) => {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment