aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrant Gayed2012-01-25 12:49:28 (EST)
committerSilenio Quarti2012-01-25 14:06:47 (EST)
commit30f0c89cbf4006ddf9459e598a64356a1729cc15 (patch)
treee2e8a8d9d63c9fc4696efab0eb6dedf96ca00957
parentc4e86691144c71195a108967b4a1f6a80ea0bed2 (diff)
downloadorg.eclipse.orion.client-30f0c89cbf4006ddf9459e598a64356a1729cc15.zip
org.eclipse.orion.client-30f0c89cbf4006ddf9459e598a64356a1729cc15.tar.gz
org.eclipse.orion.client-30f0c89cbf4006ddf9459e598a64356a1729cc15.tar.bz2
Bug 369710 - Debug contribution, various improvements and fixes
-rw-r--r--bundles/org.eclipse.orion.client.debug/chromeExtension/bin/debugChromeExtension.crxbin1414 -> 1525 bytes
-rw-r--r--bundles/org.eclipse.orion.client.debug/chromeExtension/src/debug.js88
-rw-r--r--bundles/org.eclipse.orion.client.debug/chromeExtension/src/manifest.json2
-rw-r--r--bundles/org.eclipse.orion.client.debug/web/connections.js202
-rw-r--r--bundles/org.eclipse.orion.client.debug/web/connectionsTree.js21
-rw-r--r--bundles/org.eclipse.orion.client.debug/web/debug.js251
-rw-r--r--bundles/org.eclipse.orion.client.debug/web/debugTab.js279
-rw-r--r--bundles/org.eclipse.orion.client.debug/web/portInputDialog.js52
8 files changed, 584 insertions, 311 deletions
diff --git a/bundles/org.eclipse.orion.client.debug/chromeExtension/bin/debugChromeExtension.crx b/bundles/org.eclipse.orion.client.debug/chromeExtension/bin/debugChromeExtension.crx
index 5ee241e..163fd90 100644
--- a/bundles/org.eclipse.orion.client.debug/chromeExtension/bin/debugChromeExtension.crx
+++ b/bundles/org.eclipse.orion.client.debug/chromeExtension/bin/debugChromeExtension.crx
Binary files differ
diff --git a/bundles/org.eclipse.orion.client.debug/chromeExtension/src/debug.js b/bundles/org.eclipse.orion.client.debug/chromeExtension/src/debug.js
index a07abfd..218ee59 100644
--- a/bundles/org.eclipse.orion.client.debug/chromeExtension/src/debug.js
+++ b/bundles/org.eclipse.orion.client.debug/chromeExtension/src/debug.js
@@ -1,47 +1,51 @@
/*******************************************************************************
-* @license
-* Copyright (c) 2011 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
-*******************************************************************************/
+ * @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
+ *******************************************************************************/
-var debugMessaging = document.getElementById("orion-debugMessaging");
-if (!debugMessaging) {
- return;
-}
+/*jslint browser:true*/
-debugMessaging.addEventListener("DOMNodeInserted", function() {
- var portLabel = document.getElementById("debug-port");
- if (!portLabel) {
- return;
- }
- var port = parseInt(portLabel.innerHTML);
- debugMessaging.removeChild(portLabel);
- if (port === NaN || !(1000 <= port && port < 65535)) {
- alert("Invalid port, value must be 1000 - 65535");
- return;
- }
- 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');
- responseLabel.style.display = 'none';
- responseLabel.innerHTML = xhr.responseText;
- debugMessaging.appendChild(responseLabel);
+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);
+ }
}
}
- }
- xhr.onerror = function () {
- alert("XHR error: " + xhr.status);
- };
- xhr.open("GET", url, true);
- 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
index 8348694..e1af3ba 100644
--- a/bundles/org.eclipse.orion.client.debug/chromeExtension/src/manifest.json
+++ b/bundles/org.eclipse.orion.client.debug/chromeExtension/src/manifest.json
@@ -1,6 +1,6 @@
{
"name":"Orion Debug Extension for Chrome",
- "version":"0.1",
+ "version":"0.2",
"content_scripts":[{
"matches":["http://*/*", "file://*/*"],
"js":["debug.js"]
diff --git a/bundles/org.eclipse.orion.client.debug/web/connections.js b/bundles/org.eclipse.orion.client.debug/web/connections.js
index 895293d..3170842 100644
--- a/bundles/org.eclipse.orion.client.debug/web/connections.js
+++ b/bundles/org.eclipse.orion.client.debug/web/connections.js
@@ -10,48 +10,82 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-/*global define orion*/
+/*global define orion localStorage*/
/*jslint browser:true*/
define(['require', 'dojo', 'orion/bootstrap', 'orion/commands', 'orion/fileClient',
- 'orion/searchClient', 'orion/globalCommands', 'debug/connectionsTree', 'orion/treetable',
- 'orion/widgets/NewSiteDialog'],
- function(require, dojo, mBootstrap, mCommands, mFileClient, mSearchClient, mGlobalCommands, mConnectionsTree, mTreeTable) {
+ 'orion/searchClient', 'orion/globalCommands', 'debug/connectionsTree', 'orion/treetable', 'debug/debugTab', 'debug/portInputDialog'],
+ function(require, dojo, mBootstrap, mCommands, mFileClient, mSearchClient, mGlobalCommands, mConnectionsTree, mTreeTable, mDebugTab) {
var treeWidget;
+
var model = new mConnectionsTree.DebugConnectionTreeModel("debug-tableTree");
function modelUpdated() {
model.getRoot(function(root) {
model.getChildren(root, function(children) {
treeWidget.refreshAndExpand(root, children);
for (var i = 0; i < children.length; i++) {
- treeWidget.refreshAndExpand(children[i], children[i].getConnections());
+ treeWidget.refreshAndExpand(children[i], children[i].getChildren());
}
});
});
}
+ 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 RemoteDebugConnection = (function() {
- function RemoteDebugConnection(info) {
- this._connections = [];
- var socketString = info.webSocketDebuggerUrl;
- var start = socketString.indexOf(':');
- start = socketString.indexOf(':', start + 1);
- var end = socketString.indexOf('/', start);
- this._port = socketString.substring(start + 1, end);
+ function RemoteDebugConnection(port) {
+ this._tabs = [];
+ this._port = port;
}
RemoteDebugConnection.prototype = /** @lends RemoteDebugConnection.prototype */ {
- addConnection: function(value) {
- this._connections.push(value);
+ 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.close();
+ this._tabs.splice(i, 1);
+ if (value) {
+ return;
+ }
+ }
+ }
},
getChildren: function() {
- return this.getConnections();
+ var result = [];
+ for (var i = 0; i < this._tabs.length; i++) {
+ result.push(new RemoteDebugTabProvider(this._tabs[i]));
+ }
+ return result;
+ },
+ getPort: function() {
+ return this._port;
},
- getConnections: function() {
- return this._connections;
+ 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.place(document.createTextNode(this.toString()), column, "last");
+ dojo.create("label", {innerHTML: this.toString().bold()}, column, "last");
},
shouldDisplayActions: function() {
return true;
@@ -63,26 +97,34 @@ define(['require', 'dojo', 'orion/bootstrap', 'orion/commands', 'orion/fileClien
return RemoteDebugConnection;
}());
- var RemoteDebugTab = (function() {
- function RemoteDebugTab(info) {
- this._wsUrl = info.webSocketDebuggerUrl;
- this._url = info.url;
+ // TODO this should move to debugTab.js
+ var RemoteDebugTabProvider = (function() {
+ function RemoteDebugTabProvider(remoteDebugTab) {
+ this._remoteDebugTab = remoteDebugTab;
}
- RemoteDebugTab.prototype = /** @lends RemoteDebugTab.prototype */{
+ RemoteDebugTabProvider.prototype = /** @lends RemoteDebugTabProvider.prototype */{
getChildren: function() {
return [];
},
+ getRemoteDebugTab: function() {
+ return this._remoteDebugTab;
+ },
getUrl: function() {
- return this._url;
+ return this._remoteDebugTab.getUrl();
},
getWSUrl: function() {
- return this._wsUrl;
+ return this._remoteDebugTab.getWSUrl();
},
renderLabel: function(column) {
- var base = require.toUrl("debug/debug.html");
- var url = base + "#" + this.getWSUrl();
- var urlLink = dojo.create("a", {href: url}, column, "last");
- dojo.place(document.createTextNode(this.getUrl()), urlLink, "last");
+ 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");
+ }
},
shouldDisplayActions: function() {
return false;
@@ -91,7 +133,7 @@ define(['require', 'dojo', 'orion/bootstrap', 'orion/commands', 'orion/fileClien
return this.getWSUrl();
}
};
- return RemoteDebugTab;
+ return RemoteDebugTabProvider;
}());
dojo.addOnLoad(function() {
@@ -106,6 +148,14 @@ define(['require', 'dojo', 'orion/bootstrap', 'orion/commands', 'orion/fileClien
var searcher = new mSearchClient.Searcher({serviceRegistry: serviceRegistry, commandService: commandService, fileService: fileClient});
mGlobalCommands.generateBanner("toolbar", serviceRegistry, commandService, preferences, searcher);
+ var isChrome = navigator.userAgent.indexOf("Chrome") !== -1;
+ if (!isChrome) {
+ var label = dojo.create("label");
+ label.innerHTML = "Sorry, Debug is currently only supported for Google Chrome browsers.";
+ dojo.place(label, "debugConnections-table", "first");
+ return;
+ }
+
var renderer = new mConnectionsTree.DebugConnectionRenderer(commandService);
treeWidget = new mTreeTable.TableTree({
id: "debug-tableTree",
@@ -120,15 +170,14 @@ define(['require', 'dojo', 'orion/bootstrap', 'orion/commands', 'orion/fileClien
tooltip: "Connect to a new browser",
id: "orion.debugConnections.connect",
groupId: "orion.debugGroup",
+ visibleWhen: function(item) {
+ return isChrome;
+ },
callback: function() {
- var dialog = new orion.widgets.NewSiteDialog({
- title: "Enter browser debug port",
+ var dialog = new orion.debug.PortInputDialog({
serviceRegistry: serviceRegistry,
- func: function(name, workspace) {
- var label = dojo.create("label", {id: "debug-port"});
- label.style.display = "none";
- label.innerHTML = name;
- dojo.place(label, "orion-debugMessaging", "first");
+ func: function(port) {
+ initiateConnection(port);
}
});
dialog.startup();
@@ -139,43 +188,92 @@ define(['require', 'dojo', 'orion/bootstrap', 'orion/commands', 'orion/fileClien
var disconnectCommand = new mCommands.Command({
name: "Disconnect",
- tooltip: "Disconnect from the target",
+ tooltip: "Disconnect",
imageClass: "core-sprite-problem",
id: "orion.debugConnections.disconnect",
visibleWhen: function(item) {
return true;
},
callback: function(data) {
- // TODO
+ 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");
- /* uncomment the following line to re-introduce the Disconnect action */
- // commandService.registerCommandContribution("orion.debugConnections.disconnect", 1);
+ 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 responseLabel = dojo.byId("debug-response");
- if (!responseLabel) {
- return;
+ 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 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);
+ }
+ changed = true;
+ }
+ }
}
- var info = JSON.parse(responseLabel.innerHTML);
- debugMessaging.removeChild(responseLabel);
- var connection = new RemoteDebugConnection(info[0]);
- for (var i = 0; i < info.length; i++) {
- var tab = new RemoteDebugTab(info[i]);
- connection.addConnection(tab);
+ if (changed) {
+ modelUpdated();
}
- treeModel.addConnection(connection);
- modelUpdated();
});
}
+
+ var portsString = localStorage.getItem("orion.debug.chromeDebugPorts");
+ if (portsString) {
+ var portsObject = JSON.parse(portsString);
+ for (var port in portsObject) {
+ initiateConnection(port);
+ }
+ }
});
});
});
diff --git a/bundles/org.eclipse.orion.client.debug/web/connectionsTree.js b/bundles/org.eclipse.orion.client.debug/web/connectionsTree.js
index 3895852..4675ed1 100644
--- a/bundles/org.eclipse.orion.client.debug/web/connectionsTree.js
+++ b/bundles/org.eclipse.orion.client.debug/web/connectionsTree.js
@@ -25,7 +25,16 @@ 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();
+ for (var i = 0; i < this._root.length; i++) {
+ var current = this._root[i];
+ if (current.getPort() === port) {
+ return false;
+ }
+ }
this._root.push(connection);
+ return true;
},
getRoot: function(/**function*/ onItem) {
onItem(this);
@@ -35,6 +44,15 @@ define(['require', 'dojo'], function(require, dojo) {
},
getId: function(/**dojo.data.Item|String*/ item) {
return (item === this || item === this._id) ? this._id : item.toString();
+ },
+ removeConnection: function(connection) {
+ for (var i = 0; i < this._root.length; i++) {
+ var current = this._root[i];
+ if (current === connection) {
+ this._root.splice(i, 1);
+ return;
+ }
+ }
}
};
return DebugConnectionTreeModel;
@@ -87,7 +105,6 @@ define(['require', 'dojo'], function(require, dojo) {
};
return DebugConnectionRenderer;
}());
-
+
return orion.debug;
});
-
diff --git a/bundles/org.eclipse.orion.client.debug/web/debug.js b/bundles/org.eclipse.orion.client.debug/web/debug.js
index fb2e104..814ce4c 100644
--- a/bundles/org.eclipse.orion.client.debug/web/debug.js
+++ b/bundles/org.eclipse.orion.client.debug/web/debug.js
@@ -7,222 +7,17 @@
* License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html).
*
* Contributors:
-* IBM Corporation - initial API and implementation
+ * IBM Corporation - initial API and implementation
*******************************************************************************/
/*global define WebSocket*/
/*jslint browser:true*/
-define(['require', 'dojo', 'orion/bootstrap', 'orion/commands', 'orion/fileClient', 'orion/searchClient', 'orion/globalCommands', 'orion/console'],
- function(require, dojo, mBootstrap, mCommands, mFileClient, mSearchClient, mGlobalCommands, mConsole) {
-
- var console;
- var commandService;
+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 RemoteDebugTab = (function() {
- function RemoteDebugTab(wsUrl) {
- this._nextId = 1;
- this._state = this.StatesEnum.STATE_DISCONNECTED;
- this._wsUrl = wsUrl;
- this._pendingResponses = [];
- this._socket = new WebSocket(wsUrl);
- var self = this;
- this._socket.onmessage = function(evt) {
- self._handleMessage(evt.data);
- };
- this._socket.onclose = function(evt) {
- self._state = self.StatesEnum.STATE_DISCONNECTED;
- var location = dojo.byId("location");
- if (location) {
- location.innerHTML = null;
- }
- console.appendOutput("<< Disconnected from external browser >>");
- console.setAcceptInput(false);
- };
- this._socket.onopen = function(evt) {
- self._state = self.StatesEnum.STATE_CONNECTED;
- self.enable();
- self._updateUrl();
- };
- }
- RemoteDebugTab.prototype = /** @lends RemoteDebugTab.prototype */{
- enable: function() {
- if (this._state !== this.StatesEnum.STATE_CONNECTED) {
- return false;
- }
- var request = {
- id: this._nextId++,
- method: "Debugger.enable",
- 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_ENABLED;
- }
- });
- }
- return result;
- },
- evaluate: function(expression) {
- if (this._state !== this.StatesEnum.STATE_SUSPENDED &&
- this._state !== this.StatesEnum.STATE_ENABLED) {
- return false;
- }
- var request;
- if (this._frameId) {
- request = {
- id: this._nextId++,
- method: "Debugger.evaluateOnCallFrame",
- params: {
- callFrameId: this._frameId,
- expression: expression
- }
- };
- } else {
- request = {
- id: this._nextId++,
- method: "Runtime.evaluate",
- params: {
- expression: expression
- }
- };
- }
-
- var requestString = JSON.stringify(request);
- var result = this._socket.send(requestString);
- if (result) {
- this._pendingResponses.push({
- id: request.id,
- action: function(event) {
- console.appendOutput(JSON.stringify(event.result.result));
- }
- });
- }
- return result;
- },
- getState: function() {
- return this._state;
- },
- getUrl: function() {
- return this._url;
- },
- resume: function() {
- if (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;
- }
- });
- }
- return result;
- },
- suspend: function() {
- if (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;
- }
- });
- }
- 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;
- } else if (method === "Debugger.resumed") {
- this._frameId = null;
- this._state = this.StatesEnum.STATE_ENABLED;
- } else if (method === "Debugger.globalObjectCleared") {
- this._url = null;
- } else if (method === "Debugger.scriptParsed") {
- if (!this._url) {
- this._updateUrl();
- }
- } else if (!method) {
- for (var i = 0; i < this._pendingResponses.length; i++) {
- var current = this._pendingResponses[i];
- if (current.id === event.id) {
- current.action(event);
- this._pendingResponses.splice(i, 1);
- break;
- }
- }
- }
- },
- _updateUrl: function() {
- // TODO is there really not a better request to send here?
- var request = {
- id: this._nextId++,
- method: "Runtime.evaluate",
- params: {
- expression: "document.location.href"
- }
- };
- var requestString = JSON.stringify(request);
- var result = this._socket.send(requestString);
- if (result) {
- this._pendingResponses.push({
- id: request.id,
- action: function(event) {
- var value = event.result.result.value;
- if (value === "about:blank") {
- this._url = null;
- } else {
- this._url = value;
- }
- var location = dojo.byId("location");
- if (location) {
- location.innerHTML = this._url;
- }
- }
- });
- }
- },
-
- StatesEnum: {
- STATE_DISCONNECTED: "Disconnected",
- STATE_CONNECTED: "Connected",
- STATE_ENABLED: "Debugging",
- STATE_SUSPENDING: "Suspending...",
- STATE_RESUMING: "Resuming...",
- STATE_SUSPENDED: "Suspended"
- }
- };
- return RemoteDebugTab;
- }());
+ var console;
dojo.addOnLoad(function() {
mBootstrap.startup().then(function(core) {
@@ -231,18 +26,46 @@ define(['require', 'dojo', 'orion/bootstrap', 'orion/commands', 'orion/fileClien
document.body.style.visibility = "visible";
dojo.parser.parse();
- commandService = new mCommands.CommandService({serviceRegistry: serviceRegistry});
+ var commandService = new mCommands.CommandService({serviceRegistry: serviceRegistry});
var fileClient = new mFileClient.FileClient(serviceRegistry);
var searcher = new mSearchClient.Searcher({serviceRegistry: serviceRegistry, commandService: commandService, fileService: fileClient});
mGlobalCommands.generateBanner("toolbar", serviceRegistry, commandService, preferences, searcher);
+ var isChrome = navigator.userAgent.indexOf("Chrome") !== -1;
+ if (!isChrome) {
+ var label = dojo.create("label");
+ label.innerHTML = "Sorry, Debug is currently only supported for Google Chrome browsers.";
+ dojo.place(label, "debug-console", "first");
+ return;
+ }
+
var hash = dojo.hash();
- var connection = new RemoteDebugTab(hash);
+ var connection = new mDebugTab.RemoteDebugTab(hash);
+ connection.addCloseListener(function() {
+ var location = dojo.byId("location");
+ if (location) {
+ location.innerHTML = null;
+ }
+ console.appendOutput("<< Disconnected from external browser >>");
+ 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);
+ connection.evaluate(inputEvent, function(result) {
+ console.appendOutput(JSON.stringify(result));
+ });
});
-
});
});
});
diff --git a/bundles/org.eclipse.orion.client.debug/web/debugTab.js b/bundles/org.eclipse.orion.client.debug/web/debugTab.js
new file mode 100644
index 0000000..e53901f
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.debug/web/debugTab.js
@@ -0,0 +1,279 @@
+/*******************************************************************************
+* @license
+* Copyright (c) 2011, 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 WebSocket*/
+
+define(['require', 'dojo'], function(require, dojo) {
+
+ var orion = {};
+ orion.debug = {};
+
+ orion.debug.RemoteDebugTab = (function() {
+ function RemoteDebugTab(wsUrl, url) {
+ this._nextId = 1;
+ this._state = this.StatesEnum.STATE_DISCONNECTED;
+ this._pendingResponses = [];
+ this._closeListeners = [];
+ 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);
+ },
+ addUrlListener: function(listener) {
+ this._urlListeners.push(listener);
+ },
+ close: function() {
+ if (this._socket) {
+ this._socket.close();
+ }
+ },
+ enable: function(listener) {
+ if (!this._socket || this._state !== this.StatesEnum.STATE_CONNECTED) {
+ return false;
+ }
+ var request = {
+ id: this._nextId++,
+ method: "Debugger.enable",
+ 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_ENABLED;
+ if (listener) {
+ listener();
+ }
+ }
+ });
+ }
+ return result;
+ },
+ evaluate: function(expression, listener) {
+ if (!this._socket ||
+ (this._state !== this.StatesEnum.STATE_SUSPENDED && this._state !== this.StatesEnum.STATE_ENABLED)) {
+ return false;
+ }
+ var request;
+ if (this._frameId) {
+ request = {
+ id: this._nextId++,
+ method: "Debugger.evaluateOnCallFrame",
+ params: {
+ callFrameId: this._frameId,
+ expression: expression
+ }
+ };
+ } else {
+ request = {
+ id: this._nextId++,
+ method: "Runtime.evaluate",
+ params: {
+ expression: expression
+ }
+ };
+ }
+
+ var requestString = JSON.stringify(request);
+ var result = this._socket.send(requestString);
+ if (result) {
+ this._pendingResponses.push({
+ id: request.id,
+ action: function(event) {
+ if (listener) {
+ listener(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];
+ if (current === listener) {
+ this._closeListeners.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;
+ }
+ }
+ },
+ 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;
+ },
+
+ _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;
+ if (this._suspendListener) {
+ this._suspendListener();
+ this._suspendListener = null;
+ }
+ } else if (method === "Debugger.resumed") {
+ this._frameId = null;
+ this._state = this.StatesEnum.STATE_ENABLED;
+ if (this._resumeListener) {
+ this._resumeListener();
+ this._resumeListener = null;
+ }
+ } else if (method === "Debugger.globalObjectCleared") {
+ this._url = null;
+ } else if (method === "Debugger.scriptParsed") {
+ if (!this._url) {
+ this._updateUrl();
+ }
+ } else if (!method) {
+ for (var i = 0; i < this._pendingResponses.length; i++) {
+ var current = this._pendingResponses[i];
+ if (current.id === event.id) {
+ current.action(event);
+ this._pendingResponses.splice(i, 1);
+ break;
+ }
+ }
+ }
+ },
+ _updateUrl: function() {
+ if (!this._socket) {
+ return false;
+ }
+
+ // TODO is there really not a better request to send here?
+ var request = {
+ id: this._nextId++,
+ method: "Runtime.evaluate",
+ params: {
+ expression: "document.location.href"
+ }
+ };
+ 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) {
+ 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;
+ }());
+
+ return orion.debug;
+});
diff --git a/bundles/org.eclipse.orion.client.debug/web/portInputDialog.js b/bundles/org.eclipse.orion.client.debug/web/portInputDialog.js
new file mode 100644
index 0000000..cfb69fa
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.debug/web/portInputDialog.js
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * @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 orion dojo dijit widgets*/
+/*jslint browser:true*/
+
+define(['dojo', 'orion/widgets/NewItemDialog'], function(dojo, dijit) {
+
+ /**
+ * @param options.serviceRegistry {eclipse.ServiceRegistry}
+ * @param options.func {Function} Invoked on OK with (port) as parameter
+ */
+ dojo.declare("orion.debug.PortInputDialog", [orion.widgets.NewItemDialog], {
+ constructor: function(options) {
+ this.options = options;
+ this.options.title = "Enter Chrome browser debug port (1000-65534)";
+ this.options.label = "Port:";
+ },
+ postMixInProperties: function() {
+ this.inherited(arguments);
+ },
+ postCreate: function() {
+ this.inherited(arguments);
+ dojo.style(this.itemName, "width", "20em;");
+ this.itemName.set("required", true);
+ this.itemName.set("isValid", dojo.hitch(this, function(focused) {
+ var port = parseInt(dojo.trim(this.itemName.get("value")), 10);
+ this.newItemButton.set("disabled", isNaN(port) || !(1000 <= port && port < 65535));
+ return !isNaN(port);
+ }));
+ },
+ _onSubmit: function() {
+ if (this.itemName.isValid()) {
+ this.inherited(arguments);
+ }
+ },
+ execute: function() {
+ if (this.options.func) {
+ this.options.func(parseInt(dojo.trim(this.itemName.get("value")), 10));
+ }
+ }
+ });
+});