Bug 741324 - Make it possible to start a debugger in a new firefox instance; r=past,rcampbell,zpao
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1053,19 +1053,24 @@ pref("devtools.inspector.sidebarOpen", f
pref("devtools.inspector.activeSidebar", "ruleview");
// Enable the Layout View
pref("devtools.layoutview.enabled", false);
pref("devtools.layoutview.open", false);
// Enable the Debugger
pref("devtools.debugger.enabled", false);
+pref("devtools.debugger.remote-enabled", false);
+pref("devtools.debugger.remote-host", "localhost");
+pref("devtools.debugger.remote-port", 6000);
// The default Debugger UI height
pref("devtools.debugger.ui.height", 250);
+pref("devtools.debugger.ui.remote-win.width", 900);
+pref("devtools.debugger.ui.remote-win.height", 400);
// Enable the style inspector
pref("devtools.styleinspector.enabled", true);
// Enable the Tilt inspector
pref("devtools.tilt.enabled", true);
pref("devtools.tilt.intro_transition", true);
pref("devtools.tilt.outro_transition", true);
--- a/browser/base/content/browser-appmenu.inc
+++ b/browser/base/content/browser-appmenu.inc
@@ -189,16 +189,20 @@
type="checkbox"
command="Tools:Inspect"
key="key_inspect"/>
<menuitem id="appmenu_debugger"
hidden="true"
label="&debuggerMenu.label;"
key="key_debugger"
command="Tools:Debugger"/>
+ <menuitem id="appmenu_remoteDebugger"
+ hidden="true"
+ label="&remoteDebuggerMenu.label;"
+ command="Tools:RemoteDebugger"/>
<menuitem id="appmenu_scratchpad"
hidden="true"
label="&scratchpad.label;"
key="key_scratchpad"
command="Tools:Scratchpad"/>
<menuitem id="appmenu_styleeditor"
hidden="true"
label="&styleeditor.label;"
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -546,16 +546,20 @@
accesskey="&inspectMenu.accesskey;"
key="key_inspect"
command="Tools:Inspect"/>
<menuitem id="menu_debugger"
hidden="true"
label="&debuggerMenu.label;"
key="key_debugger"
command="Tools:Debugger"/>
+ <menuitem id="menu_remoteDebugger"
+ hidden="true"
+ label="&remoteDebuggerMenu.label;"
+ command="Tools:RemoteDebugger"/>
<menuitem id="menu_scratchpad"
hidden="true"
label="&scratchpad.label;"
accesskey="&scratchpad.accesskey;"
key="key_scratchpad"
command="Tools:Scratchpad"/>
<menuitem id="menu_styleeditor"
hidden="true"
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -124,16 +124,17 @@
<command id="cmd_fullZoomToggle" oncommand="ZoomManager.toggleZoom();"/>
<command id="Browser:OpenLocation" oncommand="openLocation();"/>
<command id="Tools:Search" oncommand="BrowserSearch.webSearch();"/>
<command id="Tools:Downloads" oncommand="BrowserDownloadsUI();"/>
<command id="Tools:WebConsole" oncommand="HUDConsoleUI.toggleHUD();"/>
<command id="Tools:Inspect" oncommand="InspectorUI.toggleInspectorUI();" disabled="true"/>
<command id="Tools:Debugger" oncommand="DebuggerUI.toggleDebugger();" disabled="true"/>
+ <command id="Tools:RemoteDebugger" oncommand="DebuggerUI.toggleRemoteDebugger();" disabled="true"/>
<command id="Tools:Scratchpad" oncommand="Scratchpad.openScratchpad();" disabled="true"/>
<command id="Tools:StyleEditor" oncommand="StyleEditor.openChrome();" disabled="true"/>
<command id="Tools:Addons" oncommand="BrowserOpenAddonsMgr();"/>
<command id="Tools:Sanitize"
oncommand="Cc['@mozilla.org/browser/browserglue;1'].getService(Ci.nsIBrowserGlue).sanitize(window);"/>
<command id="Tools:PrivateBrowsing" oncommand="gPrivateBrowsingUI.toggleMode();"/>
<command id="History:UndoCloseTab" oncommand="undoCloseTab();"/>
<command id="History:UndoCloseWindow" oncommand="undoCloseWindow();"/>
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1711,16 +1711,26 @@ function delayedStartup(isLoadingBlank,
if (enabled) {
document.getElementById("menu_debugger").hidden = false;
document.getElementById("Tools:Debugger").removeAttribute("disabled");
#ifdef MENUBAR_CAN_AUTOHIDE
document.getElementById("appmenu_debugger").hidden = false;
#endif
}
+ // Enable Remote Debugger?
+ let enabled = gPrefService.getBoolPref("devtools.debugger.remote-enabled");
+ if (enabled) {
+ document.getElementById("menu_remoteDebugger").hidden = false;
+ document.getElementById("Tools:RemoteDebugger").removeAttribute("disabled");
+#ifdef MENUBAR_CAN_AUTOHIDE
+ document.getElementById("appmenu_remoteDebugger").hidden = false;
+#endif
+ }
+
// Enable Error Console?
// XXX Temporarily always-enabled, see bug 601201
let consoleEnabled = true || gPrefService.getBoolPref("devtools.errorconsole.enabled");
if (consoleEnabled) {
document.getElementById("javascriptConsole").hidden = false;
document.getElementById("key_errorConsole").removeAttribute("disabled");
#ifdef MENUBAR_CAN_AUTOHIDE
document.getElementById("appmenu_errorConsole").hidden = false;
--- a/browser/devtools/debugger/DebuggerUI.jsm
+++ b/browser/devtools/debugger/DebuggerUI.jsm
@@ -40,17 +40,23 @@
*
* ***** END LICENSE BLOCK ***** */
"use strict";
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
+const DBG_XUL = "chrome://browser/content/debugger.xul";
+const REMOTE_PROFILE_NAME = "_remote-debug";
+
+Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/FileUtils.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
let EXPORTED_SYMBOLS = ["DebuggerUI"];
/**
* Provides a simple mechanism of managing debugger instances per tab.
*
* @param nsIDOMWindow aWindow
* The chrome window for which the DebuggerUI instance is created.
@@ -71,59 +77,85 @@ DebuggerUI.prototype = {
if (tab._scriptDebugger) {
tab._scriptDebugger.close();
return null;
}
return new DebuggerPane(tab);
},
/**
+ * Starts a remote debugger in a new process, or stops it if already started.
+ * @see DebuggerProcess.constructor
+ * @return DebuggerProcess if the debugger is started, null if it's stopped.
+ */
+ toggleRemoteDebugger: function DUI_toggleRemoteDebugger(aOnClose, aOnRun) {
+ let win = this.chromeWindow;
+
+ if (win._remoteDebugger) {
+ win._remoteDebugger.close();
+ return null;
+ }
+ return new DebuggerProcess(win, aOnClose, aOnRun);
+ },
+
+ /**
* Get the debugger for a specified tab.
* @return DebuggerPane if a debugger exists for the tab, null otherwise
*/
getDebugger: function DUI_getDebugger(aTab) {
return aTab._scriptDebugger;
},
/**
* Get the preferences associated with the debugger frontend.
* @return object
*/
get preferences() {
- return DebuggerUIPreferences;
+ return DebuggerPreferences;
}
};
/**
* Creates a pane that will host the debugger.
*
* @param XULElement aTab
* The tab in which to create the debugger.
*/
function DebuggerPane(aTab) {
this._tab = aTab;
+ this._initServer();
this._create();
}
DebuggerPane.prototype = {
/**
+ * Initializes the debugger server.
+ */
+ _initServer: function DP__initServer() {
+ if (!DebuggerServer.initialized) {
+ DebuggerServer.init();
+ DebuggerServer.addBrowserActors();
+ }
+ },
+
+ /**
* Creates and initializes the widgets containing the debugger UI.
*/
_create: function DP__create() {
this._tab._scriptDebugger = this;
let gBrowser = this._tab.linkedBrowser.getTabBrowser();
let ownerDocument = gBrowser.parentNode.ownerDocument;
this._splitter = ownerDocument.createElement("splitter");
this._splitter.setAttribute("class", "hud-splitter");
this._frame = ownerDocument.createElement("iframe");
- this._frame.height = DebuggerUIPreferences.height;
+ this._frame.height = DebuggerPreferences.height;
this._nbox = gBrowser.getNotificationBox(this._tab.linkedBrowser);
this._nbox.appendChild(this._splitter);
this._nbox.appendChild(this._frame);
this.close = this.close.bind(this);
let self = this;
@@ -134,30 +166,30 @@ DebuggerPane.prototype = {
// Bind shortcuts for accessing the breakpoint methods in the debugger.
let bkp = self.debuggerWindow.DebuggerController.Breakpoints;
self.addBreakpoint = bkp.addBreakpoint;
self.removeBreakpoint = bkp.removeBreakpoint;
self.getBreakpoint = bkp.getBreakpoint;
}, true);
- this._frame.setAttribute("src", "chrome://browser/content/debugger.xul");
+ this._frame.setAttribute("src", DBG_XUL);
},
/**
* Closes the debugger, removing child nodes and event listeners.
*/
close: function DP_close() {
if (!this._tab) {
return;
}
- this._tab._scriptDebugger = null;
+ delete this._tab._scriptDebugger;
this._tab = null;
- DebuggerUIPreferences.height = this._frame.height;
+ DebuggerPreferences.height = this._frame.height;
this._frame.removeEventListener("Debugger:Close", this.close, true);
this._frame.removeEventListener("unload", this.close, true);
this._nbox.removeChild(this._splitter);
this._nbox.removeChild(this._frame);
this._splitter = null;
this._frame = null;
@@ -181,19 +213,123 @@ DebuggerPane.prototype = {
if (debuggerWindow) {
return debuggerWindow.DebuggerController.Breakpoints.store;
}
return null;
}
};
/**
- * Various debugger UI preferences (currently just the pane height).
+ * Creates a process that will hold the remote debugger.
+ *
+ * @param function aOnClose
+ * Optional, a function called when the process exits.
+ * @param function aOnRun
+ * Optional, a function called when the process starts running.
+ * @param nsIDOMWindow aWindow
+ * The chrome window for which the remote debugger instance is created.
*/
-let DebuggerUIPreferences = {
+function DebuggerProcess(aWindow, aOnClose, aOnRun) {
+ this._win = aWindow;
+ this._closeCallback = aOnClose;
+ this._runCallback = aOnRun;
+ this._initServer();
+ this._initProfile();
+ this._create();
+}
+
+DebuggerProcess.prototype = {
+
+ /**
+ * Initializes the debugger server.
+ */
+ _initServer: function RDP__initServer() {
+ if (!DebuggerServer.initialized) {
+ DebuggerServer.init();
+ DebuggerServer.addBrowserActors();
+ }
+ DebuggerServer.closeListener();
+ DebuggerServer.openListener(DebuggerPreferences.remotePort, false);
+ },
+
+ /**
+ * Initializes a profile for the remote debugger process.
+ */
+ _initProfile: function RDP__initProfile() {
+ let profileService = Cc["@mozilla.org/toolkit/profile-service;1"]
+ .createInstance(Ci.nsIToolkitProfileService);
+
+ let dbgProfileName;
+ try {
+ dbgProfileName = profileService.selectedProfile.name + REMOTE_PROFILE_NAME;
+ } catch(e) {
+ dbgProfileName = REMOTE_PROFILE_NAME;
+ Cu.reportError(e);
+ }
+
+ this._dbgProfile = profileService.createProfile(null, null, dbgProfileName);
+ profileService.flush();
+ },
+
+ /**
+ * Creates and initializes the profile & process for the remote debugger.
+ */
+ _create: function RDP__create() {
+ this._win._remoteDebugger = this;
+
+ let file = FileUtils.getFile("CurProcD",
+ [Services.appinfo.OS == "WINNT" ? "firefox.exe"
+ : "firefox-bin"]);
+
+ let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
+ process.init(file);
+
+ let args = [
+ "-no-remote", "-P", this._dbgProfile.name,
+ "-chrome", DBG_XUL,
+ "-width", DebuggerPreferences.remoteWinWidth,
+ "-height", DebuggerPreferences.remoteWinHeight];
+
+ process.runwAsync(args, args.length, { observe: this.close.bind(this) });
+ this._dbgProcess = process;
+
+ if (typeof this._runCallback === "function") {
+ this._runCallback.call({}, this);
+ }
+ },
+
+ /**
+ * Closes the remote debugger, removing the profile and killing the process.
+ */
+ close: function RDP_close() {
+ if (!this._win) {
+ return;
+ }
+ delete this._win._remoteDebugger;
+ this._win = null;
+
+ if (this._dbgProcess.isRunning) {
+ this._dbgProcess.kill();
+ }
+ if (this._dbgProfile) {
+ this._dbgProfile.remove(false);
+ }
+ if (typeof this._closeCallback === "function") {
+ this._closeCallback.call({}, this);
+ }
+
+ this._dbgProcess = null;
+ this._dbgProfile = null;
+ }
+};
+
+/**
+ * Various debugger preferences.
+ */
+let DebuggerPreferences = {
/**
* Gets the preferred height of the debugger pane.
* @return number
*/
get height() {
if (this._height === undefined) {
this._height = Services.prefs.getIntPref("devtools.debugger.ui.height");
@@ -205,8 +341,40 @@ let DebuggerUIPreferences = {
* Sets the preferred height of the debugger pane.
* @param number value
*/
set height(value) {
Services.prefs.setIntPref("devtools.debugger.ui.height", value);
this._height = value;
}
};
+
+/**
+ * Gets the preferred width of the remote debugger window.
+ * @return number
+ */
+XPCOMUtils.defineLazyGetter(DebuggerPreferences, "remoteWinWidth", function() {
+ return Services.prefs.getIntPref("devtools.debugger.ui.remote-win.width");
+});
+
+/**
+ * Gets the preferred height of the remote debugger window.
+ * @return number
+ */
+XPCOMUtils.defineLazyGetter(DebuggerPreferences, "remoteWinHeight", function() {
+ return Services.prefs.getIntPref("devtools.debugger.ui.remote-win.height");
+});
+
+/**
+ * Gets the preferred default remote debugging host.
+ * @return string
+ */
+XPCOMUtils.defineLazyGetter(DebuggerPreferences, "remoteHost", function() {
+ return Services.prefs.getCharPref("devtools.debugger.remote-host");
+});
+
+/**
+ * Gets the preferred default remote debugging port.
+ * @return number
+ */
+XPCOMUtils.defineLazyGetter(DebuggerPreferences, "remotePort", function() {
+ return Services.prefs.getIntPref("devtools.debugger.remote-port");
+});
--- a/browser/devtools/debugger/debugger-controller.js
+++ b/browser/devtools/debugger/debugger-controller.js
@@ -109,29 +109,28 @@ let DebuggerController = {
DebuggerView.Properties.destroy();
DebuggerController.SourceScripts.disconnect();
DebuggerController.StackFrames.disconnect();
DebuggerController.ThreadState.disconnect();
this.dispatchEvent("Debugger:Unloaded");
this._disconnect();
+ this._isRemote && this._quitApp();
},
/**
* Initializes a debugger client and connects it to the debugger server,
* wiring event handlers as necessary.
*/
_connect: function DC__connect() {
- if (!DebuggerServer.initialized) {
- DebuggerServer.init();
- DebuggerServer.addBrowserActors();
- }
+ let transport =
+ this._isRemote ? debuggerSocketConnect(Prefs.remoteHost, Prefs.remotePort)
+ : DebuggerServer.connectPipe();
- let transport = DebuggerServer.connectPipe();
let client = this.client = new DebuggerClient(transport);
client.addListener("tabNavigated", this._onTabNavigated);
client.addListener("tabDetached", this._onTabDetached);
client.connect(function(aType, aTraits) {
client.listTabs(function(aResponse) {
let tab = aResponse.tabs[aResponse.selected];
@@ -216,16 +215,41 @@ let DebuggerController = {
});
});
}.bind(this));
}.bind(this));
},
/**
+ * Returns true if this is a remote debugger instance.
+ * @return boolean
+ */
+ get _isRemote() {
+ return !window.parent.content;
+ },
+
+ /**
+ * Attempts to quit the current process if allowed.
+ */
+ _quitApp: function DC__quitApp() {
+ let canceled = Cc["@mozilla.org/supports-PRBool;1"]
+ .createInstance(Ci.nsISupportsPRBool);
+
+ Services.obs.notifyObservers(canceled, "quit-application-requested", null);
+
+ // Somebody canceled our quit request.
+ if (canceled.data) {
+ return;
+ }
+
+ Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit);
+ },
+
+ /**
* Convenience method, dispatching a custom event.
*
* @param string aType
* The name of the event.
* @param string aDetail
* The data passed when initializing the event.
*/
dispatchEvent: function DC_dispatchEvent(aType, aDetail) {
@@ -743,51 +767,70 @@ SourceScripts.prototype = {
let q = aUrl.indexOf('?');
if (q > -1) {
return aUrl.slice(0, q);
}
return aUrl;
},
/**
+ * Gets the prePath for a script URL.
+ *
+ * @param string aUrl
+ * The script url.
+ * @return string
+ * The script prePath if the url is valid, null otherwise.
+ */
+ _getScriptPrePath: function SS__getScriptDomain(aUrl) {
+ try {
+ return Services.io.newURI(aUrl, null, null).prePath + "/";
+ } catch (e) {
+ }
+ return null;
+ },
+
+ /**
* Gets a unique, simplified label from a script url.
* ex: a). ici://some.address.com/random/subrandom/
* b). ni://another.address.org/random/subrandom/page.html
* c). san://interesting.address.gro/random/script.js
* d). si://interesting.address.moc/random/another/script.js
* =>
* a). subrandom/
* b). page.html
* c). script.js
* d). another/script.js
*
* @param string aUrl
* The script url.
* @param string aHref
* The content location href to be used. If unspecified, it will
- * defalult to debugged panrent window location.
+ * default to the script url prepath.
* @return string
* The simplified label.
*/
_getScriptLabel: function SS__getScriptLabel(aUrl, aHref) {
let url = this._trimUrlQuery(aUrl);
if (this._labelsCache[url]) {
return this._labelsCache[url];
}
- let href = aHref || window.parent.content.location.href;
+ let content = window.parent.content;
+ let domain = content ? content.location.href : this._getScriptPrePath(aUrl);
+
+ let href = aHref || domain;
let pathElements = url.split("/");
let label = pathElements.pop() || (pathElements.pop() + "/");
- // if the label as a leaf name is alreay present in the scripts list
+ // If the label as a leaf name is already present in the scripts list.
if (DebuggerView.Scripts.containsLabel(label)) {
label = url.replace(href.substring(0, href.lastIndexOf("/") + 1), "");
- // if the path/to/script is exactly the same, we're in different domains
+ // If the path/to/script is exactly the same, we're in different domains.
if (DebuggerView.Scripts.containsLabel(label)) {
label = url;
}
}
return this._labelsCache[url] = label;
},
@@ -871,17 +914,17 @@ SourceScripts.prototype = {
url: aScript.url
});
},
/**
* Handles notifications to load a source script from the cache or from a
* local file.
*
- * XXX: Tt may be better to use nsITraceableChannel to get to the sources
+ * XXX: It may be better to use nsITraceableChannel to get to the sources
* without relying on caching when we can (not for eval, etc.):
* http://www.softwareishard.com/blog/firebug/nsitraceablechannel-intercept-http-traffic/
*/
_onLoadSource: function SS__onLoadSource(aEvent) {
let url = aEvent.detail.url;
let options = aEvent.detail.options;
let self = this;
@@ -962,17 +1005,17 @@ SourceScripts.prototype = {
* Log an error message in the error console when a script fails to load.
*
* @param string aUrl
* The URL of the source script.
* @param string aStatus
* The failure status code.
*/
_logError: function SS__logError(aUrl, aStatus) {
- Components.utils.reportError(L10N.getFormatStr("loadingError", [aUrl, aStatus]));
+ Cu.reportError(L10N.getFormatStr("loadingError", [aUrl, aStatus]));
},
};
/**
* Handles all the breakpoints in the current debugger.
*/
function Breakpoints() {
this._onEditorBreakpointChange = this._onEditorBreakpointChange.bind(this);
@@ -1254,16 +1297,37 @@ let L10N = {
}
};
XPCOMUtils.defineLazyGetter(L10N, "stringBundle", function() {
return Services.strings.createBundle(DBG_STRINGS_URI);
});
/**
+ * Shortcuts for accessing various debugger preferences.
+ */
+let Prefs = {};
+
+/**
+ * Gets the preferred default remote debugging host.
+ * @return string
+ */
+XPCOMUtils.defineLazyGetter(Prefs, "remoteHost", function() {
+ return Services.prefs.getCharPref("devtools.debugger.remote-host");
+});
+
+/**
+ * Gets the preferred default remote debugging port.
+ * @return number
+ */
+XPCOMUtils.defineLazyGetter(Prefs, "remotePort", function() {
+ return Services.prefs.getIntPref("devtools.debugger.remote-port");
+});
+
+/**
* Preliminary setup for the DebuggerController object.
*/
DebuggerController.init();
DebuggerController.ThreadState = new ThreadState();
DebuggerController.StackFrames = new StackFrames();
DebuggerController.SourceScripts = new SourceScripts();
DebuggerController.Breakpoints = new Breakpoints();
--- a/browser/devtools/debugger/test/Makefile.in
+++ b/browser/devtools/debugger/test/Makefile.in
@@ -41,16 +41,17 @@ topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = browser/devtools/debugger/test
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_BROWSER_TEST_FILES = \
+ browser_dbg_createRemote.js \
browser_dbg_debuggerstatement.js \
browser_dbg_listtabs.js \
browser_dbg_tabactor-01.js \
browser_dbg_tabactor-02.js \
browser_dbg_contextactor-01.js \
browser_dbg_contextactor-02.js \
testactors.js \
browser_dbg_nav-01.js \
new file mode 100644
--- /dev/null
+++ b/browser/devtools/debugger/test/browser_dbg_createRemote.js
@@ -0,0 +1,86 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+var gProcess = null;
+var gTab = null;
+var gDebuggee = null;
+
+function test() {
+ remote_debug_tab_pane(STACK_URL, aOnClosing, function(aTab, aDebuggee, aProcess) {
+ gTab = aTab;
+ gDebuggee = aDebuggee;
+ gProcess = aProcess;
+
+ testSimpleCall();
+ });
+}
+
+function testSimpleCall() {
+ Services.tm.currentThread.dispatch({ run: function() {
+
+ ok(gProcess._dbgProcess,
+ "The remote debugger process wasn't created properly!");
+ ok(gProcess._dbgProcess.isRunning,
+ "The remote debugger process isn't running!");
+ is(typeof gProcess._dbgProcess.pid, "number",
+ "The remote debugger process doesn't have a pid (?!)");
+
+ info("process location: " + gProcess._dbgProcess.location);
+ info("process pid: " + gProcess._dbgProcess.pid);
+ info("process name: " + gProcess._dbgProcess.processName);
+ info("process sig: " + gProcess._dbgProcess.processSignature);
+
+ ok(gProcess._dbgProfile,
+ "The remote debugger profile wasn't created properly!");
+ ok(gProcess._dbgProfile.localDir,
+ "The remote debugger profile doesn't have a localDir...");
+ ok(gProcess._dbgProfile.rootDir,
+ "The remote debugger profile doesn't have a rootDir...");
+ ok(gProcess._dbgProfile.name,
+ "The remote debugger profile doesn't have a name...");
+
+ info("profile localDir: " + gProcess._dbgProfile.localDir);
+ info("profile rootDir: " + gProcess._dbgProfile.rootDir);
+ info("profile name: " + gProcess._dbgProfile.name);
+
+ let profileService = Cc["@mozilla.org/toolkit/profile-service;1"]
+ .createInstance(Ci.nsIToolkitProfileService);
+
+ let profile = profileService.getProfileByName(gProcess._dbgProfile.name);
+
+ ok(profile,
+ "The remote debugger profile wasn't *actually* created properly!");
+ is(profile.localDir.path, gProcess._dbgProfile.localDir.path,
+ "The remote debugger profile doesn't have the correct localDir!");
+ is(profile.rootDir.path, gProcess._dbgProfile.rootDir.path,
+ "The remote debugger profile doesn't have the correct rootDir!");
+
+ DebuggerUI.toggleRemoteDebugger();
+ }}, 0);
+}
+
+function aOnClosing() {
+ ok(!gProcess._dbgProcess.isRunning,
+ "The remote debugger process isn't closed as it should be!");
+ is(gProcess._dbgProcess.exitValue, (Services.appinfo.OS == "WINNT" ? 0 : 256),
+ "The remote debugger process didn't die cleanly.");
+
+ info("process exit value: " + gProcess._dbgProcess.exitValue);
+
+ info("profile localDir: " + gProcess._dbgProfile.localDir.path);
+ info("profile rootDir: " + gProcess._dbgProfile.rootDir.path);
+ info("profile name: " + gProcess._dbgProfile.name);
+
+ executeSoon(function() {
+ finish();
+ });
+}
+
+registerCleanupFunction(function() {
+ removeTab(gTab);
+ gProcess = null;
+ gTab = null;
+ gDebuggee = null;
+});
--- a/browser/devtools/debugger/test/head.js
+++ b/browser/devtools/debugger/test/head.js
@@ -87,22 +87,35 @@ function attach_thread_actor_for_url(aCl
});
});
}
function debug_tab_pane(aURL, aOnDebugging)
{
let tab = addTab(aURL, function() {
gBrowser.selectedTab = gTab;
-
let debuggee = tab.linkedBrowser.contentWindow.wrappedJSObject;
let pane = DebuggerUI.toggleDebugger();
pane._frame.addEventListener("Debugger:Connecting", function dbgConnected() {
pane._frame.removeEventListener("Debugger:Connecting", dbgConnected, true);
// Wait for the initial resume...
pane.debuggerWindow.gClient.addOneTimeListener("resumed", function() {
aOnDebugging(tab, debuggee, pane);
});
}, true);
});
}
+
+function remote_debug_tab_pane(aURL, aOnClosing, aOnDebugging)
+{
+ let tab = addTab(aURL, function() {
+ gBrowser.selectedTab = gTab;
+ let debuggee = tab.linkedBrowser.contentWindow.wrappedJSObject;
+
+ DebuggerUI.toggleRemoteDebugger(aOnClosing, function dbgRan(process) {
+
+ // Wait for the remote debugging process to start...
+ aOnDebugging(tab, debuggee, process);
+ });
+ });
+}
--- a/browser/locales/en-US/chrome/browser/devtools/debugger.dtd
+++ b/browser/locales/en-US/chrome/browser/devtools/debugger.dtd
@@ -6,16 +6,20 @@
- You want to make that choice consistent across the developer tools.
- A good criteria is the language in which you'd find the best
- documentation on web development on the web. -->
<!-- LOCALIZATION NOTE (debuggerMenu.label): This is the label for the
- application menu item that opens the debugger UI. -->
<!ENTITY debuggerMenu.label "Script Debugger">
+<!-- LOCALIZATION NOTE (remoteDebuggerMenu.label): This is the label for the
+ - application menu item that opens the remote debugger UI. -->
+<!ENTITY remoteDebuggerMenu.label "Remote Debugger">
+
<!-- LOCALIZATION NOTE (debuggerMenu.commandkey): This is the command key that
- launches the debugger UI. Do not translate this one! -->
<!ENTITY debuggerMenu.commandkey "S">
<!-- LOCALIZATION NOTE (debuggerUI.closeButton): This is the label for the
- button that closes the debugger UI. -->
<!ENTITY debuggerUI.closeButton "Close">