Skip to content

Instantly share code, notes, and snippets.

@robcee
Created December 27, 2012 20:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robcee/4391640 to your computer and use it in GitHub Desktop.
Save robcee/4391640 to your computer and use it in GitHub Desktop.
diff --git a/browser/devtools/scratchpad/scratchpad.js b/browser/devtools/scratchpad/scratchpad.js
--- a/browser/devtools/scratchpad/scratchpad.js
+++ b/browser/devtools/scratchpad/scratchpad.js
@@ -23,19 +23,22 @@ Cu.import("resource://gre/modules/Servic
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource:///modules/PropertyPanel.jsm");
Cu.import("resource:///modules/source-editor.jsm");
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm");
Cu.import("resource:///modules/devtools/scratchpad-manager.jsm");
Cu.import("resource://gre/modules/jsdebugger.jsm");
Cu.import("resource:///modules/devtools/gDevTools.jsm");
Cu.import("resource:///modules/devtools/Target.jsm");
+Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
+Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
const SCRATCHPAD_CONTEXT_CONTENT = 1;
const SCRATCHPAD_CONTEXT_BROWSER = 2;
+const SCRATCHPAD_CONTEXT_DEBUGGER = 3;
const SCRATCHPAD_L10N = "chrome://browser/locale/devtools/scratchpad.properties";
const DEVTOOLS_CHROME_ENABLED = "devtools.chrome.enabled";
const PREF_RECENT_FILES_MAX = "devtools.scratchpad.recentFilesMax";
const BUTTON_POSITION_SAVE = 0;
const BUTTON_POSITION_CANCEL = 1;
const BUTTON_POSITION_DONT_SAVE = 2;
const BUTTON_POSITION_REVERT=0;
@@ -50,18 +53,20 @@ var Scratchpad = {
* The script execution context. This tells Scratchpad in which context the
* script shall execute.
*
* Possible values:
* - SCRATCHPAD_CONTEXT_CONTENT to execute code in the context of the current
* tab content window object.
* - SCRATCHPAD_CONTEXT_BROWSER to execute code in the context of the
* currently active chrome window object.
+ * - SCRATCHPAD_CONTEXT_DEBUGGER to execute code in the context of the
+ * current tab content window object via the Debugger API.
*/
- executionContext: SCRATCHPAD_CONTEXT_CONTENT,
+ executionContext: SCRATCHPAD_CONTEXT_DEBUGGER,
/**
* Tells if this Scratchpad is initialized and ready for use.
* @boolean
* @see addObserver
*/
initialized: false,
@@ -204,16 +209,21 @@ var Scratchpad = {
},
/**
* Cached Cu.Sandbox object for the active tab content window object.
*/
_contentSandbox: null,
/**
+ * Cached Debugger object for the active tab content window object.
+ */
+ _contentDebugger: null,
+
+ /**
* Unique name for the current Scratchpad instance. Used to distinguish
* Scratchpad windows between each other. See bug 661762.
*/
get uniqueName()
{
return "Scratchpad/" + this._instanceId;
},
@@ -246,16 +256,151 @@ var Scratchpad = {
this._previousBrowser = this.gBrowser.selectedBrowser;
this._previousLocation = contentWindow.location.href;
}
return this._contentSandbox;
},
/**
+ * Get the content debugger.
+ */
+ get contentDebugger()
+ {
+ if (!this.browserWindow) {
+ Cu.reportError(this.strings.
+ GetStringFromName("browserWindow.unavailable"));
+ return;
+ }
+
+ if (!this._contentDebugger ||
+ this.browse rWindow != this._previousBrowserWindow ||
+ this._previousBrowser != this.gBrowser.selectedBrowser ||
+ this._previousLocation != this.gBrowser.contentWindow.location.href) {
+ let contentWindow = this.gBrowser.selectedBrowser.contentWindow;
+ this._contentDebugger =
+ }
+
+ // Content or chrome debugging can connect directly to the debuggee.
+ // TODO: convert this to use a TabTarget.
+ let transport = DebuggerServer.connectPipe();
+
+ let client = this.client = new DebuggerClient(transport);
+ client.addListener("tabNavigated", this._onTabNavigated);
+ client.addListener("tabDetached", this._onTabDetached);
+ window.addEventListener("unload", this._shutdownDebugger, true);
+
+ client.connect(function(aType, aTraits) {
+ client.listTabs(function(aResponse) {
+ let tab = aResponse.tabs[aResponse.selected];
+ this._startDebuggingTab(client, tab, callback);
+ }.bind(this));
+ }.bind(this));
+ },
+
+ /**
+ * Sets up a debugging session.
+ *
+ * @param DebuggerClient aClient
+ * The debugger client.
+ * @param object aTabGrip
+ * The remote protocol grip of the tab.
+ */
+ _startDebuggingTab: function DC__startDebuggingTab(aClient, aTabGrip, aCallback) {
+ if (!aClient) {
+ Cu.reportError("No client found!");
+ return;
+ }
+ this.client = aClient;
+
+ aClient.attachTab(aTabGrip.actor, function(aResponse, aTabClient) {
+ if (!aTabClient) {
+ Cu.reportError("No tab client found!");
+ return;
+ }
+ this.tabClient = aTabClient;
+
+ aClient.attachThread(aResponse.threadActor, function(aResponse, aThreadClient) {
+ if (!aThreadClient) {
+ Cu.reportError("Couldn't attach to thread: " + aResponse.error);
+ return;
+ }
+ this.activeThread = aThreadClient;
+
+ this.ThreadState.connect();
+ this.StackFrames.connect();
+ this.SourceScripts.connect();
+ aThreadClient.resume();
+
+ if (aCallback) {
+ aCallback();
+ }
+ }.bind(this));
+ }.bind(this));
+ },
+
+ /**
+ * Called for each location change in the debugged tab.
+ *
+ * @param string aType
+ * Packet type.
+ * @param object aPacket
+ * Packet received from the server.
+ */
+ _onTabNavigated: function DC__onTabNavigated(aType, aPacket) {
+ this._shutdownDebugger();
+ /* XXX controller poo. We can just disconnect and start over here.
+ if (aPacket.state == "start") {
+ DebuggerView._handleTabNavigation();
+ return;
+ }
+
+ this.ThreadState._handleTabNavigation();
+ this.StackFrames._handleTabNavigation();
+ this.SourceScripts._handleTabNavigation();
+ */
+ },
+
+ /**
+ * Called when the debugged tab is closed.
+ */
+ _onTabDetached: function DC__onTabDetached() {
+ this._shutdownDebugger();
+ },
+
+ /**
+ * Disconnects the debugger client and removes event handlers as necessary.
+ */
+ _disconnect: function DC__disconnect() {
+ // Return early if the client didn't even have a chance to instantiate.
+ if (!this.client) {
+ return;
+ }
+ this.client.removeListener("tabNavigated", this._onTabNavigated);
+ this.client.removeListener("tabDetached", this._onTabDetached);
+
+ this.client = null;
+ this.tabClient = null;
+ this.activeThread = null;
+ },
+
+ /**
+ * Disconnects the debugger client from the server.
+ */
+ _shutdownDebugger: function DC__shutdownDebugger() {
+ window.removeEventListener("unload", this._shutdownDebugger, true);
+
+ // XXX this.SourceScripts.disconnect();
+ // this.StackFrames.disconnect();
+ // this.ThreadState.disconnect();
+
+ this._disconnect();
+ },
+
+ /**
* Cached Cu.Sandbox object for the most recently active navigator:browser
* chrome window object.
*/
_chromeSandbox: null,
/**
* Get the Cu.Sandbox object for the most recently active navigator:browser
* chrome window object. Note that the returned object is cached for later
diff --git a/browser/devtools/scratchpad/scratchpad.xul b/browser/devtools/scratchpad/scratchpad.xul
--- a/browser/devtools/scratchpad/scratchpad.xul
+++ b/browser/devtools/scratchpad/scratchpad.xul
@@ -41,16 +41,17 @@
-->
<command id="sp-cmd-close" oncommand="Scratchpad.close();"/>
<command id="sp-cmd-run" oncommand="Scratchpad.run();"/>
<command id="sp-cmd-inspect" oncommand="Scratchpad.inspect();"/>
<command id="sp-cmd-display" oncommand="Scratchpad.display();"/>
<command id="sp-cmd-contentContext" oncommand="Scratchpad.setContentContext();"/>
<command id="sp-cmd-browserContext" oncommand="Scratchpad.setBrowserContext();" disabled="true"/>
+ <command id="sp-cmd-debugContext" oncommand="Scratchpad.setDebugContext();"/>
<command id="sp-cmd-reloadAndRun" oncommand="Scratchpad.reloadAndRun();"/>
<command id="sp-cmd-resetContext" oncommand="Scratchpad.resetContext();"/>
<command id="sp-cmd-errorConsole" oncommand="Scratchpad.openErrorConsole();" disabled="true"/>
<command id="sp-cmd-webConsole" oncommand="Scratchpad.openWebConsole();"/>
<command id="sp-cmd-documentationLink" oncommand="Scratchpad.openDocumentationPage();"/>
</commandset>
<keyset id="sourceEditorKeys"/>
@@ -219,16 +220,21 @@
command="sp-cmd-contentContext"
checked="true"
type="radio"/>
<menuitem id="sp-menu-browser"
command="sp-cmd-browserContext"
label="&browserContext.label;"
accesskey="&browserContext.accesskey;"
type="radio"/>
+ <menuitem id="sp-menu-debug"
+ command="sp-cmd-debugContext"
+ label="&debugContext.label;"
+ accesskey="&debugContext.accesskey;"
+ type="radio"/>
</menupopup>
</menu>
#ifdef XP_WIN
<menu id="sp-help-menu"
label="&helpMenu.label;"
accesskey="&helpMenuWin.accesskey;">
#else
diff --git a/browser/locales/en-US/chrome/browser/devtools/scratchpad.dtd b/browser/locales/en-US/chrome/browser/devtools/scratchpad.dtd
--- a/browser/locales/en-US/chrome/browser/devtools/scratchpad.dtd
+++ b/browser/locales/en-US/chrome/browser/devtools/scratchpad.dtd
@@ -82,16 +82,22 @@
- to select an execution environment for the browser window itself as opposed
- to content. This is a feature for browser and addon developers and only
- enabled via the devtools.chrome.enabled preference. Formerly, this label
- was called "Chrome".
-->
<!ENTITY browserContext.label "Browser">
<!ENTITY browserContext.accesskey "B">
+<!-- LOCALIZATION NOTE (debugContext.label, accesskey): This menu item is used
+ - to select an execution environment that runs against the Debug server.
+ -->
+<!ENTITY debugContext.label "Debug">
+<!ENTITY debugContext.accesskey "D">
+
<!-- LOCALIZATION NOTE some localizations of Windows (ex:french, german) use "?"
- for the help button in the menubar but Gnome does not.
-->
<!ENTITY helpMenu.label "Help">
<!ENTITY helpMenu.accesskey "H">
<!ENTITY helpMenuWin.label "Help">
<!ENTITY helpMenuWin.accesskey "H">
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment