Fix
bug 881235 - Add actors and initial UI for remote debugging. r=mconley
new file mode 100644
--- /dev/null
+++ b/mail/components/debugger/Makefile.in
@@ -0,0 +1,12 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DEPTH = @DEPTH@
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/mail/components/debugger/content/dbg-mail-actors.js
@@ -0,0 +1,59 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+Components.utils.import("resource://gre/modules/iteratorUtils.jsm");
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+/**
+ * Create the root actor for Thunderbird's debugger implementation.
+ *
+ * @param aConnection The debugger connection to create the actor for.
+ * @return The mail actor for the connection.
+ */
+function createRootActor(aConnection) {
+ let parameters = {
+ tabList: new MailTabList(aConnection),
+ globalActorFactories: DebuggerServer.globalActorFactories,
+ onShutdown: sendShutdownEvent,
+ };
+
+ let mailActor = new RootActor(aConnection, parameters);
+ mailActor.applicationType = "mail";
+ return mailActor;
+}
+
+/**
+ * Send a debugger shutdown event to all mail windows.
+ */
+function sendShutdownEvent() {
+ for (let win in fixIterator(Services.wm.getEnumerator("mail:3pane"))) {
+ let evt = win.document.createEvent("Event");
+ evt.initEvent("Debugger:Shutdown", true, false);
+ win.document.documentElement.dispatchEvent(evt);
+ }
+}
+
+/**
+ * The live list of tabs for Thunderbird. The term tab is taken from Firefox
+ * tabs, where each browser tab shows up as a tab in the debugger. As in
+ * Thunderbird all tabs are chrome tabs, we will be iterating the content
+ * windows and presenting them as tabs instead.
+ *
+ * @param aConnection The connection to create the tab list for
+ */
+function MailTabList(aConnection) {
+ BrowserTabList.call(this, aConnection);
+}
+
+MailTabList.prototype = {
+ __proto__: BrowserTabList.prototype,
+
+ iterator: function() {
+ // For now we just need to make sure this function is a generator. Actually
+ // returning a list of tabs will be done in a future bug.
+ for (let dummy in []) {
+ yield dummy;
+ }
+ }
+};
new file mode 100644
--- /dev/null
+++ b/mail/components/debugger/content/dbg-messenger-overlay.js
@@ -0,0 +1,103 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+Components.utils.import("resource://gre/modules/devtools/dbg-server.jsm");
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "console", "resource://gre/modules/devtools/Console.jsm");
+
+/**
+ * Start the devtools debugger server and open a listener to contact it.
+ */
+function startDebugger() {
+ if (!DebuggerServer.initialized) {
+ // Initialize the debugger, if non-local connections are permitted then
+ // have the default prompt kick in.
+ DebuggerServer.init(() => {
+ return Services.prefs.getBoolPref("devtools.debugger.force-local") ||
+ DebuggerServer._defaultAllowConnection();
+ });
+
+ // Load the toolkit actor first
+ DebuggerServer.addActors("resource://gre/modules/devtools/server/actors/webbrowser.js");
+
+ // Add the mail root actor and the chrome debugger global actor
+ DebuggerServer.addActors("chrome://messenger/content/debugger/dbg-mail-actors.js");
+ DebuggerServer.addActors("resource://gre/modules/devtools/server/actors/script.js");
+ DebuggerServer.addGlobalActor(DebuggerServer.ChromeDebuggerActor, "chromeDebugger");
+ }
+
+ // Start the debugger listener unconditionally, it will check itself if it
+ // really needs to be started.
+ let port = Services.prefs.getIntPref('devtools.debugger.remote-port') || 6000;
+ try {
+ DebuggerServer.openListener(port);
+ } catch (e) {
+ console.exception("Unable to start debugger server", e);
+ }
+}
+
+/**
+ * Quit the devtools debugger server, forcing to disconnect all connections.
+ */
+function stopDebugger() {
+ try {
+ DebuggerServer.closeListener(true);
+ } catch (e) {
+ console.exception("Unable to stop debugger server", e);
+ }
+}
+
+/**
+ * Handler to call when the checked state of the menuitem is toggled. Sets the
+ * remote-enabled preference of the debugger and starts the debugger if needed.
+ */
+function toggleDebugger() {
+ let shouldEnable = document.getElementById("devtoolsDebugger").getAttribute("checked") == "true";
+ Services.prefs.setBoolPref("devtools.debugger.remote-enabled", shouldEnable);
+
+ if (shouldEnable) {
+ startDebugger();
+ } else {
+ stopDebugger();
+ }
+}
+
+/**
+ * Intialize the checked state, to be used when the view menu is opened.
+ */
+function initDebuggerToolsMenu() {
+ let debuggerEnabled = Services.prefs.getBoolPref("devtools.debugger.remote-enabled");
+ document.getElementById("devtoolsDebugger")
+ .setAttribute("checked", debuggerEnabled);
+}
+
+/**
+ * Intialize everything needed on load in the window for the debugger, i.e
+ * menuitem checked state listeners.
+ */
+function loadDebugger() {
+ window.removeEventListener("load", loadDebugger, false);
+ let viewPopup = document.getElementById("taskPopup");
+ viewPopup.addEventListener("popupshowing", initDebuggerToolsMenu, false);
+
+ // Call these functions once to start or stop the debugger on startup.
+ initDebuggerToolsMenu();
+ toggleDebugger();
+}
+
+/**
+ * Shutdown everything needed on load in the window for the debugger, i.e
+ * menuitem checked state listeners.
+ */
+function unloadDebugger() {
+ window.removeEventListener("unload", unloadDebugger, false);
+ let viewPopup = document.getElementById("taskPopup");
+ viewPopup.removeEventListener("popupshowing", initDebuggerToolsMenu, false);
+}
+
+// Load and unload the debugger when the window loads/unloads.
+window.addEventListener("load", loadDebugger, false);
+window.addEventListener("unload", unloadDebugger, false);
new file mode 100644
--- /dev/null
+++ b/mail/components/debugger/content/dbg-messenger-overlay.xul
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<!DOCTYPE overlay SYSTEM "chrome://messenger/locale/messenger.dtd">
+
+<overlay id="debugger-overlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script type="application/javascript" src="chrome://messenger/content/debugger/dbg-messenger-overlay.js"/>
+
+ <menupopup id="taskPopup">
+ <menuitem id="devtoolsDebugger"
+ type="checkbox"
+ insertafter="menu_inspector,javascriptConsole,javaScriptConsole"
+ label="&allowRemoteDebugging.label;"
+ accesskey="&allowRemoteDebugging.accesskey;"
+ oncommand="toggleDebugger()"/>
+ </menupopup>
+</overlay>
new file mode 100644
--- /dev/null
+++ b/mail/components/debugger/jar.mn
@@ -0,0 +1,9 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+messenger.jar:
+% overlay chrome://messenger/content/messenger.xul chrome://messenger/content/debugger/dbg-messenger-overlay.xul
+ content/messenger/debugger/dbg-messenger-overlay.xul (content/dbg-messenger-overlay.xul)
+ content/messenger/debugger/dbg-messenger-overlay.js (content/dbg-messenger-overlay.js)
+ content/messenger/debugger/dbg-mail-actors.js (content/dbg-mail-actors.js)
new file mode 100644
--- /dev/null
+++ b/mail/components/debugger/moz.build
@@ -0,0 +1,4 @@
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
--- a/mail/components/moz.build
+++ b/mail/components/moz.build
@@ -3,16 +3,17 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# Only Mac and Windows have search integration components, but we include at
# least one module from search/ on all platforms
DIRS += [
'compose',
'cloudfile',
+ 'debugger',
'preferences',
'addrbook',
'migration',
'activity',
'search',
'about-support',
'wintaskbar',
'newmailaccount',
--- a/mail/locales/en-US/chrome/messenger/messenger.dtd
+++ b/mail/locales/en-US/chrome/messenger/messenger.dtd
@@ -482,16 +482,18 @@
<!ENTITY errorConsoleCmd.commandkey "j">
<!ENTITY clearRecentHistory.label "Clear Recent History…">
<!ENTITY clearRecentHistory.accesskey "H">
<!ENTITY accountManagerCmd.label "Account Settings…">
<!ENTITY accountManagerCmd.accesskey "S">
<!-- LOCALIZATION NOTE (accountManagerCmdUnix.accesskey): belongs to accountManagerCmd.label,
which is placed under the Edit menu on Unix systems -->
<!ENTITY accountManagerCmdUnix.accesskey "A">
+<!ENTITY allowRemoteDebugging.label "Allow Remote Debugging">
+<!ENTITY allowRemoteDebugging.accesskey "g">
<!-- Mail Toolbar -->
<!ENTITY getMsgButton.label "Get Mail">
<!ENTITY newMsgButton.label "Write">
<!ENTITY replyButton.label "Reply">
<!ENTITY replyAllButton.label "Reply All">
<!ENTITY replyListButton.label "Reply to List">
<!ENTITY forwardButton.label "Forward">