summaryrefslogtreecommitdiffstatsabout
diff options
context:
space:
mode:
authorGrant Gayed2012-02-08 17:04:57 (EST)
committer Silenio Quarti2012-02-09 10:47:13 (EST)
commitccdb7a934f5f7e2c6ba7b47e66e884b515500c3f (patch)
tree32bafc25d9bf3e606929a6a879edccc9cd74638e
parentff9dcd46bf96d77f46705746f6abfb7b17e578be (diff)
downloadorg.eclipse.orion.client-ccdb7a934f5f7e2c6ba7b47e66e884b515500c3f.zip
org.eclipse.orion.client-ccdb7a934f5f7e2c6ba7b47e66e884b515500c3f.tar.gz
org.eclipse.orion.client-ccdb7a934f5f7e2c6ba7b47e66e884b515500c3f.tar.bz2
Bug 371013 - make debug work on tabs within a Chrome instance
-rw-r--r--bundles/org.eclipse.orion.client.debug/chromeExtension/background.html139
-rw-r--r--bundles/org.eclipse.orion.client.debug/chromeExtension/bin/debugChromeExtension.crxbin1525 -> 0 bytes
-rw-r--r--bundles/org.eclipse.orion.client.debug/chromeExtension/debug.js55
-rw-r--r--bundles/org.eclipse.orion.client.debug/chromeExtension/manifest.json15
-rw-r--r--bundles/org.eclipse.orion.client.debug/chromeExtension/src/debug.js51
-rw-r--r--bundles/org.eclipse.orion.client.debug/chromeExtension/src/manifest.json9
-rw-r--r--bundles/org.eclipse.orion.client.debug/web/connections.html3
-rw-r--r--bundles/org.eclipse.orion.client.debug/web/connections.js401
-rw-r--r--bundles/org.eclipse.orion.client.debug/web/connectionsTree.js14
-rw-r--r--bundles/org.eclipse.orion.client.debug/web/debug.html4
-rw-r--r--bundles/org.eclipse.orion.client.debug/web/debug.js97
-rw-r--r--bundles/org.eclipse.orion.client.debug/web/debugMessaging.js115
-rw-r--r--bundles/org.eclipse.orion.client.debug/web/debugTab.js394
-rw-r--r--bundles/org.eclipse.orion.client.debug/web/ext/debugChromeExtension.crxbin0 -> 3239 bytes
14 files changed, 954 insertions, 343 deletions
diff --git a/bundles/org.eclipse.orion.client.debug/chromeExtension/background.html b/bundles/org.eclipse.orion.client.debug/chromeExtension/background.html
new file mode 100644
index 0000000..6c5406a
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.debug/chromeExtension/background.html
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * @license
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0
+ * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution
+ * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html).
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/*jslint browser:true*/
+
+<html>
+<script>
+var ADD_EVENT_TARGET = "add-event-target";
+var REMOVE_EVENT_TARGET = "remove-event-target";
+var REQUEST_ATTACH = "attach";
+var REQUEST_CONNECT_LOCAL = "connect-local";
+var REQUEST_CONNECT_PORT = "connect-port";
+var REQUEST_DETACH = "detach";
+var REQUEST_ENABLE = "enable";
+var REQUEST_GET_ID = "get-id";
+var REQUEST_GET_URL = "get-url";
+var REQUEST_GET_VERSION = "get-version";
+var REQUEST_SEND_COMMAND = "send-command";
+
+var counter = 0;
+var eventTargets = {};
+
+chrome.debugger.onDetach.addListener(function(source) {
+ for (current in eventTargets) {
+ chrome.tabs.sendRequest(eventTargets[current], {id: "event-" + source.tabId + "-" + counter++, content: {id: "detached", data: {}}});
+ }
+});
+chrome.debugger.onEvent.addListener(function(source, method, params) {
+ for (current in eventTargets) {
+ chrome.tabs.sendRequest(eventTargets[current], {id: "event-" + source.tabId + "-" + counter++, content: {id: method, data: params || {}}});
+ }
+});
+chrome.tabs.onCreated.addListener(function(tab) {
+ for (current in eventTargets) {
+ chrome.tabs.sendRequest(eventTargets[current], {id: "event-global-" + counter++, content: {id: "tabCreated", data: {id: tab.id, url: tab.url}}});
+ }
+});
+chrome.tabs.onRemoved.addListener(function(tabId, removeInfo) {
+ for (current in eventTargets) {
+ chrome.tabs.sendRequest(eventTargets[current], {id: "event-global-" + counter++, content: {id: "tabRemoved", data: {id: tabId}}});
+ }
+});
+chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
+ if (changeInfo.url) {
+ for (current in eventTargets) {
+ chrome.tabs.sendRequest(eventTargets[current], {id: "event-" + tabId + "-" + counter++, content: {id: "updateUrl", data: {url: changeInfo.url}}});
+ }
+ }
+});
+
+chrome.extension.onRequest.addListener(
+ function(request, sender, sendResponse) {
+ var content = request.content;
+ if (content.id === REQUEST_CONNECT_LOCAL) {
+ chrome.windows.getAll({populate: true}, function(windows) {
+ var data = [];
+ for (var i = 0; i < windows.length; i++) {
+ var tabs = windows[i].tabs;
+ for (var j = 0; j < tabs.length; j++) {
+ var current = tabs[j];
+ var url = current.url;
+ data.push({
+ id: current.id,
+ url: url
+ });
+ }
+ }
+ sendResponse({id: request.id, content: {data: {tabs: data}}});
+ });
+ } else if (content.id === REQUEST_CONNECT_PORT) {
+ var port = content.data.port;
+ if (isNaN(port) || !(1000 <= port && port < 65535)) {
+ sendResponse({id: request.id, content: {data: {error: "Invalid port, value must be 1000 - 65535"}}});
+ } else {
+ var url = "http://localhost:" + port + "/json";
+ var xhr = new XMLHttpRequest();
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState === 4) {
+ if (xhr.responseText.length > 0) {
+ sendResponse({id: request.id, content: {data: {tabs: JSON.parse(xhr.responseText)}}});
+ }
+ }
+ };
+ xhr.onerror = function() {
+ sendResponse({id: request.id, content: {data: {error: "TODO get the error message"}}}); // TODO
+ };
+ xhr.open("GET", url, true);
+ xhr.setRequestHeader('Cache-Control','no-cache');
+ xhr.send(null);
+ }
+ } else if (content.id === REQUEST_ATTACH) {
+ var id = content.data.id;
+ chrome.debugger.attach({tabId: id}, "0.1", function() {
+ sendResponse({id: request.id, content: {data: chrome.extension.lastError ? {error: chrome.extension.lastError} : {}}});
+ });
+ } else if (content.id === REQUEST_DETACH) {
+ var id = content.data.id;
+ chrome.debugger.detach({tabId: id}, function() {
+ sendResponse({id: request.id, content: {data: chrome.extension.lastError ? {error: chrome.extension.lastError} : {}}});
+ });
+ } else if (content.id === REQUEST_SEND_COMMAND) {
+ chrome.debugger.sendCommand({tabId: content.data.id}, content.data.command, content.data.args || {}, function(result) {
+ sendResponse({id: request.id, content: {data: chrome.extension.lastError ? {error: chrome.extension.lastError} : {result: result}}});
+ });
+ } else if (content.id === ADD_EVENT_TARGET) {
+ eventTargets["t" + sender.tab.id] = sender.tab.id;
+ } else if (content.id === REMOVE_EVENT_TARGET) {
+ delete eventTargets["t" + sender.tab.id];
+ } else if (content.id === REQUEST_GET_ID) {
+ sendResponse({id: request.id, content: {data: {id: sender.tab.id}}});
+ } else if (content.id === REQUEST_GET_URL) {
+ chrome.tabs.get(content.data.id, function(tab) {
+ sendResponse({id: request.id, content: {data: chrome.extension.lastError ? {error: chrome.extension.lastError} : {url: tab.url}}});
+ });
+ } else if (content.id === REQUEST_GET_VERSION) {
+ chrome.management.getAll(function (extensions) {
+ for (var i = 0; i < extensions.length; i++) {
+ var current = extensions[i];
+ if (current.name === "Orion Debug Extension for Chrome") {
+ sendResponse({id: request.id, content: {data: {version: current.version}}});
+ return;
+ }
+ }
+ sendResponse({id: request.id, content: {data: {}}});
+ });
+ }
+ }
+);
+</script>
+</html>
diff --git a/bundles/org.eclipse.orion.client.debug/chromeExtension/bin/debugChromeExtension.crx b/bundles/org.eclipse.orion.client.debug/chromeExtension/bin/debugChromeExtension.crx
deleted file mode 100644
index 163fd90..0000000
--- a/bundles/org.eclipse.orion.client.debug/chromeExtension/bin/debugChromeExtension.crx
+++ /dev/null
Binary files differ
diff --git a/bundles/org.eclipse.orion.client.debug/chromeExtension/debug.js b/bundles/org.eclipse.orion.client.debug/chromeExtension/debug.js
new file mode 100644
index 0000000..46536fa
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.debug/chromeExtension/debug.js
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * @license
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0
+ * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution
+ * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html).
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/*global chrome*/
+/*jslint browser:true*/
+
+var incoming = document.getElementById("orion-debugMessaging-toExtension");
+var outgoing = document.getElementById("orion-debugMessaging-toPage");
+
+if (incoming && outgoing) {
+ incoming.addEventListener("DOMNodeInserted", function() {
+ var children = incoming.childNodes;
+ for (var i = children.length - 1; i >= 0; i--) {
+ var current = children[i];
+ incoming.removeChild(current);
+ chrome.extension.sendRequest({id: current.id, content: JSON.parse(current.innerText)}, function(response) {
+ if (response && response.id) {
+ var responseLabel = document.createElement('label');
+ responseLabel.setAttribute('id', response.id);
+ responseLabel.style.display = 'none';
+ responseLabel.innerText = JSON.stringify(response.content);
+ var outgoingChildren = outgoing.childNodes;
+ if (outgoingChildren.length > 0) {
+ outgoing.insertBefore(responseLabel, outgoingChildren[0]);
+ } else {
+ outgoing.appendChild(responseLabel);
+ }
+ }
+ });
+ }
+ });
+
+ chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
+ var eventLabel = document.createElement('label');
+ eventLabel.setAttribute('id', request.id);
+ eventLabel.style.display = 'none';
+ eventLabel.innerText = JSON.stringify(request.content);
+ var outgoingChildren = outgoing.childNodes;
+ if (outgoingChildren.length > 0) {
+ outgoing.insertBefore(eventLabel, outgoingChildren[0]);
+ } else {
+ outgoing.appendChild(eventLabel);
+ }
+ sendResponse({});
+ });
+}
diff --git a/bundles/org.eclipse.orion.client.debug/chromeExtension/manifest.json b/bundles/org.eclipse.orion.client.debug/chromeExtension/manifest.json
new file mode 100644
index 0000000..4bdf8d2
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.debug/chromeExtension/manifest.json
@@ -0,0 +1,15 @@
+{
+ "name":"Orion Debug Extension for Chrome",
+ "version":"0.3",
+ "content_scripts":[{
+ "matches":["http://*/*", "file://*/*"],
+ "js":["debug.js"]
+ }],
+ "background_page": "background.html",
+ "permissions": [
+ "debugger",
+ "management",
+ "tabs",
+ "http://*/json"
+ ]
+}
diff --git a/bundles/org.eclipse.orion.client.debug/chromeExtension/src/debug.js b/bundles/org.eclipse.orion.client.debug/chromeExtension/src/debug.js
deleted file mode 100644
index 218ee59..0000000
--- a/bundles/org.eclipse.orion.client.debug/chromeExtension/src/debug.js
+++ /dev/null
@@ -1,51 +0,0 @@
-/*******************************************************************************
- * @license
- * Copyright (c) 2012 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials are made
- * available under the terms of the Eclipse Public License v1.0
- * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution
- * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html).
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-/*jslint browser:true*/
-
-var debugMessaging = document.getElementById("orion-debugMessaging");
-if (debugMessaging) {
- debugMessaging.addEventListener("DOMNodeInserted", function() {
- var children = debugMessaging.childNodes;
- for (var i = 0; i < children.length; i++) {
- var current = children[i];
- if (current.id.indexOf("debug-port-") === 0) {
- var port = parseInt(current.innerHTML, 10);
- debugMessaging.removeChild(current);
- if (isNaN(port) || !(1000 <= port && port < 65535)) {
- var responseLabel = document.createElement('label');
- responseLabel.setAttribute('id', 'debug-error');
- responseLabel.style.display = 'none';
- responseLabel.innerHTML = "Invalid port, value must be 1000 - 65535";
- debugMessaging.appendChild(responseLabel);
- } else {
- var url = "http://localhost:" + port + "/json";
- var xhr = new XMLHttpRequest();
- xhr.onreadystatechange = function() {
- if (xhr.readyState === 4) {
- if (xhr.responseText.length > 0) {
- var responseLabel = document.createElement('label');
- responseLabel.setAttribute('id', 'debug-response-' + port);
- responseLabel.style.display = 'none';
- responseLabel.innerHTML = xhr.responseText;
- debugMessaging.appendChild(responseLabel);
- }
- }
- };
- xhr.open("GET", url, true);
- xhr.setRequestHeader('Cache-Control','no-cache');
- xhr.send(null);
- }
- }
- }
- });
-}
diff --git a/bundles/org.eclipse.orion.client.debug/chromeExtension/src/manifest.json b/bundles/org.eclipse.orion.client.debug/chromeExtension/src/manifest.json
deleted file mode 100644
index e1af3ba..0000000
--- a/bundles/org.eclipse.orion.client.debug/chromeExtension/src/manifest.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "name":"Orion Debug Extension for Chrome",
- "version":"0.2",
- "content_scripts":[{
- "matches":["http://*/*", "file://*/*"],
- "js":["debug.js"]
- }],
- "optional-permissions":["http://*/json", "file://*/json"]
-}
diff --git a/bundles/org.eclipse.orion.client.debug/web/connections.html b/bundles/org.eclipse.orion.client.debug/web/connections.html
index 44d6411..ebdd3d0 100644
--- a/bundles/org.eclipse.orion.client.debug/web/connections.html
+++ b/bundles/org.eclipse.orion.client.debug/web/connections.html
@@ -45,7 +45,8 @@
<div class="toolbar" id="toolbar" dojotype="dijit.layout.ContentPane" region="top">
</div>
<div id="orion-debugConnectionsMainPane" dojotype="dijit.layout.ContentPane" region="center" class="mainpane">
- <div id="orion-debugMessaging"></div>
+ <div id="orion-debugMessaging-toExtension"></div>
+ <div id="orion-debugMessaging-toPage"></div>
<div id="debugConnections-table"></div>
</div>
<div class="footer" id="footer" dojotype="dijit.layout.ContentPane" region="bottom" splitter="false">
diff --git a/bundles/org.eclipse.orion.client.debug/web/connections.js b/bundles/org.eclipse.orion.client.debug/web/connections.js
index 3170842..37f9dd3 100644
--- a/bundles/org.eclipse.orion.client.debug/web/connections.js
+++ b/bundles/org.eclipse.orion.client.debug/web/connections.js
@@ -13,13 +13,14 @@
/*global define orion localStorage*/
/*jslint browser:true*/
-define(['require', 'dojo', 'orion/bootstrap', 'orion/commands', 'orion/fileClient',
- 'orion/searchClient', 'orion/globalCommands', 'debug/connectionsTree', 'orion/treetable', 'debug/debugTab', 'debug/portInputDialog'],
- function(require, dojo, mBootstrap, mCommands, mFileClient, mSearchClient, mGlobalCommands, mConnectionsTree, mTreeTable, mDebugTab) {
+define(['require', 'dojo', 'orion/bootstrap', 'orion/commands', 'orion/fileClient', 'orion/searchClient',
+ 'orion/globalCommands', 'debug/connectionsTree', 'orion/treetable', 'debug/debugTab', 'debug/debugMessaging',
+ 'debug/portInputDialog'],
+ function(require, dojo, mBootstrap, mCommands, mFileClient, mSearchClient, mGlobalCommands, mConnectionsTree, mTreeTable, mDebugTab, mDebugMessaging) {
var treeWidget;
- var model = new mConnectionsTree.DebugConnectionTreeModel("debug-tableTree");
+ var model = new mConnectionsTree.DebugConnectionTreeModel("debug-tableTree");
function modelUpdated() {
model.getRoot(function(root) {
model.getChildren(root, function(children) {
@@ -31,15 +32,42 @@ define(['require', 'dojo', 'orion/bootstrap', 'orion/commands', 'orion/fileClien
});
}
- function initiateConnection(portString) {
- var port = parseInt(portString, 10);
- if (1000 <= port && port < 65535) {
- var label = dojo.create("label", {id: "debug-port-" + port});
- label.style.display = "none";
- label.innerHTML = port;
- dojo.place(label, "orion-debugMessaging", "first");
+ var messaging = new mDebugMessaging.DebugMessaging("connectionsPage");
+
+ var RemoteDebugTabProvider = (function() {
+ function RemoteDebugTabProvider(debugTab) {
+ this._debugTab = debugTab;
}
- }
+ RemoteDebugTabProvider.prototype = /** @lends RemoteDebugTabProvider.prototype */{
+ getChildren: function() {
+ return [];
+ },
+ getUrl: function() {
+ return this._debugTab.getUrl();
+ },
+ getWSUrl: function() {
+ return this._debugTab.getWSUrl();
+ },
+ renderLabel: function(column) {
+ var wsUrl = this.getWSUrl();
+ if (wsUrl) {
+ var base = require.toUrl("debug/debug.html");
+ var url = base + "#" + wsUrl;
+ var urlLink = dojo.create("a", {href: url}, column, "last");
+ dojo.place(document.createTextNode(this.getUrl() || "< Loading >"), urlLink, "last");
+ } else {
+ dojo.create("label", {innerHTML: this.getUrl() + " [debugger attached]"}, column, "last");
+ }
+ },
+ shouldDisplayActions: function() {
+ return false;
+ },
+ toString: function() {
+ return this.getWSUrl();
+ }
+ };
+ return RemoteDebugTabProvider;
+ }());
var RemoteDebugConnection = (function() {
function RemoteDebugConnection(port) {
@@ -54,7 +82,7 @@ define(['require', 'dojo', 'orion/bootstrap', 'orion/commands', 'orion/fileClien
for (var i = this._tabs.length - 1; i >= 0; i--) {
var current = this._tabs[i];
if (!value || current === value) {
- current.close();
+ current.detach();
this._tabs.splice(i, 1);
if (value) {
return;
@@ -72,6 +100,9 @@ define(['require', 'dojo', 'orion/bootstrap', 'orion/commands', 'orion/fileClien
getPort: function() {
return this._port;
},
+ getId: function() {
+ return this.getPort();
+ },
getTabs: function() {
return this._tabs;
},
@@ -97,45 +128,168 @@ define(['require', 'dojo', 'orion/bootstrap', 'orion/commands', 'orion/fileClien
return RemoteDebugConnection;
}());
- // TODO this should move to debugTab.js
- var RemoteDebugTabProvider = (function() {
- function RemoteDebugTabProvider(remoteDebugTab) {
- this._remoteDebugTab = remoteDebugTab;
+ function initiateRemoteConnection(port) {
+ messaging.send("connect-port", {port: port}, function(data) {
+ if (data.error) {
+ // TODO log
+ return;
+ }
+ var tabs = data.tabs;
+ var connection = new RemoteDebugConnection(port);
+ if (model.addConnection(connection)) {
+// var urlChangedFunction = function() {
+// modelUpdated();
+// };
+// var tabClosedFunction = function(remoteDebugTab) {
+// connection.disconnect(remoteDebugTab);
+// if (connection.getTabs().length === 0) {
+// model.removeConnection(connection);
+// }
+// modelUpdated();
+// };
+ for (var j = 0; j < tabs.length; j++) {
+ var current = tabs[j];
+ var remoteDebugTab = new mDebugTab.RemoteDebugTab(current.webSocketDebuggerUrl, current.url);
+// remoteDebugTab.addUrlListener(urlChangedFunction);
+// remoteDebugTab.addDetachListener(tabClosedFunction);
+ connection.addTab(remoteDebugTab);
+ }
+
+ var portsString = localStorage.getItem("orion.debug.chromeDebugPorts");
+ var portsObject = portsString ? JSON.parse(portsString) : {};
+ if (!portsObject[port]) {
+ portsObject[port] = true;
+ portsString = JSON.stringify(portsObject);
+ localStorage.setItem("orion.debug.chromeDebugPorts", portsString);
+ }
+ modelUpdated();
+ }
+ });
+ }
+
+ var LocalDebugTabProvider = (function() {
+ function LocalDebugTabProvider(debugTab) {
+ this._debugTab = debugTab;
}
- RemoteDebugTabProvider.prototype = /** @lends RemoteDebugTabProvider.prototype */{
+ LocalDebugTabProvider.prototype = /** @lends LocalDebugTabProvider.prototype */{
getChildren: function() {
return [];
},
- getRemoteDebugTab: function() {
- return this._remoteDebugTab;
- },
getUrl: function() {
- return this._remoteDebugTab.getUrl();
- },
- getWSUrl: function() {
- return this._remoteDebugTab.getWSUrl();
+ return this._debugTab.getUrl();
},
renderLabel: function(column) {
- var wsUrl = this.getWSUrl();
- if (wsUrl) {
- var base = require.toUrl("debug/debug.html");
- var url = base + "#" + wsUrl;
- var urlLink = dojo.create("a", {href: url}, column, "last");
- dojo.place(document.createTextNode(this.getUrl() || "< Loading >"), urlLink, "last");
- } else {
- dojo.create("label", {innerHTML: this.getUrl() + " [currently not debuggable]"}, column, "last");
+ var base = require.toUrl("debug/debug.html");
+ var url = base + "#id" + this._debugTab.getId();
+ var urlLink = dojo.create("a", {href: url}, column, "last");
+ dojo.place(document.createTextNode(this.getUrl() || "< Loading >"), urlLink, "last");
+ },
+ shouldDisplayActions: function() {
+ return false;
+ },
+ toString: function() {
+ return this.getUrl();
+ }
+ };
+ return LocalDebugTabProvider;
+ }());
+
+ var LocalDebugConnection = (function() {
+ function LocalDebugConnection() {
+ this._tabs = [];
+ }
+ LocalDebugConnection.prototype = /** @lends LocalDebugConnection.prototype */ {
+ addTab: function(value) {
+ this._tabs.push(value);
+ },
+ disconnect: function(value) {
+ for (var i = this._tabs.length - 1; i >= 0; i--) {
+ var current = this._tabs[i];
+ if (!value || current === value) {
+ current.detach();
+ this._tabs.splice(i, 1);
+ if (value) {
+ return;
+ }
+ }
+ }
+ },
+ getChildren: function() {
+ var result = [];
+ for (var i = 0; i < this._tabs.length; i++) {
+ result.push(new LocalDebugTabProvider(this._tabs[i]));
}
+ return result;
+ },
+ getId: function() {
+ return "local";
+ },
+ getTabs: function() {
+ return this._tabs;
+ },
+ removeTab: function(tab) {
+ for (var i = 0; i < this._tabs.length; i++) {
+ var current = this._tabs[i];
+ if (current === tab) {
+ this._tabs.splice(i, 1);
+ return;
+ }
+ }
+ },
+ renderLabel: function(column) {
+ dojo.create("label", {innerHTML: this.toString().bold()}, column, "last");
},
shouldDisplayActions: function() {
return false;
},
toString: function() {
- return this.getWSUrl();
+ return "Local Chrome browser";
}
};
- return RemoteDebugTabProvider;
+ return LocalDebugConnection;
}());
+ function refreshAvailableTabs() {
+ model.clear();
+ messaging.send("connect-local", null, function(result) {
+ var tabs = result.tabs;
+ var localDebugConnection;
+ messaging.send("get-id", null, function(result) {
+ var selfTabId = result.id;
+ var urlChangedFunction = function() {
+ modelUpdated();
+ };
+ for (var j = 0; j < tabs.length; j++) {
+ var currentTab = tabs[j];
+ if (currentTab.id !== selfTabId) {
+ var localDebugTab = new mDebugTab.LocalDebugTab(currentTab.id, messaging, currentTab.url);
+ localDebugTab.addUrlListener(urlChangedFunction);
+ if (!localDebugConnection) {
+ localDebugConnection = new LocalDebugConnection();
+ model.addConnection(localDebugConnection);
+ }
+ localDebugConnection.addTab(localDebugTab);
+ }
+ }
+ modelUpdated();
+ });
+ });
+
+ var portsString = localStorage.getItem("orion.debug.chromeDebugPorts");
+ if (portsString) {
+ var portsObject = JSON.parse(portsString);
+ for (var port in portsObject) {
+ initiateRemoteConnection(parseInt(port, 10));
+ }
+ }
+ }
+
+ messaging.addEventListener(messaging.getId(), function(event, data) {
+ if (event === "tabCreated" || event === "tabRemoved") {
+ refreshAvailableTabs();
+ }
+ });
+
dojo.addOnLoad(function() {
mBootstrap.startup().then(function(core) {
var serviceRegistry = core.serviceRegistry;
@@ -156,124 +310,83 @@ define(['require', 'dojo', 'orion/bootstrap', 'orion/commands', 'orion/fileClien
return;
}
- var renderer = new mConnectionsTree.DebugConnectionRenderer(commandService);
- treeWidget = new mTreeTable.TableTree({
- id: "debug-tableTree",
- parent: dojo.byId("debugConnections-table"),
- model: model,
- showRoot: false,
- renderer: renderer
- });
-
- var connectCommand = new mCommands.Command({
- name: "Connect",
- tooltip: "Connect to a new browser",
- id: "orion.debugConnections.connect",
- groupId: "orion.debugGroup",
- visibleWhen: function(item) {
- return isChrome;
- },
- callback: function() {
- var dialog = new orion.debug.PortInputDialog({
- serviceRegistry: serviceRegistry,
- func: function(port) {
- initiateConnection(port);
- }
- });
- dialog.startup();
- dialog.show();
+ messaging.verifyExtension(function(result) {
+ if (result) {
+ var label = dojo.create("label");
+ label.innerHTML = result;
+ dojo.place(label, "debugConnections-table", "first");
+ var url = require.toUrl("debug/ext/debugChromeExtension.crx");
+ var urlLink = dojo.create("a", {href: url}, "debugConnections-table", "last");
+ dojo.place(document.createTextNode(" [Click to install it]"), urlLink, "last");
+ return;
}
- });
- commandService.addCommand(connectCommand, "dom");
-
- var disconnectCommand = new mCommands.Command({
- name: "Disconnect",
- tooltip: "Disconnect",
- imageClass: "core-sprite-problem",
- id: "orion.debugConnections.disconnect",
- visibleWhen: function(item) {
- return true;
- },
- callback: function(data) {
- var connection = data.items;
- connection.disconnect();
- model.removeConnection(connection);
- modelUpdated();
-
- var port = connection.getPort();
- var portsString = localStorage.getItem("orion.debug.chromeDebugPorts");
- var portsObject = portsString ? JSON.parse(portsString) : {};
- if (portsObject[port]) {
- delete portsObject[port];
- portsString = JSON.stringify(portsObject);
- localStorage.setItem("orion.debug.chromeDebugPorts", portsString);
- }
- }
- });
- commandService.addCommand(disconnectCommand, "object");
-
- commandService.registerCommandContribution("orion.debugConnections.connect", 1, "pageActions");
- commandService.registerCommandContribution("orion.debugConnections.disconnect", 1);
- mGlobalCommands.generateDomCommandsInBanner(commandService, {});
- var debugMessaging = dojo.byId("orion-debugMessaging");
- if (debugMessaging) {
- var treeModel = model;
- debugMessaging.addEventListener("DOMNodeInserted", function() {
- var changed = false;
- var children = debugMessaging.childNodes;
- for (var i = 0; i < children.length; i++) {
- var current = children[i];
- if (current.id.indexOf("debug-response-") === 0) {
- var info = JSON.parse(current.innerHTML);
- debugMessaging.removeChild(current);
-
- var port = current.id.substring("debug-response-".length);
- var connection = new RemoteDebugConnection(port);
- if (treeModel.addConnection(connection)) {
- var urlChangedFunction = function() {
- modelUpdated();
- };
- var tabClosedFunction = function(remoteDebugTab) {
- connection.disconnect(remoteDebugTab);
- if (connection.getTabs().length === 0) {
- treeModel.removeConnection(connection);
- }
- modelUpdated();
- };
- for (var j = 0; j < info.length; j++) {
- var current = info[j];
- var remoteDebugTab = new mDebugTab.RemoteDebugTab(current.webSocketDebuggerUrl, current.url);
- remoteDebugTab.addUrlListener(urlChangedFunction);
- remoteDebugTab.addCloseListener(tabClosedFunction);
- connection.addTab(remoteDebugTab);
- }
+ var renderer = new mConnectionsTree.DebugConnectionRenderer(commandService);
+ treeWidget = new mTreeTable.TableTree({
+ id: "debug-tableTree",
+ parent: dojo.byId("debugConnections-table"),
+ model: model,
+ showRoot: false,
+ renderer: renderer
+ });
- var portsString = localStorage.getItem("orion.debug.chromeDebugPorts");
- var portsObject = portsString ? JSON.parse(portsString) : {};
- if (!portsObject[port]) {
- portsObject[port] = true;
- portsString = JSON.stringify(portsObject);
- localStorage.setItem("orion.debug.chromeDebugPorts", portsString);
+ var connectCommand = new mCommands.Command({
+ name: "Connect",
+ tooltip: "Connect to a new browser",
+ id: "orion.debugConnections.connect",
+ groupId: "orion.debugGroup",
+ visibleWhen: function(item) {
+ return isChrome;
+ },
+ callback: function() {
+ var dialog = new orion.debug.PortInputDialog({
+ serviceRegistry: serviceRegistry,
+ func: function(port) {
+ if (port && 1000 <= port && port < 65535) {
+ initiateRemoteConnection(port);
}
- changed = true;
}
- }
+ });
+ dialog.startup();
+ dialog.show();
}
-
- if (changed) {
+ });
+ commandService.addCommand(connectCommand, "dom");
+
+ var disconnectCommand = new mCommands.Command({
+ name: "Disconnect",
+ tooltip: "Disconnect",
+ imageClass: "core-sprite-problem",
+ id: "orion.debugConnections.disconnect",
+ visibleWhen: function(item) {
+ return true;
+ },
+ callback: function(data) {
+ var connection = data.items;
+ connection.disconnect();
+ model.removeConnection(connection);
modelUpdated();
+
+ var port = connection.getPort();
+ var portsString = localStorage.getItem("orion.debug.chromeDebugPorts");
+ var portsObject = portsString ? JSON.parse(portsString) : {};
+ if (portsObject[port]) {
+ delete portsObject[port];
+ portsString = JSON.stringify(portsObject);
+ localStorage.setItem("orion.debug.chromeDebugPorts", portsString);
+ }
}
});
- }
-
- var portsString = localStorage.getItem("orion.debug.chromeDebugPorts");
- if (portsString) {
- var portsObject = JSON.parse(portsString);
- for (var port in portsObject) {
- initiateConnection(port);
- }
- }
+ commandService.addCommand(disconnectCommand, "object");
+
+ // the following are intentionally commented
+// commandService.registerCommandContribution("orion.debugConnections.connect", 2, "pageActions");
+// commandService.registerCommandContribution("orion.debugConnections.disconnect", 1);
+ mGlobalCommands.generateDomCommandsInBanner(commandService, {});
+ refreshAvailableTabs();
+ });
});
});
});
+
+
diff --git a/bundles/org.eclipse.orion.client.debug/web/connectionsTree.js b/bundles/org.eclipse.orion.client.debug/web/connectionsTree.js
index 36aa0a8..ddb2e38 100644
--- a/bundles/org.eclipse.orion.client.debug/web/connectionsTree.js
+++ b/bundles/org.eclipse.orion.client.debug/web/connectionsTree.js
@@ -11,7 +11,6 @@
*******************************************************************************/
/*global define*/
-/*jslint browser:true*/
define(['require', 'dojo'], function(require, dojo) {
@@ -26,18 +25,18 @@ define(['require', 'dojo'], function(require, dojo) {
DebugConnectionTreeModel.prototype = /** @lends orion.debug.DebugConnectionTreeModel.prototype */{
addConnection: function(connection) {
/* first check for a duplicate */
- var port = connection.getPort();
+ var id = connection.getId();
for (var i = 0; i < this._root.length; i++) {
var current = this._root[i];
- if (current.getPort() === port) {
+ if (current.getId() === id) {
return false;
}
}
this._root.push(connection);
return true;
},
- getRoot: function(/**function*/ onItem) {
- onItem(this);
+ clear: function() {
+ this._root = [];
},
getChildren: function(/**dojo.data.Item*/ parentItem, /**Function(items)*/ onComplete) {
onComplete(parentItem === this ? this._root : parentItem.getChildren());
@@ -45,6 +44,9 @@ define(['require', 'dojo'], function(require, dojo) {
getId: function(/**dojo.data.Item|String*/ item) {
return (item === this || item === this._id) ? this._id : item.toString();
},
+ getRoot: function(/**function*/ onItem) {
+ onItem(this);
+ },
removeConnection: function(connection) {
for (var i = 0; i < this._root.length; i++) {
var current = this._root[i];
@@ -79,7 +81,7 @@ define(['require', 'dojo'], function(require, dojo) {
{id: tableRow.id + "actionswrapper"},
actionColumn,
"only");
- this._commandService.renderCommands(actionsWrapper, "object", item, {}, "tool");
+ this._commandService.renderCommands(actionsWrapper, "object", item, {}, "button");
}
dojo.place(labelColumn, tableRow, "last");
dojo.place(actionColumn, tableRow, "last");
diff --git a/bundles/org.eclipse.orion.client.debug/web/debug.html b/bundles/org.eclipse.orion.client.debug/web/debug.html
index ef8b27b..8bfd872 100644
--- a/bundles/org.eclipse.orion.client.debug/web/debug.html
+++ b/bundles/org.eclipse.orion.client.debug/web/debug.html
@@ -45,7 +45,9 @@
<div class="toolbar" id="toolbar" dojotype="dijit.layout.ContentPane" region="top">
</div>
<div id="orion-debugMainPane" dojotype="dijit.layout.ContentPane" region="center" class="mainpane">
- <div id="debug-console" style='width:100%;height:650px;border: 1px solid teal;'></div>
+ <div id="orion-debugMessaging-toExtension"></div>
+ <div id="orion-debugMessaging-toPage"></div>
+ <div id="debug-console" style='width:100%;height:650px;border: 1px solid black;'></div>
</div>
<div class="footer" id="footer" dojotype="dijit.layout.ContentPane" region="bottom" splitter="false">
</div>
diff --git a/bundles/org.eclipse.orion.client.debug/web/debug.js b/bundles/org.eclipse.orion.client.debug/web/debug.js
index 814ce4c..8061f72 100644
--- a/bundles/org.eclipse.orion.client.debug/web/debug.js
+++ b/bundles/org.eclipse.orion.client.debug/web/debug.js
@@ -14,10 +14,8 @@
/*jslint browser:true*/
define(['require', 'dojo', 'orion/bootstrap', 'orion/commands', 'orion/fileClient', 'orion/searchClient', 'orion/globalCommands',
- 'orion/console', 'debug/debugTab'],
- function(require, dojo, mBootstrap, mCommands, mFileClient, mSearchClient, mGlobalCommands, mConsole, mDebugTab) {
-
- var console;
+ 'orion/console', 'debug/debugTab', 'debug/debugMessaging'],
+ function(require, dojo, mBootstrap, mCommands, mFileClient, mSearchClient, mGlobalCommands, mConsole, mDebugTab, mDebugMessaging) {
dojo.addOnLoad(function() {
mBootstrap.startup().then(function(core) {
@@ -39,33 +37,82 @@ define(['require', 'dojo', 'orion/bootstrap', 'orion/commands', 'orion/fileClien
return;
}
+ var connection, console, messaging;
var hash = dojo.hash();
- var connection = new mDebugTab.RemoteDebugTab(hash);
- connection.addCloseListener(function() {
- var location = dojo.byId("location");
- if (location) {
- location.innerHTML = null;
+ if (hash.indexOf("ws://") === 0) {
+ connection = new mDebugTab.RemoteDebugTab(hash);
+ } else {
+ if (hash.indexOf("id") === 0) {
+ var id = parseInt(hash.substring(2), 10);
+ if (id) {
+ messaging = new mDebugMessaging.DebugMessaging("debugPage-" + id);
+ connection = new mDebugTab.LocalDebugTab(id, messaging);
+ }
+ }
+ if (!connection) {
+ return;
}
- console.appendOutput("<< Disconnected from external browser >>");
- console.setAcceptInput(false);
- });
- connection.addUrlListener(function(url) {
- var location = dojo.byId("location");
- if (location) {
- if (url === "about:blank") {
+ }
+
+ var init = function() {
+ dojo.addOnUnload(function() {
+ connection.detach();
+ });
+
+ connection.addDetachListener(function() {
+ var location = dojo.byId("location");
+ if (location) {
location.innerHTML = null;
- } else {
- location.innerHTML = url;
}
- }
- });
+ console.appendOutput("<< Disconnected from debug target >>");
+ console.setAcceptInput(false);
+ });
+ connection.addUrlListener(function(url) {
+ var location = dojo.byId("location");
+ if (location) {
+ if (url === "about:blank") {
+ location.innerHTML = null;
+ } else {
+ location.innerHTML = url;
+ }
+ }
+ });
- console = new mConsole.Console("debug-console");
- console.addInputListener(function(inputEvent) {
- connection.evaluate(inputEvent, function(result) {
- console.appendOutput(JSON.stringify(result));
+ console = new mConsole.Console("debug-console");
+ console.addInputListener(function(inputEvent) {
+ connection.evaluate(inputEvent, function(result) {
+ if (result.error) {
+ console.appendOutput("<< " + result.error + " >>");
+ } else {
+ console.appendOutput(JSON.stringify(result.result));
+ }
+ });
+ });
+
+ connection.attach(function (error) {
+ if (error) {
+ console.appendOutput("<< " + error + " >>");
+ console.setAcceptInput(false);
+ }
});
- });
+ };
+
+ if (messaging) {
+ messaging.verifyExtension(function(error) {
+ if (error) {
+ var label = dojo.create("label");
+ label.innerHTML = error;
+ dojo.place(label, "debug-console", "first");
+ var url = require.toUrl("debug/ext/debugChromeExtension.crx");
+ var urlLink = dojo.create("a", {href: url}, "debug-console", "last");
+ dojo.place(document.createTextNode(" [Click to install it]"), urlLink, "last");
+ return;
+ }
+ init();
+ });
+ } else {
+ init();
+ }
});
});
});
diff --git a/bundles/org.eclipse.orion.client.debug/web/debugMessaging.js b/bundles/org.eclipse.orion.client.debug/web/debugMessaging.js
new file mode 100644
index 0000000..0bc4268
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.debug/web/debugMessaging.js
@@ -0,0 +1,115 @@
+/*******************************************************************************
+* @license
+* Copyright (c) 2012 IBM Corporation and others.
+* All rights reserved. This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License v1.0
+* (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution
+* License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html).
+*
+* Contributors:
+* IBM Corporation - initial API and implementation
+*******************************************************************************/
+
+/*global define*/
+/*jslint browser:true*/
+
+define(['require', 'dojo'], function(require, dojo) {
+
+ var orion = {};
+ orion.debug = {};
+
+ orion.debug.DebugMessaging = (function() {
+ function DebugMessaging(id) {
+ this._id = id;
+
+ this._counter = 0;
+ this._eventListeners = {};
+ this._pendingRequests = {};
+ this._initialize();
+ }
+ DebugMessaging.prototype = /** @lends DebugMessaging.prototype */{
+ _initialize: function() {
+ this._incoming = dojo.byId("orion-debugMessaging-toPage");
+ this._outgoing = dojo.byId("orion-debugMessaging-toExtension");
+
+ if (this._incoming) {
+ this.send("add-event-target");
+ var self = this;
+ this._incoming.addEventListener("DOMNodeInserted", function() {
+ var children = self._incoming.childNodes;
+ for (var i = children.length - 1; i >= 0; i--) {
+ var current = children[i];
+ self._incoming.removeChild(current);
+ var response = self._pendingRequests[current.id];
+ if (response) {
+ response(JSON.parse(current.innerText).data);
+ } else if (current.id.indexOf("event-") === 0) {
+ var start = current.id.indexOf("-") + 1;
+ var end = current.id.indexOf("-", start);
+ var content = JSON.parse(current.innerText);
+ var listenerId = current.id.substring(start, end);
+ if (listenerId === "global") {
+ for (var current in self._eventListeners) {
+ self._eventListeners[current](content.id, content.data);
+ }
+ } else {
+ var listener = self._eventListeners[listenerId];
+ if (listener) {
+ listener(content.id, content.data);
+ }
+ }
+ }
+ }
+ });
+ }
+ },
+ addEventListener: function(id, func) {
+ this._eventListeners[id] = func;
+ },
+ getId: function() {
+ return this._id;
+ },
+ removeEventListener: function(id) {
+ delete this._eventListeners[id];
+ },
+ send: function(requestId, data, response) {
+ if (!this._outgoing) {
+ return false;
+ }
+
+ var messageId = "req-" + this._counter++;
+ if (response) {
+ this._pendingRequests[messageId] = response;
+ }
+ var label = dojo.create("label", {id: messageId});
+ var content = {id: requestId, data: data || {}};
+ label.innerText = JSON.stringify(content);
+ label.style.display = "none";
+ dojo.place(label, this._outgoing, "first");
+ return true;
+ },
+ verifyExtension: function(callback) {
+ var timer = setTimeout(
+ function() {callback("The Orion Debug Extension for Chrome must be installed in order to use debug.");},
+ 999);
+ var self = this;
+ this.send("get-version", null, function(result) {
+ clearTimeout(timer);
+ if (result.version) {
+ if (result.version === self.REQUIRED_VERSION) {
+ callback();
+ } else {
+ callback("An updated version of the Orion Debug Extension for Chrome must be installed in order to use debug.");
+ }
+ } else {
+ callback("The Orion Debug Extension for Chrome must be installed in order to use debug.");
+ }
+ });
+ },
+ REQUIRED_VERSION: "0.3"
+ };
+ return DebugMessaging;
+ }());
+
+ return orion.debug;
+});
diff --git a/bundles/org.eclipse.orion.client.debug/web/debugTab.js b/bundles/org.eclipse.orion.client.debug/web/debugTab.js
index e53901f..82c6c97 100644
--- a/bundles/org.eclipse.orion.client.debug/web/debugTab.js
+++ b/bundles/org.eclipse.orion.client.debug/web/debugTab.js
@@ -17,50 +17,72 @@ define(['require', 'dojo'], function(require, dojo) {
var orion = {};
orion.debug = {};
+ var StatesEnum = {
+ STATE_DISCONNECTED: 0,
+ STATE_CONNECTED: 1,
+ STATE_ENABLED: 2,
+ STATE_SUSPENDING: 3,
+ STATE_RESUMING: 4,
+ STATE_SUSPENDED: 5
+ };
+
orion.debug.RemoteDebugTab = (function() {
function RemoteDebugTab(wsUrl, url) {
+ this._wsUrl = wsUrl;
+ this._url = url;
+
this._nextId = 1;
- this._state = this.StatesEnum.STATE_DISCONNECTED;
+ this._state = StatesEnum.STATE_DISCONNECTED;
this._pendingResponses = [];
- this._closeListeners = [];
+ this._detachListeners = [];
this._urlListeners = [];
- this._url = url;
- this._wsUrl = wsUrl;
- if (this._wsUrl) {
- this._socket = new WebSocket(this._wsUrl);
- var self = this;
- this._socket.onmessage = function(evt) {
- self._handleMessage(evt.data);
- };
- this._socket.onclose = function(evt) {
- self._state = self.StatesEnum.STATE_DISCONNECTED;
- for (var i = 0; i < self._closeListeners.length; i++) {
- self._closeListeners[i](self);
- }
- };
- this._socket.onopen = function(evt) {
- self._state = self.StatesEnum.STATE_CONNECTED;
- self.enable();
- if (!self._url) {
- self._updateUrl();
- }
- };
- }
}
RemoteDebugTab.prototype = /** @lends RemoteDebugTab.prototype */{
- addCloseListener: function(listener) {
- this._closeListeners.push(listener);
+ addDetachListener: function(listener) {
+ this._detachListeners.push(listener);
},
addUrlListener: function(listener) {
this._urlListeners.push(listener);
},
- close: function() {
+ attach: function(callback) {
+ var pendingCallback = callback;
+ if (this._wsUrl) {
+ this._socket = new WebSocket(this._wsUrl);
+ var self = this;
+ this._socket.onmessage = function(evt) {
+ self._handleMessage(evt.data);
+ };
+ this._socket.onclose = function(evt) {
+ self._state = StatesEnum.STATE_DISCONNECTED;
+ if (pendingCallback) {
+ pendingCallback("Failed to connect, remote tab is likely closed or has another debugger attached");
+ pendingCallback = null;
+ return;
+ }
+ for (var i = 0; i < self._detachListeners.length; i++) {
+ self._detachListeners[i](self);
+ }
+ };
+ this._socket.onopen = function(evt) {
+ self._state = StatesEnum.STATE_CONNECTED;
+ self.enable(pendingCallback);
+ pendingCallback = null;
+ if (!self._url) {
+ self._updateUrl();
+ }
+ };
+ }
+ },
+ detach: function(callback) {
if (this._socket) {
this._socket.close();
}
+ if (callback) {
+ callback();
+ }
},
- enable: function(listener) {
- if (!this._socket || this._state !== this.StatesEnum.STATE_CONNECTED) {
+ enable: function(callback) {
+ if (!this._socket || this._state !== StatesEnum.STATE_CONNECTED) {
return false;
}
var request = {
@@ -75,18 +97,20 @@ define(['require', 'dojo'], function(require, dojo) {
this._pendingResponses.push({
id: request.id,
action: function(event) {
- self._state = self.StatesEnum.STATE_ENABLED;
- if (listener) {
- listener();
+ if (!event.error) {
+ self._state = StatesEnum.STATE_ENABLED;
+ }
+ if (callback) {
+ callback(event.error);
}
}
});
}
return result;
},
- evaluate: function(expression, listener) {
+ evaluate: function(expression, callback) {
if (!this._socket ||
- (this._state !== this.StatesEnum.STATE_SUSPENDED && this._state !== this.StatesEnum.STATE_ENABLED)) {
+ (this._state !== StatesEnum.STATE_SUSPENDED && this._state !== StatesEnum.STATE_ENABLED)) {
return false;
}
var request;
@@ -115,28 +139,25 @@ define(['require', 'dojo'], function(require, dojo) {
this._pendingResponses.push({
id: request.id,
action: function(event) {
- if (listener) {
- listener(event.result.result);
+ if (callback) {
+ callback(event.error ? {error: event.error.message} : {result: event.result.result});
}
}
});
}
return result;
},
- getState: function() {
- return this._state;
- },
getUrl: function() {
return this._url;
},
getWSUrl: function() {
return this._wsUrl;
},
- removeCloseListener: function(listener) {
- for (var i = 0; i < this._closeListeners.length; i++) {
- var current = this._closeListeners[i];
+ removeDetachListener: function(listener) {
+ for (var i = 0; i < this._detachListeners.length; i++) {
+ var current = this._detachListeners[i];
if (current === listener) {
- this._closeListeners.splice(i, 1);
+ this._detachListeners.splice(i, 1);
return;
}
}
@@ -150,70 +171,71 @@ define(['require', 'dojo'], function(require, dojo) {
}
}
},
- resume: function(listener) {
- if (!this._socket || this._state !== this.StatesEnum.STATE_SUSPENDED) {
- return false;
- }
- var request = {
- id: this._nextId++,
- method: "Debugger.resume",
- params: {}
- };
- var requestString = JSON.stringify(request);
- var result = this._socket.send(requestString);
- if (result) {
- var self = this;
- this._pendingResponses.push({
- id: request.id,
- action: function(event) {
- self._state = self.StatesEnum.STATE_RESUMING;
- self._resumeListener = listener;
- }
- });
- }
- return result;
- },
- suspend: function(listener) {
- if (!this._socket || this._state !== this.StatesEnum.STATE_ENABLED) {
- return false;
- }
- var request = {
- id: this._nextId++,
- method: "Debugger.pause",
- params: {}
- };
- var requestString = JSON.stringify(request);
- var result = this._socket.send(requestString);
- if (result) {
- var self = this;
- this._pendingResponses.push({
- id: request.id,
- action: function(event) {
- self._state = self.StatesEnum.STATE_SUSPENDING;
- self._suspendListener = listener;
- }
- });
- }
- return result;
- },
+// resume: function(callback) {
+// if (!this._socket || this._state !== StatesEnum.STATE_SUSPENDED) {
+// return false;
+// }
+// var request = {
+// id: this._nextId++,
+// method: "Debugger.resume",
+// params: {}
+// };
+// var requestString = JSON.stringify(request);
+// var result = this._socket.send(requestString);
+// if (result) {
+// var self = this;
+// this._pendingResponses.push({
+// id: request.id,
+// action: function(event) {
+// self._state = StatesEnum.STATE_RESUMING;
+// self._resumeListener = callback;
+// }
+// });
+// }
+// return result;
+// },
+// suspend: function(callback) {
+// if (!this._socket || this._state !== StatesEnum.STATE_ENABLED) {
+// return false;
+// }
+// var request = {
+// id: this._nextId++,
+// method: "Debugger.pause",
+// params: {}
+// };
+// var requestString = JSON.stringify(request);
+// var result = this._socket.send(requestString);
+// if (result) {
+// var self = this;
+// this._pendingResponses.push({
+// id: request.id,
+// action: function(event) {
+// self._state = StatesEnum.STATE_SUSPENDING;
+// self._suspendListener = callback;
+// }
+// });
+// }
+// return result;
+// },
_handleMessage: function(wsMessage) {
var event = JSON.parse(wsMessage);
var method = event.method;
if (method === "Debugger.paused") {
this._frameId = event.params.callFrames[0].callFrameId;
- this._state = this.StatesEnum.STATE_SUSPENDED;
+ this._state = StatesEnum.STATE_SUSPENDED;
if (this._suspendListener) {
- this._suspendListener();
+ this._suspendListener(event.error);
this._suspendListener = null;
}
} else if (method === "Debugger.resumed") {
this._frameId = null;
- this._state = this.StatesEnum.STATE_ENABLED;
+ this._state = StatesEnum.STATE_ENABLED;
if (this._resumeListener) {
- this._resumeListener();
+ this._resumeListener(event.error);
this._resumeListener = null;
}
+ // TODO replace the following two with the new event
} else if (method === "Debugger.globalObjectCleared") {
this._url = null;
} else if (method === "Debugger.scriptParsed") {
@@ -251,29 +273,189 @@ define(['require', 'dojo'], function(require, dojo) {
this._pendingResponses.push({
id: request.id,
action: function(event) {
- var value = event.result.result.value;
- self._url = value;
- for (var i = 0; i < self._urlListeners.length; i++) {
- self._urlListeners[i](self._url, self);
+ if (event.error) {
+ // maybe display error somehow
+ } else {
+ var value = event.result.result.value;
+ self._url = value;
+ for (var i = 0; i < self._urlListeners.length; i++) {
+ self._urlListeners[i](self._url, self);
+ }
}
}
});
return true;
}
return false;
- },
-
- StatesEnum: {
- STATE_DISCONNECTED: "Disconnected",
- STATE_CONNECTED: "Connected",
- STATE_ENABLED: "Debugging",
- STATE_SUSPENDING: "Suspending...",
- STATE_RESUMING: "Resuming...",
- STATE_SUSPENDED: "Suspended"
}
};
return RemoteDebugTab;
}());
+ orion.debug.LocalDebugTab = (function() {
+ function LocalDebugTab(id, messaging, url) {
+ this._id = id;
+ this._messaging = messaging;
+ this._url = url;
+
+ this._state = StatesEnum.STATE_DISCONNECTED;
+ this._detachListeners = [];
+ this._pendingResponses = [];
+ this._urlListeners = [];
+
+ var self = this;
+ messaging.addEventListener(id, function(event, data) {
+ if (event === "detached") {
+ self._state = StatesEnum.STATE_DISCONNECTED;
+ for (var j = 0; j < self._detachListeners.length; j++) {
+ self._detachListeners[j](self);
+ }
+ } else if (event === "updateUrl") {
+ self._url = data.url;
+ for (var i = 0; i < self._urlListeners.length; i++) {
+ self._urlListeners[i](self._url, self);
+ }
+ }
+ });
+ }
+
+ LocalDebugTab.prototype = /** @lends LocalDebugTab.prototype */{
+ addDetachListener: function(listener) {
+ this._detachListeners.push(listener);
+ },
+ addUrlListener: function(listener) {
+ this._urlListeners.push(listener);
+ },
+ attach: function(callback) {
+ if (this._state === StatesEnum.STATE_CONNECTED || this._state === StatesEnum.STATE_ENABLED) {
+ if (callback) {
+ callback();
+ }
+ return;
+ }
+ var self = this;
+ this._messaging.send("attach", {id: this._id}, function(result) {
+ if (result.error) {
+ if (callback) {
+ callback(result.error.message);
+ }
+ return;
+ }
+ self._state = StatesEnum.STATE_CONNECTED;
+ self.enable(callback);
+ });
+ },
+ detach: function(callback) {
+ if (this._state === StatesEnum.STATE_DISCONNECTED) {
+ if (callback) {
+ callback();
+ }
+ return;
+ }
+ var self = this;
+ this._messaging.send("detach", {id: this._id}, function (result) {
+ if (result.error) {
+ if (callback) {
+ callback(result.error.message);
+ }
+ return;
+ }
+ self._state = StatesEnum.STATE_DISCONNECTED;
+ for (var j = 0; j < self._detachListeners.length; j++) {
+ self._detachListeners[j](self);
+ }
+ if (callback) {
+ callback();
+ }
+ });
+ },
+ enable: function(callback) {
+ var self = this;
+ this._messaging.send("send-command", {id: this._id, command: "Debugger.enable", args: {}}, function(result) {
+ if (result.error) {
+ if (callback) {
+ callback(result.error.message);
+ }
+ return;
+ }
+ self._state = StatesEnum.STATE_ENABLED;
+ if (!self._url) {
+ self._updateUrl();
+ }
+ if (callback) {
+ callback();
+ }
+ });
+ },
+ evaluate: function(expression, callback) {
+ if (this._state !== StatesEnum.STATE_SUSPENDED && this._state !== StatesEnum.STATE_ENABLED) {
+ return false;
+ }
+ var resultListener = function(result) {
+ if (result.error) {
+ if (callback) {
+ callback({error: result.error.message});
+ }
+ return;
+ }
+ if (callback) {
+ callback({result: result.result.result});
+ }
+ };
+
+ if (this._frameId) {
+ this._messaging.send(
+ "send-command",
+ {id: this._id, command: "Debugger.evaluateOnCallFrame", args: {callFrameId: this._frameId, expression: expression}},
+ resultListener);
+ } else {
+ this._messaging.send(
+ "send-command",
+ {id: this._id, command: "Runtime.evaluate", args: {expression: expression}},
+ resultListener);
+ }
+ },
+ getId: function() {
+ return this._id;
+ },
+ getUrl: function() {
+ return this._url;
+ },
+ removeDetachListener: function(listener) {
+ for (var i = 0; i < this._detachListeners.length; i++) {
+ var current = this._detachListeners[i];
+ if (current === listener) {
+ this._detachListeners.splice(i, 1);
+ return;
+ }
+ }
+ },
+ removeUrlListener: function(listener) {
+ for (var i = 0; i < this._urlListeners.length; i++) {
+ var current = this._urlListeners[i];
+ if (current === listener) {
+ this._urlListeners.splice(i, 1);
+ return;
+ }
+ }
+ },
+ _updateUrl: function() {
+ var self = this;
+ this._messaging.send("get-url", {id: this._id}, function(result) {
+ if (result.error) {
+ // TODO log
+ return;
+ }
+ self._url = result.url;
+ for (var i = 0; i < self._urlListeners.length; i++) {
+ self._urlListeners[i](self._url, self);
+ }
+ });
+ return true;
+ }
+ };
+ return LocalDebugTab;
+ }());
+
return orion.debug;
});
diff --git a/bundles/org.eclipse.orion.client.debug/web/ext/debugChromeExtension.crx b/bundles/org.eclipse.orion.client.debug/web/ext/debugChromeExtension.crx
new file mode 100644
index 0000000..67aa964
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.debug/web/ext/debugChromeExtension.crx
Binary files differ