Bug 764625 - Web Console and Debugger stay checked in Web Developer menu after closing them with the close X button. r=msucan,past
authorPaul Rouget <paul@mozilla.com>
Tue, 19 Jun 2012 18:56:31 +0200
changeset 101925 f50196512e836632127f510a516dfcb61a572bc5
parent 101924 7808db2872b64909f5b02bdf4c88ec057d73bd1b
child 101926 6475b0ff65c17b3952b0d6286a82d98ac4344cc4
push id1316
push userakeybl@mozilla.com
push dateMon, 27 Aug 2012 22:37:00 +0000
treeherdermozilla-beta@db4b09302ee2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmsucan, past
bugs764625
milestone16.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 764625 - Web Console and Debugger stay checked in Web Developer menu after closing them with the close X button. r=msucan,past
browser/devtools/debugger/DebuggerUI.jsm
browser/devtools/debugger/test/Makefile.in
browser/devtools/debugger/test/browser_dbg_menustatus.js
browser/devtools/shared/DeveloperToolbar.jsm
browser/devtools/webconsole/HUDService.jsm
browser/devtools/webconsole/test/Makefile.in
browser/devtools/webconsole/test/browser_webconsole_menustatus.js
--- a/browser/devtools/debugger/DebuggerUI.jsm
+++ b/browser/devtools/debugger/DebuggerUI.jsm
@@ -24,32 +24,50 @@ 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.
  */
 function DebuggerUI(aWindow) {
   this.chromeWindow = aWindow;
+  this.listenToTabs();
 }
 
 DebuggerUI.prototype = {
+  /**
+   * Update the status of tool's menuitems and buttons when
+   * the user switch tabs.
+   */
+  listenToTabs: function DUI_listenToTabs() {
+    let win = this.chromeWindow;
+    let tabs = win.gBrowser.tabContainer;
+
+    let bound_refreshCommand = this.refreshCommand.bind(this);
+    tabs.addEventListener("TabSelect", bound_refreshCommand, true);
+
+    win.addEventListener("unload", function onClose(aEvent) {
+      tabs.removeEventListener("TabSelect", bound_refreshCommand, true);
+      win.removeEventListener("unload", onClose, false);
+    }, false);
+  },
 
   /**
    * Called by the DebuggerPane to update the Debugger toggle switches with the
    * debugger state.
    */
   refreshCommand: function DUI_refreshCommand() {
-    let selectedTab = this.chromeWindow.getBrowser().selectedTab;
+    let scriptDebugger = this.getDebugger();
     let command = this.chromeWindow.document.getElementById("Tools:Debugger");
+    let selectedTab = this.chromeWindow.gBrowser.selectedTab;
 
-    if (this.getDebugger()) {
+    if (scriptDebugger && scriptDebugger.ownerTab === selectedTab) {
       command.setAttribute("checked", "true");
     } else {
-      command.removeAttribute("checked");
+      command.setAttribute("checked", "false");
     }
   },
 
   /**
    * Starts a debugger for the current tab, or stops it if already started.
    * @return DebuggerPane if the debugger is started, null if it's stopped.
    */
   toggleDebugger: function DUI_toggleDebugger() {
--- a/browser/devtools/debugger/test/Makefile.in
+++ b/browser/devtools/debugger/test/Makefile.in
@@ -51,16 +51,17 @@ include $(topsrcdir)/config/rules.mk
 	$(warning browser_dbg_select-line.js temporarily disabled due to oranges, see bug 726609) \
 	browser_dbg_clean-exit.js \
 	browser_dbg_bug723069_editor-breakpoints.js \
 	browser_dbg_bug731394_editor-contextmenu.js \
 	browser_dbg_displayName.js \
 	browser_dbg_iframes.js \
 	browser_dbg_pause-exceptions.js \
 	browser_dbg_multiple-windows.js \
+	browser_dbg_menustatus.js \
 	head.js \
 	$(NULL)
 
 _BROWSER_TEST_PAGES = \
 	browser_dbg_tab1.html \
 	browser_dbg_tab2.html \
 	browser_dbg_debuggerstatement.html \
 	browser_dbg_stack.html \
new file mode 100644
--- /dev/null
+++ b/browser/devtools/debugger/test/browser_dbg_menustatus.js
@@ -0,0 +1,48 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// We make sure the menuitems in the application menubar
+// are checked.
+
+function test() {
+  var tab1 = addTab("about:blank", function() {
+    var tab2 = addTab("about:blank", function() {
+      gBrowser.selectedTab = tab2;
+
+      let pane = DebuggerUI.toggleDebugger();
+      ok(pane, "toggleDebugger() should return a pane.");
+      let frame = pane._frame;
+
+      frame.addEventListener("Debugger:Loaded", function dbgLoaded() {
+        frame.removeEventListener("Debugger:Loaded", dbgLoaded, true);
+
+        let cmd = document.getElementById("Tools:Debugger");
+        is(cmd.getAttribute("checked"), "true", "<command Tools:Debugger> is checked.");
+
+        gBrowser.selectedTab = tab1;
+
+        is(cmd.getAttribute("checked"), "false", "<command Tools:Debugger> is unchecked after tab switch.");
+
+        gBrowser.selectedTab = tab2;
+
+        is(cmd.getAttribute("checked"), "true", "<command Tools:Debugger> is checked.");
+
+        let pane = DebuggerUI.toggleDebugger();
+
+        is(cmd.getAttribute("checked"), "false", "<command Tools:Debugger> is unchecked once closed.");
+      }, true);
+
+      frame.addEventListener("Debugger:Unloaded", function dbgUnloaded() {
+        frame.removeEventListener("Debugger:Unloaded", dbgUnloaded, true);
+          removeTab(tab1);
+          removeTab(tab2);
+
+          finish();
+      }, true);
+    });
+  });
+}
+
--- a/browser/devtools/shared/DeveloperToolbar.jsm
+++ b/browser/devtools/shared/DeveloperToolbar.jsm
@@ -338,19 +338,16 @@ DeveloperToolbar.prototype._notify = fun
 
 /**
  * Update various parts of the UI when the current tab changes
  * @param aEvent
  */
 DeveloperToolbar.prototype.handleEvent = function DT_handleEvent(aEvent)
 {
   if (aEvent.type == "TabSelect" || aEvent.type == "load") {
-    this._chromeWindow.HUDConsoleUI.refreshCommand();
-    this._chromeWindow.DebuggerUI.refreshCommand();
-
     if (this.visible) {
       let contentDocument = this._chromeWindow.getBrowser().contentDocument;
 
       this.display.reattach({
         contentDocument: contentDocument,
         chromeWindow: this._chromeWindow,
         environment: {
           chromeDocument: this._doc,
--- a/browser/devtools/webconsole/HUDService.jsm
+++ b/browser/devtools/webconsole/HUDService.jsm
@@ -246,16 +246,17 @@ function pruneConsoleOutputIfNecessary(a
 ///////////////////////////////////////////////////////////////////////////
 //// The HUD service
 
 function HUD_SERVICE()
 {
   // These methods access the "this" object, but they're registered as
   // event listeners. So we hammer in the "this" binding.
   this.onTabClose = this.onTabClose.bind(this);
+  this.onTabSelect = this.onTabSelect.bind(this);
   this.onWindowUnload = this.onWindowUnload.bind(this);
 
   // Remembers the last console height, in pixels.
   this.lastConsoleHeight = Services.prefs.getIntPref("devtools.hud.height");
 
   /**
    * Each HeadsUpDisplay has a set of filter preferences
    */
@@ -312,16 +313,17 @@ HUD_SERVICE.prototype =
 
     this.wakeup();
 
     let window = aTab.ownerDocument.defaultView;
     let gBrowser = window.gBrowser;
 
     // TODO: check that this works as intended
     gBrowser.tabContainer.addEventListener("TabClose", this.onTabClose, false);
+    gBrowser.tabContainer.addEventListener("TabSelect", this.onTabSelect, false);
     window.addEventListener("unload", this.onWindowUnload, false);
 
     this.registerDisplay(hudId);
 
     let hud = new HeadsUpDisplay(aTab);
     this.hudReferences[hudId] = hud;
 
     // register the controller to handle "select all" properly
@@ -611,16 +613,17 @@ HUD_SERVICE.prototype =
 
       let window = document.defaultView;
 
       window.removeEventListener("unload", this.onWindowUnload, false);
 
       let gBrowser = window.gBrowser;
       let tabContainer = gBrowser.tabContainer;
       tabContainer.removeEventListener("TabClose", this.onTabClose, false);
+      tabContainer.removeEventListener("TabSelect", this.onTabSelect, false);
 
       this.suspend();
     }
   },
 
   /**
    * "Wake up" the Web Console activity. This is called when the first Web
    * Console is open. This method initializes the various observers we have.
@@ -799,16 +802,27 @@ HUD_SERVICE.prototype =
    * @returns void
    */
   onTabClose: function HS_onTabClose(aEvent)
   {
     this.deactivateHUDForContext(aEvent.target, false);
   },
 
   /**
+   * onTabSelect event handler function
+   *
+   * @param aEvent
+   * @returns void
+   */
+  onTabSelect: function HS_onTabSelect(aEvent)
+  {
+    HeadsUpDisplayUICommands.refreshCommand();
+  },
+
+  /**
    * Called whenever a browser window closes. Cleans up any consoles still
    * around.
    *
    * @param nsIDOMEvent aEvent
    *        The dispatched event.
    * @returns void
    */
   onWindowUnload: function HS_onWindowUnload(aEvent)
@@ -816,16 +830,17 @@ HUD_SERVICE.prototype =
     let window = aEvent.target.defaultView;
 
     window.removeEventListener("unload", this.onWindowUnload, false);
 
     let gBrowser = window.gBrowser;
     let tabContainer = gBrowser.tabContainer;
 
     tabContainer.removeEventListener("TabClose", this.onTabClose, false);
+    tabContainer.removeEventListener("TabSelect", this.onTabSelect, false);
 
     let tab = tabContainer.firstChild;
     while (tab != null) {
       this.deactivateHUDForContext(tab, false);
       tab = tab.nextSibling;
     }
 
     if (window.webConsoleCommandController) {
@@ -4426,17 +4441,17 @@ HeadsUpDisplayUICommands = {
     if (!window) {
       return;
     }
 
     let command = window.document.getElementById("Tools:WebConsole");
     if (this.getOpenHUD() != null) {
       command.setAttribute("checked", true);
     } else {
-      command.removeAttribute("checked");
+      command.setAttribute("checked", false);
     }
   },
 
   toggleHUD: function UIC_toggleHUD() {
     var window = HUDService.currentContext();
     var gBrowser = window.gBrowser;
     var linkedBrowser = gBrowser.selectedTab.linkedBrowser;
     var tabId = gBrowser.getNotificationBox(linkedBrowser).getAttribute("id");
--- a/browser/devtools/webconsole/test/Makefile.in
+++ b/browser/devtools/webconsole/test/Makefile.in
@@ -104,16 +104,17 @@ include $(topsrcdir)/config/rules.mk
 	browser_webconsole_bug_659907_console_dir.js \
 	browser_webconsole_bug_664131_console_group.js \
 	browser_webconsole_bug_704295.js \
 	browser_webconsole_bug_658368_time_methods.js \
 	browser_webconsole_bug_622303_persistent_filters.js \
 	browser_webconsole_window_zombie.js \
 	browser_cached_messages.js \
 	browser_bug664688_sandbox_update_after_navigation.js \
+	browser_webconsole_menustatus.js \
 	head.js \
 	$(NULL)
 
 _BROWSER_TEST_PAGES = \
 	test-console.html \
 	test-network.html \
 	test-network-request.html \
 	test-mutation.html \
new file mode 100644
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_menustatus.js
@@ -0,0 +1,33 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+function test() {
+  var tab1 = gBrowser.addTab();
+  var tab2 = gBrowser.addTab();
+  gBrowser.selectedTab = tab2;
+
+  openConsole(tab2, function() {
+    let cmd = document.getElementById("Tools:WebConsole");
+    is(cmd.getAttribute("checked"), "true", "<command Tools:WebConsole> is checked.");
+
+    gBrowser.selectedTab = tab1;
+
+    is(cmd.getAttribute("checked"), "false", "<command Tools:WebConsole> is unchecked after tab switch.");
+
+    gBrowser.selectedTab = tab2;
+
+    is(cmd.getAttribute("checked"), "true", "<command Tools:WebConsole> is checked.");
+
+    closeConsole(tab2, function() {
+      is(cmd.getAttribute("checked"), "false", "<command Tools:WebConsole> is checked once closed.");
+
+      gBrowser.removeTab(tab1);
+      gBrowser.removeTab(tab2);
+
+      finish();
+    });
+  });
+}