| author | Grant Gayed | 2012-01-25 12:49:28 (EST) |
|---|---|---|
| committer | Silenio Quarti | 2012-01-25 14:06:47 (EST) |
| commit | 30f0c89cbf4006ddf9459e598a64356a1729cc15 (patch) (side-by-side diff) | |
| tree | e2e8a8d9d63c9fc4696efab0eb6dedf96ca00957 | |
| parent | c4e86691144c71195a108967b4a1f6a80ea0bed2 (diff) | |
| download | org.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
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 Binary files differindex 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 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 --- a/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 --- a/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));
+ }
+ }
+ });
+});
|

