Extend remote debugger communication protocol for supporting messages

larger than 65536 characters (limitation of web sockets).
This commit is contained in:
konsoletyper 2014-10-05 18:25:31 +04:00
parent 2d583dc7f4
commit 493ca64411
4 changed files with 65 additions and 8 deletions

View File

@ -27,9 +27,11 @@ import javax.websocket.server.ServerEndpoint;
*/ */
@ServerEndpoint("/") @ServerEndpoint("/")
public class ChromeRDPDebuggerEndpoint implements ChromeRDPExchange { public class ChromeRDPDebuggerEndpoint implements ChromeRDPExchange {
public static final int MAX_MESSAGE_SIZE = 65534;
private Session session; private Session session;
private ChromeRDPExchangeConsumer debugger; private ChromeRDPExchangeConsumer debugger;
private List<ChromeRDPExchangeListener> listeners = new ArrayList<>(); private List<ChromeRDPExchangeListener> listeners = new ArrayList<>();
private StringBuilder messageBuffer = new StringBuilder();
@OnOpen @OnOpen
public void open(Session session) { public void open(Session session) {
@ -61,14 +63,26 @@ public class ChromeRDPDebuggerEndpoint implements ChromeRDPExchange {
@OnMessage @OnMessage
public void receive(String message) throws IOException { public void receive(String message) throws IOException {
char ctl = message.charAt(0);
messageBuffer.append(message.substring(1));
if (ctl == '.') {
message = messageBuffer.toString();
for (ChromeRDPExchangeListener listener : listeners) { for (ChromeRDPExchangeListener listener : listeners) {
listener.received(message); listener.received(message);
} }
messageBuffer = new StringBuilder();
}
} }
@Override @Override
public void send(String message) { public void send(String message) {
session.getAsyncRemote().sendText(message); int index = 0;
while (message.length() - index > MAX_MESSAGE_SIZE) {
int next = index + MAX_MESSAGE_SIZE;
session.getAsyncRemote().sendText("," + message.substring(index, next));
index = next;
}
session.getAsyncRemote().sendText("." + message.substring(index));
} }
@Override @Override

View File

@ -9,8 +9,10 @@ function DebuggerAgent(tab) {
this.tab = null; this.tab = null;
this.debuggee = { tabId : tab.id }; this.debuggee = { tabId : tab.id };
this.attachedToDebugger = false; this.attachedToDebugger = false;
this.messageBuffer = "";
debuggerAgentMap[tab.id] = this; debuggerAgentMap[tab.id] = this;
} }
DebuggerAgent.MAX_MESSAGE_SIZE = 65534;
DebuggerAgent.prototype.attach = function() { DebuggerAgent.prototype.attach = function() {
chrome.debugger.attach(this.debuggee, "1.0", (function(callback) { chrome.debugger.attach(this.debuggee, "1.0", (function(callback) {
this.attachedToDebugger = true; this.attachedToDebugger = true;
@ -20,7 +22,13 @@ DebuggerAgent.prototype.attach = function() {
DebuggerAgent.prototype.connectToServer = function() { DebuggerAgent.prototype.connectToServer = function() {
this.connection = new WebSocket("ws://localhost:2357/"); this.connection = new WebSocket("ws://localhost:2357/");
this.connection.onmessage = function(event) { this.connection.onmessage = function(event) {
this.receiveMessage(JSON.parse(event.data)); var str = event.data;
var ctl = str.substring(0, 1);
this.messageBuffer += str.substring(1);
if (ctl == '.') {
this.receiveMessage(JSON.parse(this.messageBuffer));
this.messageBuffer = "";
}
}.bind(this); }.bind(this);
this.connection.onclose = function(event) { this.connection.onclose = function(event) {
if (this.connection != null) { if (this.connection != null) {
@ -30,7 +38,7 @@ DebuggerAgent.prototype.connectToServer = function() {
}.bind(this); }.bind(this);
this.connection.onopen = function() { this.connection.onopen = function() {
for (var i = 0; i < this.pendingMessages.length; ++i) { for (var i = 0; i < this.pendingMessages.length; ++i) {
this.connection.send(JSON.stringify(this.pendingMessages[i])); this.sendMessage(this.pendingMessages[i]);
} }
this.pendingMessages = null; this.pendingMessages = null;
}.bind(this); }.bind(this);
@ -40,10 +48,19 @@ DebuggerAgent.prototype.receiveMessage = function(message) {
if (message.id) { if (message.id) {
var responseToServer = { id : message.id, result : response, var responseToServer = { id : message.id, result : response,
error : response ? undefined : chrome.runtime.lastError }; error : response ? undefined : chrome.runtime.lastError };
this.connection.send(JSON.stringify(responseToServer)); this.sendMessage(responseToServer);
} }
}.bind(this)); }.bind(this));
}; };
DebuggerAgent.prototype.sendMessage = function(message) {
var str = JSON.stringify(message);
while (str.length > DebuggerAgent.MAX_MESSAGE_SIZE) {
var part = "," + str.substring(0, DebuggerAgent.MAX_MESSAGE_SIZE);
this.connection.send(part);
str = str.substring(DebuggerAgent.MAX_MESSAGE_SIZE);
}
this.connection.send("." + str);
}
DebuggerAgent.prototype.disconnect = function() { DebuggerAgent.prototype.disconnect = function() {
if (this.connection) { if (this.connection) {
var conn = this.connection; var conn = this.connection;
@ -69,7 +86,7 @@ chrome.debugger.onEvent.addListener(function(source, method, params) {
if (agent.pendingMessages) { if (agent.pendingMessages) {
agent.pendingMessages.push(message); agent.pendingMessages.push(message);
} else if (agent.connection) { } else if (agent.connection) {
agent.connection.send(JSON.stringify(message)); agent.sendMessage(message);
} }
}); });
chrome.debugger.onDetach.addListener(function(source) { chrome.debugger.onDetach.addListener(function(source) {

View File

@ -43,5 +43,6 @@ bin.includes = META-INF/,\
lib/websocket-client-9.2.1.v20140609.jar,\ lib/websocket-client-9.2.1.v20140609.jar,\
lib/websocket-common-9.2.1.v20140609.jar,\ lib/websocket-common-9.2.1.v20140609.jar,\
lib/websocket-server-9.2.1.v20140609.jar,\ lib/websocket-server-9.2.1.v20140609.jar,\
lib/websocket-servlet-9.2.1.v20140609.jar, lib/websocket-servlet-9.2.1.v20140609.jar,\
logback.xml
jars.compile.order = . jars.compile.order = .

View File

@ -0,0 +1,25 @@
<!--
Copyright 2014 Alexey Andreev.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="STDOUT" />
</root>
</configuration>