diff --git a/tools/chrome-rdp/src/main/js/chrome/contentscript.js b/tools/chrome-rdp/src/main/js/chrome/contentscript.js index 5859f1799..c8f1334ff 100644 --- a/tools/chrome-rdp/src/main/js/chrome/contentscript.js +++ b/tools/chrome-rdp/src/main/js/chrome/contentscript.js @@ -14,13 +14,13 @@ * limitations under the License. */ -var connected = false; -window.addEventListener("message", function(event) { +let connected = false; +window.addEventListener("message", (event) => { if (event.source !== window) { return; } - var data = event.data; + const data = event.data; if (typeof data.teavmDebugger !== "undefined" && !connected) { connected = true; chrome.runtime.sendMessage({ command: "debug", port: data.teavmDebugger.port }); diff --git a/tools/chrome-rdp/src/main/js/chrome/main.js b/tools/chrome-rdp/src/main/js/chrome/main.js index 555d7806a..131a0f169 100644 --- a/tools/chrome-rdp/src/main/js/chrome/main.js +++ b/tools/chrome-rdp/src/main/js/chrome/main.js @@ -1,110 +1,144 @@ -debuggerAgentMap = {}; +debuggerAgentMap = Object.create(null); + +class DebuggerAgent { + constructor(tab, port) { + this.pendingMessages = []; + this.connection = null; + this.attachedToDebugger = false; + this.messageBuffer = ""; + this.port = 0; + this.disconnectCallbacks = null; + + this.debuggee = { tabId : tab.id }; + this.port = port; + debuggerAgentMap[tab.id] = this; + } + + attach() { + chrome.debugger.attach(this.debuggee, "1.2", () => { + this.attachedToDebugger = true; + chrome.debugger.sendCommand(this.debuggee, "Debugger.enable", {}, () => this.connectToServer()); + }); + } + + connectToServer() { + this.connection = new WebSocket("ws://localhost:" + this.port + "/"); + this.connection.onmessage = event => { + const str = event.data; + const ctl = str.substring(0, 1); + this.messageBuffer += str.substring(1); + if (ctl === '.') { + this.receiveMessage(JSON.parse(this.messageBuffer)); + this.messageBuffer = ""; + } + }; + this.connection.onclose = () => { + if (this.connection != null) { + this.connection = null; + this.disconnect(); + } + }; + this.connection.onopen = () => { + for (const pendingMessage of this.pendingMessages) { + this.sendMessage(pendingMessage); + } + this.pendingMessages = null; + }; + } + + receiveMessage(message) { + chrome.debugger.sendCommand(this.debuggee, message.method, message.params, response => { + if (message.id) { + const responseToServer = { + id : message.id, + result : response, + error : response ? void 0 : chrome.runtime.lastError + }; + this.sendMessage(responseToServer); + } + }); + } + + sendMessage(message) { + let str = JSON.stringify(message); + while (str.length > DebuggerAgent.MAX_MESSAGE_SIZE) { + const part = "," + str.substring(0, DebuggerAgent.MAX_MESSAGE_SIZE); + this.connection.send(part); + str = str.substring(DebuggerAgent.MAX_MESSAGE_SIZE); + } + this.connection.send("." + str); + } + + disconnect(callback) { + if (this.connection) { + const conn = this.connection; + this.connection = null; + conn.close(); + } + if (this.attachedToDebugger) { + chrome.debugger.detach(this.debuggee, () => { + if (this.debuggee) { + delete debuggerAgentMap[this.debuggee.tabId]; + this.debuggee = null; + } + for (const callback of this.disconnectCallbacks) { + callback(); + } + this.disconnectCallbacks = null; + }); + this.attachedToDebugger = false; + this.disconnectCallbacks = []; + } + + if (callback) { + if (this.disconnectCallbacks != null) { + this.disconnectCallbacks.push(callback); + } else { + callback(); + } + } + } +} + +DebuggerAgent.MAX_MESSAGE_SIZE = 65534; chrome.browserAction.onClicked.addListener(function(tab) { - chrome.storage.sync.get({ - port: 2357, - }, function(items) { - new DebuggerAgent(tab, items.port).attach(); - }); + chrome.storage.sync.get({ port: 2357 }, items => attachDebugger(tab, items.port)); }); -function DebuggerAgent(tab, port) { - this.pendingMessages = []; - this.connection = null; - this.tab = null; - this.debuggee = { tabId : tab.id }; - this.attachedToDebugger = false; - this.messageBuffer = ""; - this.port = port; - debuggerAgentMap[tab.id] = this; -} -DebuggerAgent.MAX_MESSAGE_SIZE = 65534; -DebuggerAgent.prototype.attach = function() { - chrome.debugger.attach(this.debuggee, "1.0", function(callback) { - this.attachedToDebugger = true; - chrome.debugger.sendCommand(this.debuggee, "Debugger.enable", {}, callback); - }.bind(this, this.connectToServer.bind(this))); -}; -DebuggerAgent.prototype.connectToServer = function() { - this.connection = new WebSocket("ws://localhost:" + this.port + "/"); - this.connection.onmessage = function(event) { - 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); - this.connection.onclose = function(event) { - if (this.connection != null) { - this.connection = null; - this.disconnect(); - } - }.bind(this); - this.connection.onopen = function() { - for (var i = 0; i < this.pendingMessages.length; ++i) { - this.sendMessage(this.pendingMessages[i]); - } - this.pendingMessages = null; - }.bind(this); -}; -DebuggerAgent.prototype.receiveMessage = function(message) { - chrome.debugger.sendCommand(this.debuggee, message.method, message.params, function(response) { - if (message.id) { - var responseToServer = { id : message.id, result : response, - error : response ? undefined : chrome.runtime.lastError }; - this.sendMessage(responseToServer); - } - }.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() { - if (this.connection) { - var conn = this.connection; - this.connection = null; - conn.close(); - } - if (this.attachedToDebugger) { - chrome.debugger.detach(this.debuggee); - this.attachedToDebugger = false; - } - if (this.debuggee) { - delete debuggerAgentMap[this.debuggee.tabId]; - this.debuggee = null; - } -}; - -chrome.debugger.onEvent.addListener(function(source, method, params) { - var agent = debuggerAgentMap[source.tabId]; +chrome.debugger.onEvent.addListener((source, method, params) => { + const agent = debuggerAgentMap[source.tabId]; if (!agent) { return; } - var message = { method : method, params : params }; + const message = { method : method, params : params }; if (agent.pendingMessages) { agent.pendingMessages.push(message); } else if (agent.connection) { agent.sendMessage(message); } }); -chrome.debugger.onDetach.addListener(function(source) { - var agent = debuggerAgentMap[source.tabId]; +chrome.debugger.onDetach.addListener((source) => { + const agent = debuggerAgentMap[source.tabId]; if (agent) { agent.attachedToDebugger = false; agent.disconnect(); } }); -chrome.runtime.onMessage.addListener(function(message, sender, callback) { +chrome.runtime.onMessage.addListener((message, sender) => { if (message.command === "debug") { - new DebuggerAgent(sender.tab, message.port).attach(); + attachDebugger(sender.tab, message.port); } -}); \ No newline at end of file +}); + +function attachDebugger(tab, port) { + const existingAgent = debuggerAgentMap[tab.id]; + if (!existingAgent) { + new DebuggerAgent(tab, port).attach(); + } else if (existingAgent.port !== port) { + existingAgent.disconnect(() => { + new DebuggerAgent(tab, port).attach(); + }); + } +} \ No newline at end of file diff --git a/tools/chrome-rdp/src/main/js/chrome/options.js b/tools/chrome-rdp/src/main/js/chrome/options.js index e2b211e31..63f5ec091 100644 --- a/tools/chrome-rdp/src/main/js/chrome/options.js +++ b/tools/chrome-rdp/src/main/js/chrome/options.js @@ -15,7 +15,7 @@ */ function saveOptions() { - var port = document.getElementById("port").value; + const port = document.getElementById("port").value; chrome.storage.sync.set({ port: port !== "" ? parseInt(port) : 2357, }); @@ -24,7 +24,7 @@ function saveOptions() { function loadOptions() { chrome.storage.sync.get({ port: 2357, - }, function(items) { + }, (items) => { document.getElementById("port").value = items.port; }); }