Bug 692405 - Convert the debugger UI to a module; r=past
authorVictor Porof <vporof@mozilla.com>
Fri, 11 Nov 2011 12:03:26 +0200
changeset 79653 b55ebf123cc43cd3fbb6f28e0265087201f6e7f9
parent 79652 60125dac74def909870a62c9508933543b6fc291
child 79654 1ce57902a7182e9abbeb9c604fb19ac8e9bfbf55
push id77
push userpastithas@mozilla.com
push dateWed, 16 Nov 2011 12:24:32 +0000
reviewerspast
bugs692405
milestone10.0a1
Bug 692405 - Convert the debugger UI to a module; r=past
browser/app/profile/firefox.js
browser/base/content/browser-appmenu.inc
browser/base/content/browser-doctype.inc
browser/base/content/browser-menubar.inc
browser/base/content/browser-sets.inc
browser/base/content/browser.js
browser/devtools/debugger/DebuggerUI.jsm
browser/devtools/debugger/Makefile.in
browser/devtools/debugger/content/debugger-overlay.js
browser/devtools/debugger/content/debugger-overlay.xul
browser/devtools/debugger/content/debugger-prefs.js
browser/devtools/debugger/content/debugger-view.js
browser/devtools/debugger/content/debugger.css
browser/devtools/debugger/content/debugger.js
browser/devtools/debugger/content/debugger.xhtml
browser/devtools/debugger/debugger-view.js
browser/devtools/debugger/debugger.css
browser/devtools/debugger/debugger.js
browser/devtools/debugger/debugger.xhtml
browser/devtools/debugger/test/Makefile.in
browser/devtools/debugger/test/browser/Makefile.in
browser/devtools/debugger/test/browser/browser_dbg_contextactor-01.js
browser/devtools/debugger/test/browser/browser_dbg_contextactor-02.js
browser/devtools/debugger/test/browser/browser_dbg_debuggerstatement.html
browser/devtools/debugger/test/browser/browser_dbg_debuggerstatement.js
browser/devtools/debugger/test/browser/browser_dbg_frame-parameters.html
browser/devtools/debugger/test/browser/browser_dbg_listtabs.js
browser/devtools/debugger/test/browser/browser_dbg_location-changes.js
browser/devtools/debugger/test/browser/browser_dbg_nav-01.js
browser/devtools/debugger/test/browser/browser_dbg_openpane.js
browser/devtools/debugger/test/browser/browser_dbg_panesize.js
browser/devtools/debugger/test/browser/browser_dbg_propertyview-01.js
browser/devtools/debugger/test/browser/browser_dbg_propertyview-02.js
browser/devtools/debugger/test/browser/browser_dbg_propertyview-03.js
browser/devtools/debugger/test/browser/browser_dbg_propertyview-04.js
browser/devtools/debugger/test/browser/browser_dbg_propertyview-05.js
browser/devtools/debugger/test/browser/browser_dbg_propertyview-06.js
browser/devtools/debugger/test/browser/browser_dbg_propertyview-07.js
browser/devtools/debugger/test/browser/browser_dbg_propertyview-08.js
browser/devtools/debugger/test/browser/browser_dbg_script-switching.html
browser/devtools/debugger/test/browser/browser_dbg_script-switching.js
browser/devtools/debugger/test/browser/browser_dbg_stack-01.js
browser/devtools/debugger/test/browser/browser_dbg_stack-02.js
browser/devtools/debugger/test/browser/browser_dbg_stack-03.js
browser/devtools/debugger/test/browser/browser_dbg_stack-04.js
browser/devtools/debugger/test/browser/browser_dbg_stack.html
browser/devtools/debugger/test/browser/browser_dbg_tab1.html
browser/devtools/debugger/test/browser/browser_dbg_tab2.html
browser/devtools/debugger/test/browser/browser_dbg_tabactor-01.js
browser/devtools/debugger/test/browser/browser_dbg_tabactor-02.js
browser/devtools/debugger/test/browser/head.js
browser/devtools/debugger/test/browser/test-script-switching-01.js
browser/devtools/debugger/test/browser/test-script-switching-02.js
browser/devtools/debugger/test/browser/testactors.js
browser/devtools/debugger/test/browser_dbg_contextactor-01.js
browser/devtools/debugger/test/browser_dbg_contextactor-02.js
browser/devtools/debugger/test/browser_dbg_debuggerstatement.html
browser/devtools/debugger/test/browser_dbg_debuggerstatement.js
browser/devtools/debugger/test/browser_dbg_frame-parameters.html
browser/devtools/debugger/test/browser_dbg_listtabs.js
browser/devtools/debugger/test/browser_dbg_location-changes.js
browser/devtools/debugger/test/browser_dbg_nav-01.js
browser/devtools/debugger/test/browser_dbg_openpane.js
browser/devtools/debugger/test/browser_dbg_panesize.js
browser/devtools/debugger/test/browser_dbg_propertyview-01.js
browser/devtools/debugger/test/browser_dbg_propertyview-02.js
browser/devtools/debugger/test/browser_dbg_propertyview-03.js
browser/devtools/debugger/test/browser_dbg_propertyview-04.js
browser/devtools/debugger/test/browser_dbg_propertyview-05.js
browser/devtools/debugger/test/browser_dbg_propertyview-06.js
browser/devtools/debugger/test/browser_dbg_propertyview-07.js
browser/devtools/debugger/test/browser_dbg_propertyview-08.js
browser/devtools/debugger/test/browser_dbg_script-switching.html
browser/devtools/debugger/test/browser_dbg_script-switching.js
browser/devtools/debugger/test/browser_dbg_stack-01.js
browser/devtools/debugger/test/browser_dbg_stack-02.js
browser/devtools/debugger/test/browser_dbg_stack-03.js
browser/devtools/debugger/test/browser_dbg_stack-04.js
browser/devtools/debugger/test/browser_dbg_stack.html
browser/devtools/debugger/test/browser_dbg_tab1.html
browser/devtools/debugger/test/browser_dbg_tab2.html
browser/devtools/debugger/test/browser_dbg_tabactor-01.js
browser/devtools/debugger/test/browser_dbg_tabactor-02.js
browser/devtools/debugger/test/head.js
browser/devtools/debugger/test/test-script-switching-01.js
browser/devtools/debugger/test/test-script-switching-02.js
browser/devtools/debugger/test/testactors.js
browser/devtools/jar.mn
browser/locales/en-US/chrome/browser/devtools/debugger.dtd
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1000,16 +1000,19 @@ pref("services.sync.prefs.sync.xpinstall
 #endif
 
 // Disable the error console
 pref("devtools.errorconsole.enabled", false);
 
 // Enable the Inspector
 pref("devtools.inspector.enabled", true);
 
+// The default Debugger UI height
+pref("devtools.debugger.ui.height", 250);
+
 // Enable the style inspector
 pref("devtools.styleinspector.enabled", true);
 
 // Enable the rules view
 pref("devtools.ruleview.enabled", true);
 
 // Enable the Scratchpad tool.
 pref("devtools.scratchpad.enabled", true);
--- a/browser/base/content/browser-appmenu.inc
+++ b/browser/base/content/browser-appmenu.inc
@@ -182,16 +182,21 @@
                     oncommand="HUDConsoleUI.toggleHUD();"
                     key="key_webConsole"/>
           <menuitem id="appmenu_pageInspect"
                     hidden="true"
                     label="&inspectMenu.label;"
                     type="checkbox"
                     command="Tools:Inspect"
                     key="key_inspect"/>
+          <menuitem id="appmenu_debugger"
+                    hidden="false"
+                    label="&debuggerMenu.label;"
+                    key="key_debugger"
+                    command="Tools:Debugger"/>
           <menuitem id="appmenu_scratchpad"
                     hidden="true"
                     label="&scratchpad.label;"
                     key="key_scratchpad"
                     command="Tools:Scratchpad"/>
           <menuitem id="appmenu_pageSource"
                     label="&viewPageSourceCmd.label;"
                     command="View:PageSource"
--- a/browser/base/content/browser-doctype.inc
+++ b/browser/base/content/browser-doctype.inc
@@ -14,10 +14,12 @@
 <!ENTITY % placesDTD SYSTEM "chrome://browser/locale/places/places.dtd">
 %placesDTD;
 #ifdef MOZ_SAFE_BROWSING
 <!ENTITY % safebrowsingDTD SYSTEM "chrome://browser/locale/safebrowsing/phishing-afterload-warning-message.dtd">
 %safebrowsingDTD;
 #endif
 <!ENTITY % aboutHomeDTD SYSTEM "chrome://browser/locale/aboutHome.dtd">
 %aboutHomeDTD;
+<!ENTITY % debuggerDTD SYSTEM "chrome://browser/locale/devtools/debugger.dtd">
+%debuggerDTD;
 ]>
 
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -539,16 +539,21 @@
                             oncommand="HUDConsoleUI.toggleHUD();"/>
                   <menuitem id="menu_pageinspect"
                             type="checkbox"
                             hidden="true"
                             label="&inspectMenu.label;"
                             accesskey="&inspectMenu.accesskey;"
                             key="key_inspect"
                             command="Tools:Inspect"/>
+                  <menuitem id="menu_debugger"
+                            hidden="false"
+                            label="&debuggerMenu.label;"
+                            key="key_debugger"
+                            command="Tools:Debugger"/>
                   <menuitem id="menu_scratchpad"
                             hidden="true"
                             label="&scratchpad.label;"
                             accesskey="&scratchpad.accesskey;"
                             key="key_scratchpad"
                             command="Tools:Scratchpad"/>
                   <menuitem id="menu_pageSource"
                             accesskey="&pageSourceCmd.accesskey;"
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -120,16 +120,17 @@
     <command id="cmd_fullZoomEnlarge" oncommand="FullZoom.enlarge()"/>
     <command id="cmd_fullZoomReset"   oncommand="FullZoom.reset()"/>
     <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:Inspect" oncommand="InspectorUI.toggleInspectorUI();" disabled="true"/>
+    <command id="Tools:Debugger" oncommand="DebuggerUI.startDebugger();" disabled="false"/>
     <command id="Tools:Scratchpad" oncommand="Scratchpad.openScratchpad();" 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();"/>
     <command id="Browser:ToggleAddonBar" oncommand="toggleAddonBar();"/>
@@ -237,16 +238,23 @@
     <key id="key_openDownloads" key="&downloadsUnix.commandkey;" command="Tools:Downloads" modifiers="accel,shift"/>
 #else
     <key id="key_openDownloads" key="&downloads.commandkey;" command="Tools:Downloads" modifiers="accel"/>
 #endif
     <key id="key_openAddons" key="&addons.commandkey;" command="Tools:Addons" modifiers="accel,shift"/>
     <key id="key_errorConsole" key="&errorConsoleCmd.commandkey;" oncommand="toJavaScriptConsole();" modifiers="accel,shift" disabled="true"/>
     <key id="key_webConsole" key="&webConsoleCmd.commandkey;" oncommand="HUDConsoleUI.toggleHUD();" modifiers="accel,shift"/>
     <key id="key_inspect" key="&inspectMenu.commandkey;" command="Tools:Inspect" modifiers="accel,shift"/>
+    <key id="key_debugger" key="&debuggerMenu.commandkey;"
+#ifdef XP_MACOSX
+        modifiers="accel,alt"
+#else
+        modifiers="accel,shift"
+#endif
+        command="Tools:Debugger"/>
     <key id="key_scratchpad" keycode="&scratchpad.keycode;" modifiers="shift"
          keytext="&scratchpad.keytext;" command="Tools:Scratchpad"/>
     <key id="openFileKb" key="&openFileCmd.commandkey;" command="Browser:OpenFile"  modifiers="accel"/>
     <key id="key_savePage" key="&savePageCmd.commandkey;" command="Browser:SavePage" modifiers="accel"/>
     <key id="printKb" key="&printCmd.commandkey;" command="cmd_print"  modifiers="accel"/>
     <key id="key_close" key="&closeCmd.key;" command="cmd_close" modifiers="accel"/>
     <key id="key_closeWindow" key="&closeCmd.key;" command="cmd_closeWindow" modifiers="accel,shift"/>
     <key id="key_undo"
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -174,16 +174,22 @@ XPCOMUtils.defineLazyGetter(this, "Popup
 });
 
 XPCOMUtils.defineLazyGetter(this, "InspectorUI", function() {
   let tmp = {};
   Cu.import("resource:///modules/inspector.jsm", tmp);
   return new tmp.InspectorUI(window);
 });
 
+XPCOMUtils.defineLazyGetter(this, "DebuggerUI", function() {
+  let tmp = {};
+  Cu.import("resource:///modules/devtools/DebuggerUI.jsm", tmp);
+  return new tmp.DebuggerUI(window);
+});
+
 let gInitialPages = [
   "about:blank",
   "about:privatebrowsing",
   "about:sessionrestore"
 ];
 
 #include browser-fullZoom.js
 #include browser-places.js
new file mode 100644
--- /dev/null
+++ b/browser/devtools/debugger/DebuggerUI.jsm
@@ -0,0 +1,355 @@
+/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ *   Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Dave Camp <dcamp@mozilla.com>
+ *   Panos Astithas <past@mozilla.com>
+ *   Victor Porof <vporof@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+"use strict";
+
+/*global Components, NetUtil, Services, XPCOMUtils */
+/*global DebuggerServer, DebuggerClient, SourceEditor */
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/NetUtil.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource:///modules/XPCOMUtils.jsm");
+Cu.import("resource:///modules/dbg-server.jsm");
+Cu.import("resource:///modules/dbg-client.jsm");
+Cu.import("resource:///modules/source-editor.jsm");
+
+let EXPORTED_SYMBOLS = ["DebuggerUI"];
+
+function DebuggerPane(aTab) {
+  this._tab = aTab;
+  this.close = this.close.bind(this);
+  this.debugTab = this.debugTab.bind(this);
+}
+
+DebuggerPane.prototype = {
+  create: function DP_create(gBrowser) {
+    this._tab._scriptDebugger = this;
+
+    this._nbox = gBrowser.getNotificationBox(this._tab.linkedBrowser);
+    this._splitter = gBrowser.parentNode.ownerDocument.createElement("splitter");
+    this._splitter.setAttribute("class", "hud-splitter");
+    this.frame = gBrowser.parentNode.ownerDocument.createElement("iframe");
+    this.frame.height = DebuggerUIPreferences.height;
+
+    this._nbox.appendChild(this._splitter);
+    this._nbox.appendChild(this.frame);
+
+    let self = this;
+
+    this.frame.addEventListener("DOMContentLoaded", function initPane(aEvent) {
+      self.frame.removeEventListener("DOMContentLoaded", initPane, true);
+      if (aEvent.target != self.frame.contentDocument) {
+        return;
+      }
+      // Initialize the source editor.
+      self.frame.contentWindow.editor = self.editor = new SourceEditor();
+
+      let config = {
+        mode: SourceEditor.MODES.JAVASCRIPT,
+        showLineNumbers: true,
+        readOnly: true
+      };
+
+      let editorPlaceholder = self.frame.contentDocument.getElementById("editor");
+      self.editor.init(editorPlaceholder, config);
+      // Connect to the debugger server.
+      self.connect();
+    }, true);
+    this.frame.addEventListener("DebuggerClose", this.close, true);
+
+    this.frame.setAttribute("src", "chrome://browser/content/debugger.xhtml");
+  },
+
+  close: function DP_close() {
+    if (this._tab) {
+      this._tab._scriptDebugger = null;
+      this._tab = null;
+    }
+    if (this.frame) {
+      DebuggerUIPreferences.height = this.frame.height;
+
+      this.frame.removeEventListener("unload", this.close);
+      this.frame.removeEventListener("DebuggerClose", this.close);
+      try {
+        this._nbox.removeChild(this.frame);
+      } catch (e) {
+        // If the child has already been removed, do nothing.
+      }
+      this.frame = null;
+    }
+    if (this._nbox) {
+      this._nbox.removeChild(this._splitter);
+      this._nbox = null;
+    }
+
+    this._splitter = null;
+
+    if (this._client) {
+      this._client.removeListener("newScript", this.onNewScript);
+      this._client.removeListener("tabDetached", this.close);
+      this._client.removeListener("tabNavigated", this.debugTab);
+      this._client.close();
+      this._client = null;
+    }
+  },
+
+  connect: function DP_connect() {
+    this.frame.addEventListener("unload", this.close, true);
+
+    let transport = DebuggerServer.connectPipe();
+    this._client = new DebuggerClient(transport);
+    // Store the new script handler locally, so when it's time to remove it we
+    // don't need to go through the iframe, since it might be cleared.
+    this.onNewScript = this.debuggerWindow.SourceScripts.onNewScript;
+    let self = this;
+    this._client.addListener("tabNavigated", this.debugTab);
+    this._client.addListener("tabDetached", this.close);
+    this._client.addListener("newScript", this.onNewScript);
+    this._client.ready(function(aType, aTraits) {
+      self._client.listTabs(function(aResponse) {
+        let tab = aResponse.tabs[aResponse.selected];
+        self.debuggerWindow.startDebuggingTab(self._client, tab);
+        if (self.onConnected) {
+          self.onConnected(self);
+        }
+      });
+    });
+  },
+
+  /**
+   * Starts debugging the current tab. This function is called on each location
+   * change.
+   */
+  debugTab: function DP_debugTab(aNotification, aPacket) {
+    let self = this;
+    this._client.activeThread.detach(function() {
+      self._client.activeTab.detach(function() {
+        self._client.listTabs(function(aResponse) {
+          let tab = aResponse.tabs[aResponse.selected];
+          self.debuggerWindow.startDebuggingTab(self._client, tab);
+          if (self.onConnected) {
+            self.onConnected(self);
+          }
+        });
+      });
+    });
+  },
+
+  get debuggerWindow() {
+    return this.frame.contentWindow;
+  },
+
+  get debuggerClient() {
+    return this._client;
+  },
+
+  get activeThread() {
+    try {
+      return this.debuggerWindow.ThreadState.activeThread;
+    } catch(ex) {
+      return undefined;
+    }
+  }
+};
+
+function DebuggerUI(aWindow) {
+  this.aWindow = aWindow;
+
+  aWindow.addEventListener("Debugger:LoadSource", this.onLoadSource.bind(this));
+}
+
+DebuggerUI.prototype = {
+
+  /**
+   * Starts the debugger or stops it, if it is already started.
+   */
+  startDebugger: function DebuggerUI_startDebugger() {
+    if (!DebuggerServer.initialized) {
+      DebuggerServer.init();
+      DebuggerServer.addBrowserActors();
+    }
+
+    let gBrowser = this.aWindow.gBrowser;
+    let tab = gBrowser.selectedTab;
+
+    if (tab._scriptDebugger) {
+      // If the debugger is already open, just close it.
+      tab._scriptDebugger.close();
+      return tab._scriptDebugger;
+    }
+
+    let pane = new DebuggerPane(tab);
+    pane.create(gBrowser);
+    return pane;
+  },
+
+  getDebugger: function DebuggerUI_getDebugger(aTab) {
+    return aTab._scriptDebugger;
+  },
+
+  getPreferences: function DebuggerUI_getPreferences() {
+    return DebuggerUIPreferences;
+  },
+
+  /**
+   * Handles notifications to load a source script from the cache or from a
+   * local file.
+   * 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 DebuggerUI_onLoadSource(aEvent) {
+    let gBrowser = this.aWindow.gBrowser;
+    let gAlert = this.aWindow.alert;
+
+    let url = aEvent.detail;
+    let scheme = Services.io.extractScheme(url);
+    switch (scheme) {
+      case "file":
+      case "chrome":
+      case "resource":
+        NetUtil.asyncFetch(url, function onAsyncFetch(stream, status) {
+          if (!Components.isSuccessCode(status)) {
+            let view = this.getDebugger(gBrowser.selectedTab).DebuggerView;
+            gAlert(view.getFormatStr("loadingError", [ url, status ]));
+            return;
+          }
+          let source = NetUtil.readInputStreamToString(stream, stream.available());
+          stream.close();
+          this.onSourceLoaded(url, source);
+        }.bind(this));
+        break;
+
+      default:
+        let cacheService = Cc["@mozilla.org/network/cache-service;1"].getService(Ci.nsICacheService);
+        let session = cacheService.createSession("HTTP", Ci.nsICache.STORE_ANYWHERE, true);
+        session.doomEntriesIfExpired = false;
+        session.asyncOpenCacheEntry(url, Ci.nsICache.ACCESS_READ, {
+          onCacheEntryAvailable: function onCacheEntryAvailable(entry, mode, status) {
+            if (!Components.isSuccessCode(status)) {
+              let view = this.getDebugger(gBrowser.selectedTab).DebuggerView;
+              gAlert(view.getFormatStr("loadingError", [ url, status ]));
+              return;
+            }
+
+            let source = "";
+            let stream = entry.openInputStream(0);
+            let head = entry.getMetaDataElement("response-head");
+
+            if (/Content-Encoding:\s*gzip/i.test(head)) {
+              let converter = Cc["@mozilla.org/streamconv;1?from=gzip&to=uncompressed"].createInstance(Ci.nsIStreamConverter);
+              converter.asyncConvertData("gzip", "uncompressed", {
+                onDataAvailable: function onDataAvailable(aRequest, aContext, uncompressedStream, aOffset, aCount) {
+                  source += NetUtil.readInputStreamToString(uncompressedStream, aCount);
+                }
+              }, this);
+              while (stream.available()) {
+                converter.onDataAvailable(null, this, stream, 0, stream.available());
+              }
+            } else {
+              // uncompressed data
+              while (stream.available()) {
+                source += NetUtil.readInputStreamToString(stream, stream.available());
+              }
+            }
+
+            stream.close();
+            entry.close();
+            this.onSourceLoaded(url, source);
+          }.bind(this)
+        });
+        break;
+    }
+  },
+
+  /**
+   * Called when source has been loaded.
+   *
+   * @param string aSourceUrl
+   *        The URL of the source script.
+   * @param string aSourceText
+   *        The text of the source script.
+   */
+  onSourceLoaded: function DebuggerUI_onSourceLoaded(aSourceUrl, aSourceText) {
+    let dbg = this.getDebugger(this.aWindow.gBrowser.selectedTab);
+    if (aSourceUrl.slice(-3) == ".js") {
+      dbg.editor.setMode(SourceEditor.MODES.JAVASCRIPT);
+    } else {
+      dbg.editor.setMode(SourceEditor.MODES.HTML);
+    }
+    dbg.editor.setText(aSourceText);
+    let doc = dbg.frame.contentDocument;
+    let elt = doc.getElementById(aSourceUrl);
+    let script = JSON.parse(elt.getAttribute("sourceScript"));
+    script.loaded = true;
+    script.text = aSourceText;
+    elt.setAttribute("sourceScript", JSON.stringify(script));
+  }
+};
+
+/**
+ * Various debugger UI preferences (currently just the pane height).
+ */
+let DebuggerUIPreferences = {
+
+  /**
+   * Gets the preferred height of the debugger pane.
+   *
+   * @return number
+   *         The preferred height.
+   */
+  get height() {
+    return Services.prefs.getIntPref("devtools.debugger.ui.height");
+  },
+
+  /**
+   * Sets the preferred height of the debugger pane.
+   *
+   * @param number value
+   *        The new height.
+   */
+  set height(value) {
+    Services.prefs.setIntPref("devtools.debugger.ui.height", value);
+    this._height = value;
+  }
+};
--- a/browser/devtools/debugger/Makefile.in
+++ b/browser/devtools/debugger/Makefile.in
@@ -15,16 +15,17 @@
 #
 # The Initial Developer of the Original Code is
 #   Mozilla Foundation
 # Portions created by the Initial Developer are Copyright (C) 2011
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
 #  Dave Camp <dcamp@mozilla.com>
+#  Victor Porof <vporof@mozilla.com>
 #
 # Alternatively, the contents of this file may be used under the terms of
 # either the GNU General Public License Version 2 or later (the "GPL"), or
 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 # in which case the provisions of the GPL or the LGPL are applicable instead
 # of those above. If you wish to allow use of your version of this file only
 # under the terms of either the GPL or the LGPL, and not to allow others to
 # use your version of this file under the terms of the MPL, indicate your
@@ -44,8 +45,11 @@ include $(DEPTH)/config/autoconf.mk
 
 ifdef ENABLE_TESTS
 ifneq (mobile,$(MOZ_BUILD_APP))
 	DIRS += test
 endif
 endif
 
 include $(topsrcdir)/config/rules.mk
+
+libs::
+	$(NSINSTALL) $(srcdir)/*.jsm $(FINAL_TARGET)/modules/devtools
deleted file mode 100644
--- a/browser/devtools/debugger/content/debugger-overlay.js
+++ /dev/null
@@ -1,308 +0,0 @@
-/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- *   Mozilla Foundation
- * Portions created by the Initial Developer are Copyright (C) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Dave Camp <dcamp@mozilla.com>
- *   Panos Astithas <past@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-"use strict";
-Cu.import("resource:///modules/XPCOMUtils.jsm");
-Cu.import("resource:///modules/dbg-server.jsm");
-Cu.import("resource:///modules/dbg-client.jsm");
-Cu.import("resource://gre/modules/NetUtil.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource:///modules/source-editor.jsm");
-
-function DebuggerPane(aTab) {
-  this._tab = aTab;
-  this.close = this.close.bind(this);
-  this.debugTab = this.debugTab.bind(this);
-}
-
-DebuggerPane.prototype = {
-  create: function DP_create() {
-    this._tab._scriptDebugger = this;
-
-    this._nbox = gBrowser.getNotificationBox(this._tab.linkedBrowser);
-    this._splitter = document.createElement("splitter");
-    this._splitter.setAttribute("class", "hud-splitter");
-    this.frame = document.createElement("iframe");
-    this.frame.height = DebuggerPreferences.UI.height;
-
-    this._nbox.appendChild(this._splitter);
-    this._nbox.appendChild(this.frame);
-
-    let self = this;
-
-    this.frame.addEventListener("DOMContentLoaded", function initPane(aEvent) {
-      self.frame.removeEventListener("DOMContentLoaded", initPane, true);
-      if (aEvent.target != self.frame.contentDocument) {
-        return;
-      }
-      // Initialize the source editor.
-      self.frame.contentWindow.editor = self.editor = new SourceEditor();
-
-      let config = {
-        mode: SourceEditor.MODES.JAVASCRIPT,
-        showLineNumbers: true,
-        readOnly: true
-      };
-
-      let editorPlaceholder = self.frame.contentDocument.getElementById("editor");
-      self.editor.init(editorPlaceholder, config);
-      // Connect to the debugger server.
-      self.connect();
-    }, true);
-    this.frame.addEventListener("DebuggerClose", this.close, true);
-
-    this.frame.setAttribute("src", "chrome://browser/content/debugger.xhtml");
-  },
-
-  close: function DP_close() {
-    if (this._tab) {
-      this._tab._scriptDebugger = null;
-      this._tab = null;
-    }
-    if (this.frame) {
-      DebuggerPreferences.UI.height = this.frame.height;
-
-      this.frame.removeEventListener("unload", this.close);
-      this.frame.removeEventListener("DebuggerClose", this.close);
-      try {
-        this._nbox.removeChild(this.frame);
-      } catch (e) {
-        // If the child has already been removed, do nothing.
-      }
-      this.frame = null;
-    }
-    if (this._nbox) {
-      this._nbox.removeChild(this._splitter);
-      this._nbox = null;
-    }
-
-    this._splitter = null;
-
-    if (this._client) {
-      this._client.removeListener("newScript", this.onNewScript);
-      this._client.removeListener("tabDetached", this.close);
-      this._client.removeListener("tabNavigated", this.debugTab);
-      this._client.close();
-      this._client = null;
-    }
-  },
-
-  connect: function DP_connect() {
-    this.frame.addEventListener("unload", this.close, true);
-
-    let transport = DebuggerServer.connectPipe();
-    this._client = new DebuggerClient(transport);
-    // Store the new script handler locally, so when it's time to remove it we
-    // don't need to go through the iframe, since it might be cleared.
-    this.onNewScript = this.debuggerWindow.SourceScripts.onNewScript;
-    let self = this;
-    this._client.addListener("tabNavigated", this.debugTab);
-    this._client.addListener("tabDetached", this.close);
-    this._client.addListener("newScript", this.onNewScript);
-    this._client.ready(function(aType, aTraits) {
-      self._client.listTabs(function(aResponse) {
-        let tab = aResponse.tabs[aResponse.selected];
-        self.debuggerWindow.startDebuggingTab(self._client, tab);
-        if (self.onConnected) {
-          self.onConnected(self);
-        }
-      });
-    });
-  },
-
-  /**
-   * Starts debugging the current tab. This function is called on each location
-   * change.
-   */
-  debugTab: function DP_debugTab(aNotification, aPacket) {
-    let self = this;
-    this._client.activeThread.detach(function() {
-      self._client.activeTab.detach(function() {
-        self._client.listTabs(function(aResponse) {
-          let tab = aResponse.tabs[aResponse.selected];
-          self.debuggerWindow.startDebuggingTab(self._client, tab);
-          if (self.onConnected) {
-            self.onConnected(self);
-          }
-        });
-      });
-    });
-  },
-
-  get debuggerWindow() {
-    return this.frame.contentWindow;
-  },
-
-  get debuggerClient() {
-    return this._client;
-  },
-
-  get activeThread() {
-    try {
-      return this.debuggerWindow.ThreadState.activeThread;
-    } catch(ex) {
-      dump(ex);
-      return undefined;
-    }
-  }
-};
-
-var DebuggerUI = {
-  /**
-   * Starts the debugger or stops it, if it is already started.
-   */
-  startDebugger: function DebuggerUI_startDebugger() {
-    if (!DebuggerServer.initialized) {
-      DebuggerServer.init();
-      DebuggerServer.addBrowserActors();
-    }
-
-    let tab = gBrowser.selectedTab;
-
-    if (tab._scriptDebugger) {
-      // If the debugger is already open, just close it.
-      tab._scriptDebugger.close();
-      return tab._scriptDebugger;
-    }
-
-    let pane = new DebuggerPane(tab);
-    pane.create();
-    return pane;
-  },
-
-  getDebugger: function DebuggerUI_getDebugger(aTab) {
-    return aTab._scriptDebugger;
-  },
-
-  /**
-   * Handles notifications to load a source script from the cache or from a
-   * local file.
-   * 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 DebuggerUI_onLoadSource(aEvent) {
-    let url = aEvent.detail;
-    let scheme = Services.io.extractScheme(url);
-    switch (scheme) {
-      case "file":
-      case "chrome":
-      case "resource":
-        NetUtil.asyncFetch(url, function onAsyncFetch(stream, status) {
-          if (!Components.isSuccessCode(status)) {
-            let view = this.getDebugger(gBrowser.selectedTab).DebuggerView;
-            alert(view.getFormatStr("loadingError", [ url, status ]));
-            return;
-          }
-          let source = NetUtil.readInputStreamToString(stream, stream.available());
-          stream.close();
-          DebuggerUI.onSourceLoaded(url, source);
-        }.bind(this));
-        break;
-
-      default:
-        let cacheService = Cc["@mozilla.org/network/cache-service;1"].getService(Ci.nsICacheService);
-        let session = cacheService.createSession("HTTP", Ci.nsICache.STORE_ANYWHERE, true);
-        session.doomEntriesIfExpired = false;
-        session.asyncOpenCacheEntry(url, Ci.nsICache.ACCESS_READ, {
-          onCacheEntryAvailable: function onCacheEntryAvailable(entry, mode, status) {
-            if (!Components.isSuccessCode(status)) {
-              let view = this.getDebugger(gBrowser.selectedTab).DebuggerView;
-              alert(view.getFormatStr("loadingError", [ url, status ]));
-              return;
-            }
-
-            let source = "";
-            let stream = entry.openInputStream(0);
-            let head = entry.getMetaDataElement("response-head");
-
-            if (/Content-Encoding:\s*gzip/i.test(head)) {
-              let converter = Cc["@mozilla.org/streamconv;1?from=gzip&to=uncompressed"].createInstance(Ci.nsIStreamConverter);
-              converter.asyncConvertData("gzip", "uncompressed", {
-                onDataAvailable: function onDataAvailable(aRequest, aContext, uncompressedStream, aOffset, aCount) {
-                  source += NetUtil.readInputStreamToString(uncompressedStream, aCount);
-                }
-              }, this);
-              while (stream.available()) {
-                converter.onDataAvailable(null, this, stream, 0, stream.available());
-              }
-            } else {
-              // uncompressed data
-              while (stream.available()) {
-                source += NetUtil.readInputStreamToString(stream, stream.available());
-              }
-            }
-
-            stream.close();
-            entry.close();
-            DebuggerUI.onSourceLoaded(url, source);
-          }.bind(this)
-        });
-        break;
-    }
-  },
-
-  /**
-   * Called when source has been loaded.
-   *
-   * @param string aSourceUrl
-   *        The URL of the source script.
-   * @param string aSourceText
-   *        The text of the source script.
-   */
-  onSourceLoaded: function DebuggerUI_onSourceLoaded(aSourceUrl, aSourceText) {
-    let dbg = this.getDebugger(gBrowser.selectedTab);
-    if (aSourceUrl.slice(-3) == ".js") {
-      dbg.editor.setMode(SourceEditor.MODES.JAVASCRIPT);
-    } else {
-      dbg.editor.setMode(SourceEditor.MODES.HTML);
-    }
-    dbg.editor.setText(aSourceText);
-    let doc = dbg.frame.contentDocument;
-    let elt = doc.getElementById(aSourceUrl);
-    let script = JSON.parse(elt.getAttribute("sourceScript"));
-    script.loaded = true;
-    script.text = aSourceText;
-    elt.setAttribute("sourceScript", JSON.stringify(script));
-  }
-};
-
-window.addEventListener("Debugger:LoadSource", DebuggerUI.onLoadSource);
-
deleted file mode 100644
--- a/browser/devtools/debugger/content/debugger-overlay.xul
+++ /dev/null
@@ -1,63 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is mozilla.org code.
-#
-# The Initial Developer of the Original Code is
-#   Mozilla Foundation
-# Portions created by the Initial Developer are Copyright (C) 2011
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#  Dave Camp <dcamp@mozilla.com>
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either the GNU General Public License Version 2 or later (the "GPL"), or
-# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-<!DOCTYPE overlay [
-<!ENTITY % debuggerDTD SYSTEM "chrome://browser/locale/devtools/debugger.dtd" >
- %debuggerDTD;
-]>
-<overlay id="debugger-overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-  <keyset>
-    <key id="key_startScriptDebugger" modifiers="alt meta" key="&menuKey;" oncommand="DebuggerUI.startDebugger();"/>
-  </keyset>
-  <script type="application/javascript;version=1.8" src="debugger-overlay.js"/>
-  <script type="application/javascript;version=1.8" src="debugger-prefs.js"/>
-
-  <menupopup id="appmenu_webDeveloper_popup">
-    <menuitem id="appmenu_startScriptDebugger" label="&applicationMenuLabel;"
-              insertbefore="appmenu_devToolsEndSeparator"
-              key="key_startScriptDebugger"
-              oncommand="DebuggerUI.startDebugger();"/>
-  </menupopup>
-  <menupopup id="menuWebDeveloperPopup">
-    <menuitem id="startDscriptDebugger" label="&contextMenuLabel;"
-              insertbefore="devToolsEndSeparator"
-              key="key_startScriptDebugger"
-              oncommand="DebuggerUI.startDebugger();"/>
-  </menupopup>
-
-
-</overlay>
deleted file mode 100644
--- a/browser/devtools/debugger/content/debugger-prefs.js
+++ /dev/null
@@ -1,204 +0,0 @@
-/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- *   Mozilla Foundation
- * Portions created by the Initial Developer are Copyright (C) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Victor Porof <vporof@mozilla.com> (original author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the LGPL or the GPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- ***** END LICENSE BLOCK *****/
-"use strict";
-
-/*global Cc, Ci, Cu, dump */
-
-const DEBUGGER_UI_DEFAULT_HEIGHT = 250;
-
-/**
- * Object handling all the debugger preferences.
- */
-let DebuggerPreferences = {};
-
-/**
- * Various debugger UI preferences.
- */
-DebuggerPreferences.UI = {
-
-  /**
-   * Gets the preferred height of the debugger pane.
-   *
-   * @return {Number} the preferred height
-   */
-  get height() {
-    let prefs = DebuggerPreferences.Branch;
-
-    // if the preference isn't cached already, get it from the pref branch
-    if ("undefined" === typeof this._height) {
-
-      // if the preference doesn't exist yet, create it now
-      prefs.create("ui.height", "integer", DEBUGGER_UI_DEFAULT_HEIGHT);
-
-      // get the actual preference
-      this._height = prefs.get("ui.height", "integer");
-    }
-
-    return this._height;
-  },
-
-  /**
-   * Sets the preferred height of the debugger pane.
-   *
-   * @param {Number} value
-   *                 the new height
-   */
-  set height(value) {
-    DebuggerPreferences.Branch.set("ui.height", "integer", value);
-    this._height = value;
-  }
-};
-
-/**
- * Object handling the preferences branch.
- */
-DebuggerPreferences.Branch = {
-
-  /**
-   * Gets a custom debugger preference.
-   * If the preference does not exist, undefined is returned. If it does exist,
-   * but the type is not correctly specified, null is returned.
-   *
-   * @param {String} aPref
-   *                 the preference name
-   * @param {String} aType
-   *                 either "boolean", "string" or "integer"
-   *
-   * @return {Boolean | String | Number} the requested preference
-   */
-  get: function DPB_get(aPref, aType) {
-    if (!aPref || !aType) {
-      return;
-    }
-
-    try {
-      let prefs = Cc["@mozilla.org/preferences-service;1"].
-        getService(Ci.nsIPrefService).getBranch(this._branch);
-
-      return (aType === "boolean") ? prefs.getBoolPref(aPref) :
-             (aType === "string") ? prefs.getCharPref(aPref) :
-             (aType === "integer") ? prefs.getIntPref(aPref) : null;
-    }
-    catch(e) {
-      // handle any unexpected exceptions
-      dump(e.message);
-      return undefined;
-    }
-  },
-
-  /**
-   * Sets a custom debugger preference.
-   * If the preference already exists, it is overwritten.
-   *
-   * @param {String} aPref
-   *                 the preference name
-   * @param {String} aType
-   *                 either "boolean", "string" or "integer"
-   * @param {String} aValue
-   *                 a new preference value
-   *
-   * @return {Boolean} true if the preference was set successfully
-   */
-  set: function DPB_set(aPref, aType, aValue) {
-    if (!aPref || !aType || aValue === undefined || aValue === null) {
-      return;
-    }
-
-    try {
-      let prefs = Cc["@mozilla.org/preferences-service;1"].
-        getService(Ci.nsIPrefService).getBranch(this._branch);
-
-      return (aType === "boolean") ? prefs.setBoolPref(aPref, aValue) :
-             (aType === "string") ? prefs.setCharPref(aPref, aValue) :
-             (aType === "integer") ? prefs.setIntPref(aPref, aValue) : false;
-    }
-    catch(e) {
-      // handle any unexpected exceptions
-      dump(e.message);
-      return false;
-    }
-  },
-
-  /**
-   * Creates a custom debugger preference.
-   * If the preference already exists, it is left unchanged.
-   *
-   * @param {String} aPref
-   *                 the preference name
-   * @param {String} aType
-   *                 either "boolean", "string" or "integer"
-   * @param {String} aValue
-   *                 the initial preference value
-   *
-   * @return {Boolean} true if the preference was initialized successfully
-   */
-  create: function DPB_create(aPref, aType, aValue) {
-    if (!aPref || !aType || aValue === undefined || aValue === null) {
-      return;
-    }
-
-    try {
-      let prefs = Cc["@mozilla.org/preferences-service;1"].
-        getService(Ci.nsIPrefService).getBranch(this._branch);
-
-      return prefs.prefHasUserValue(aPref) ? false :
-             (aType === "boolean") ? prefs.setBoolPref(aPref, aValue) :
-             (aType === "string") ? prefs.setCharPref(aPref, aValue) :
-             (aType === "integer") ? prefs.setIntPref(aPref, aValue) : false;
-    }
-    catch(e) {
-      // handle any unexpected exceptions
-      dump(e.message);
-      return false;
-    }
-  },
-
-  /**
-   * The preferences branch for this tool.
-   */
-  _branch: "devtools.debugger."
-};
-
-
-let DPU = DebuggerPreferences.UI;
-let DPB = DebuggerPreferences.Branch;
-
-DPB.get = DPB.get.bind(DPB);
-DPB.set = DPB.set.bind(DPB);
-DPB.create = DPB.create.bind(DPB);
deleted file mode 100644
--- a/browser/devtools/debugger/content/debugger-view.js
+++ /dev/null
@@ -1,1135 +0,0 @@
-/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- *   Mozilla Foundation
- * Portions created by the Initial Developer are Copyright (C) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Victor Porof <vporof@mozilla.com> (original author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the LGPL or the GPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- ***** END LICENSE BLOCK *****/
-"use strict";
-
-/*global StackFrames, ThreadState, dump */
-
-const Cu = Components.utils;
-
-const DBG_STRINGS_URI = "chrome://browser/locale/devtools/debugger.properties";
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import('resource://gre/modules/Services.jsm');
-
-XPCOMUtils.defineLazyGetter(this, "stringBundle", function () {
-  return Services.strings.createBundle(DBG_STRINGS_URI);
-});
-
-/**
- * Object mediating visual changes and event listeners between the debugger and
- * the html view.
- */
-let DebuggerView = {
-
-  /**
-   * L10N shortcut function
-   *
-   * @param string aName
-   * @returns string
-   */
-  getStr: function DV_getStr(aName)
-  {
-    return stringBundle.GetStringFromName(aName);
-  },
-
-  /**
-   * L10N shortcut function
-   *
-   * @param string aName
-   * @param array aArray
-   * @returns string
-   */
-  getFormatStr: function DV_getFormatStr(aName, aArray)
-  {
-    return stringBundle.formatStringFromName(aName, aArray, aArray.length);
-  }
-
-};
-
-/**
- * Functions handling the html stackframes UI.
- */
-DebuggerView.Stackframes = {
-
-  /**
-   * Sets the current frames state based on the debugger active thread state.
-   *
-   * @param {String} aState
-   *                 either "paused" or "attached"
-   */
-  updateState: function DVF_updateState(aState) {
-    let resume = document.getElementById("resume");
-    let status = document.getElementById("status");
-
-    // if we're paused, show a pause label and disable the resume button
-    if (aState === "paused") {
-      status.textContent = DebuggerView.getStr("pausedState");
-      resume.disabled = false;
-    } else if (aState === "attached") {
-      // if we're attached, do the opposite
-      status.textContent = DebuggerView.getStr("runningState");
-      resume.disabled = true;
-    } else {
-      // no valid state parameter
-      status.textContent = "";
-    }
-  },
-
-  /**
-   * Sets the onClick listener for the stackframes container.
-   *
-   * @param {Function} aHandler
-   *                   the delegate used as the event listener
-   */
-  addClickListener: function DVF_addClickListener(aHandler) {
-    // save the handler so it can be removed on shutdown
-    this._onFramesClick = aHandler;
-    this._frames.addEventListener("click", aHandler, false);
-  },
-
-  /**
-   * Removes all elements from the stackframes container, leaving it empty.
-   */
-  empty: function DVF_empty() {
-    while (this._frames.firstChild) {
-      this._frames.removeChild(this._frames.firstChild);
-    }
-  },
-
-  /**
-   * Removes all elements from the stackframes container, and adds a child node
-   * with an empty text note attached.
-   */
-  emptyText: function DVF_emptyText() {
-    // make sure the container is empty first
-    this.empty();
-
-    let item = document.createElement("div");
-
-    // the empty node should look grayed out to avoid confusion
-    item.className = "empty list-item";
-    item.appendChild(document.createTextNode(DebuggerView.getStr("emptyText")));
-
-    this._frames.appendChild(item);
-  },
-
-  /**
-   * Adds a frame to the stackframes container.
-   * If the frame already exists (was previously added), null is returned.
-   * Otherwise, the newly created element is returned.
-   *
-   * @param {Number} aDepth
-   *                 the frame depth specified by the debugger
-   * @param {String} aFrameIdText
-   *                 the id to be displayed in the list
-   * @param {String} aFrameNameText
-   *                 the name to be displayed in the list
-   *
-   * @return {Object} the newly created html node representing the added frame
-   */
-  addFrame: function DVF_addFrame(aDepth, aFrameIdText, aFrameNameText) {
-    // make sure we don't duplicate anything
-    if (document.getElementById("stackframe-" + aDepth)) {
-      return null;
-    }
-
-    let frame = document.createElement("div");
-    let frameId = document.createElement("span");
-    let frameName = document.createElement("span");
-
-    // create a list item to be added to the stackframes container
-    frame.id = "stackframe-" + aDepth;
-    frame.className = "dbg-stackframe list-item";
-
-    // this list should display the id and name of the frame
-    frameId.className = "dbg-stackframe-id";
-    frameName.className = "dbg-stackframe-name";
-    frameId.appendChild(document.createTextNode(aFrameIdText));
-    frameName.appendChild(document.createTextNode(aFrameNameText));
-
-    frame.appendChild(frameId);
-    frame.appendChild(frameName);
-
-    this._frames.appendChild(frame);
-
-    // return the element for later use if necessary
-    return frame;
-  },
-
-  /**
-   * Highlights a frame from the stackframe container as selected/deselected.
-   *
-   * @param {Number} aDepth
-   *                 the frame depth specified by the debugger
-   * @param {Boolean} aSelect
-   *                  true if the frame should be selected, false otherwise
-   */
-  highlightFrame: function DVF_highlightFrame(aDepth, aSelect) {
-    let frame = document.getElementById("stackframe-" + aDepth);
-
-    // the list item wasn't found in the stackframe container
-    if (!frame) {
-      dump("The frame list item wasn't found in the stackframes container.");
-      return;
-    }
-
-    // add the 'selected' css class if the frame isn't already selected
-    if (aSelect && !frame.classList.contains("selected")) {
-      frame.classList.add("selected");
-
-    // remove the 'selected' css class if the frame is already selected
-    } else if (!aSelect && frame.classList.contains("selected")) {
-      frame.classList.remove("selected");
-    }
-  },
-
-  /**
-   * Gets the current dirty state.
-   */
-  get dirty() {
-    return this._dirty;
-  },
-
-  /**
-   * Sets if the active thread has more frames that need to be loaded.
-   *
-   * @param {Boolean} value
-   *                  true if should load more frames
-   */
-  set dirty(value) {
-    this._dirty = value;
-  },
-
-  /**
-   * The cached click listener for the stackframes container.
-   */
-  _onFramesClick: null,
-
-  /**
-   * Listener handling the stackframes container scroll event.
-   */
-  _onFramesScroll: function DVF__onFramesScroll(e) {
-    // update the stackframes container only if we have to
-    if (this._dirty) {
-
-      let clientHeight = this._frames.clientHeight;
-      let scrollTop = this._frames.scrollTop;
-      let scrollHeight = this._frames.scrollHeight;
-
-      // if the stackframes container was scrolled past 95% of the height,
-      // load more content
-      if (scrollTop >= (scrollHeight - clientHeight) * 0.95) {
-        this._dirty = false;
-
-        StackFrames._addMoreFrames();
-      }
-    }
-  },
-
-  /**
-   * Listener handling the close button click event.
-   */
-  _onCloseButtonClick: function DVF__onCloseButtonClick() {
-    let root = document.documentElement;
-    let debuggerClose = document.createEvent("Events");
-
-    debuggerClose.initEvent("DebuggerClose", true, false);
-    root.dispatchEvent(debuggerClose);
-  },
-
-  /**
-   * Listener handling the resume button click event.
-   */
-  _onResumeButtonClick: function DVF__onResumeButtonClick() {
-    ThreadState.activeThread.resume();
-  },
-
-  /**
-   * Specifies if the active thread has more frames which need to be loaded.
-   */
-  _dirty: false,
-
-  /**
-   * The cached stackframes container.
-   */
-  _frames: null,
-
-  /**
-   * Initialization function, called when the debugger is initialized.
-   */
-  initialize: function DVF_initialize() {
-    let close = document.getElementById("close");
-    let resume = document.getElementById("resume");
-    let frames = document.getElementById("stackframes");
-
-    close.addEventListener("click", this._onCloseButtonClick, false);
-    resume.addEventListener("click", this._onResumeButtonClick, false);
-    frames.addEventListener("scroll", this._onFramesScroll, false);
-    window.addEventListener("resize", this._onFramesScroll, false);
-
-    this._frames = frames;
-  },
-
-  /**
-   * Destruction function, called when the debugger is shut down.
-   */
-  destroy: function DVF_destroy() {
-    let close = document.getElementById("close");
-    let resume = document.getElementById("resume");
-    let frames = this._frames;
-
-    close.removeEventListener("click", this._onCloseButtonClick, false);
-    resume.removeEventListener("click", this._onResumeButtonClick, false);
-    frames.removeEventListener("click", this._onFramesClick, false);
-    frames.removeEventListener("scroll", this._onFramesScroll, false);
-    window.removeEventListener("resize", this._onFramesScroll, false);
-
-    this._frames = null;
-  }
-};
-
-/**
- * Functions handling the properties view.
- */
-DebuggerView.Properties = {
-
-  /**
-   * Adds a scope to contain any inspected variables.
-   * If the optional id is not specified, the scope html node will have a
-   * default id set as aName-scope.
-   *
-   * @param {String} aName
-   *                 the scope name (e.g. "Local", "Global" or "With block")
-   * @paarm {String} aId
-   *                 optional, an id for the scope html node
-   *
-   * @return {Object} the newly created html node representing the added scope
-   */
-  _addScope: function DVP__addScope(aName, aId) {
-    // make sure the parent container exists
-    if (!this._vars) {
-      return null;
-    }
-
-    // compute the id of the element if not specified
-    aId = aId || (aName + "-scope");
-
-    // contains generic nodes and functionality
-    let element = this._createPropertyElement(aName, aId, "scope", this._vars);
-
-    // make sure the element was created successfully
-    if (!element) {
-      dump("The debugger scope container wasn't created properly: " + aId);
-      return null;
-    }
-
-    /**
-     * @see DebuggerView.Properties._addVar
-     */
-    element.addVar = this._addVar.bind(this, element);
-
-    // return the element for later use if necessary
-    return element;
-  },
-
-  /**
-   * Adds a variable to a specified scope.
-   * If the optional id is not specified, the variable html node will have a
-   * default id set as aScope.id->aName-variable.
-   *
-   * @param {Object} aScope
-   *                 the parent scope element
-   * @param {String} aName
-   *                 the variable name
-   * @paarm {String} aId
-   *                 optional, an id for the variable html node
-   *
-   * @return {Object} the newly created html node representing the added var.
-   */
-  _addVar: function DVP__addVar(aScope, aName, aId) {
-    // make sure the scope container exists
-    if (!aScope) {
-      return null;
-    }
-
-    // compute the id of the element if not specified
-    aId = aId || (aScope.id + "->" + aName + "-variable");
-
-    // contains generic nodes and functionality
-    let element = this._createPropertyElement(aName, aId, "variable",
-                                              aScope.querySelector(".details"));
-
-    // make sure the element was created successfully
-    if (!element) {
-      dump("The debugger variable container wasn't created properly: " + aId);
-      return null;
-    }
-
-    /**
-     * @see DebuggerView.Properties._setGrip
-     */
-    element.setGrip = this._setGrip.bind(this, element);
-
-    /**
-     * @see DebuggerView.Properties._addProperties
-     */
-    element.addProperties = this._addProperties.bind(this, element);
-
-    // setup the additional elements specific for a variable node
-    element.refresh(function() {
-      let separator = document.createElement("span");
-      let info = document.createElement("span");
-      let title = element.querySelector(".title");
-      let arrow = element.querySelector(".arrow");
-
-      // separator shouldn't be selectable
-      separator.className = "unselectable";
-      separator.appendChild(document.createTextNode(": "));
-
-      // the variable information (type, class and/or value)
-      info.className = "info";
-
-      title.appendChild(separator);
-      title.appendChild(info);
-      arrow.classList.add("small");
-
-    }.bind(this));
-
-    // return the element for later use if necessary
-    return element;
-  },
-
-  /**
-   * Sets the specific grip for a variable.
-   * The grip should contain the value or the type & class, as defined in the
-   * remote debugger protocol. For convenience, undefined and null are
-   * both considered types.
-   *
-   * @param {Object} aVar
-   *                 the parent variable element
-   * @param {Object} aGrip
-   *                 the primitive or object defining the grip, specifying
-   *                 the value and/or type & class of the variable (if the type
-   *                 is not specified, it will be inferred from the value)
-   *                 e.g. 42
-   *                      true
-   *                      "nasu"
-   *                      { type: "undefined" } }
-   *                      { type: "null" } }
-   *                      { type: "object", class: "Object" } }
-   *
-   * @return {Object} the same variable
-   */
-  _setGrip: function DVP__setGrip(aVar, aGrip) {
-    // make sure the variable container exists
-    if (!aVar) {
-      return null;
-    }
-
-    let info = aVar.querySelector(".info") || aVar.target.info;
-
-    // make sure the info node exists
-    if (!info) {
-      dump("Could not set the grip for the corresponding variable: " + aVar.id);
-      return null;
-    }
-
-    info.textContent = this._propertyString(aGrip);
-    info.classList.add(this._propertyColor(aGrip));
-
-    return aVar;
-  },
-
-  /**
-   * Adds multiple properties to a specified variable.
-   * This function handles two types of properties: data properties and
-   * accessor properties, as defined in the remote debugger protocol spec.
-   *
-   * @param {Object} aVar
-   *                 the parent variable element
-   * @param {Object} aProperties
-   *                 an object containing the key: descriptor data properties,
-   *                 specifying the value and/or type & class of the variable,
-   *                 or 'get' & 'set' accessor properties
-   *                 e.g. { "someProp0": { value: 42 },
-   *                        "someProp1": { value: true },
-   *                        "someProp2": { value: "nasu" },
-   *                        "someProp3": { value: { type: "undefined" } },
-   *                        "someProp4": { value: { type: "null" } },
-   *                        "someProp5": { value: { type: "object", class: "Object" } },
-   *                        "someProp6": { get: { "type": "object", "class": "Function" },
-   *                                       set: { "type": "undefined" } } }
-   *
-   * @return {Object} the same variable
-   */
-  _addProperties: function DVP__addProperties(aVar, aProperties) {
-    // for each property, add it using the passed object key/grip
-    for (let i in aProperties) {
-      if (aProperties.hasOwnProperty(i)) {
-
-        // get the specified descriptor for current property
-        let desc = aProperties[i];
-
-        // as described in the remote debugger protocol, the value grip must be
-        // contained in a 'value' property
-        let value = desc["value"];
-
-        // for accessor property descriptors, the two grips need to be
-        // contained in 'get' and 'set' properties
-        let getter = desc["get"];
-        let setter = desc["set"];
-
-        // handle data property and accessor property descriptors
-        if (value !== undefined) {
-          this._addProperty(aVar, [i, value]);
-        }
-        if (getter !== undefined || setter !== undefined) {
-          let prop = this._addProperty(aVar, [i]).expand();
-          prop.getter = this._addProperty(prop, ["get", getter]);
-          prop.setter = this._addProperty(prop, ["set", setter]);
-        }
-      }
-    }
-    return aVar;
-  },
-
-  /**
-   * Adds a property to a specified variable.
-   * If the optional id is not specified, the property html node will have a
-   * default id set as aVar.id->aKey-property.
-   *
-   * @param {Object} aVar
-   *                 the parent variable element
-   * @param {Array} aProperty
-   *                an array containing the key and grip properties, specifying
-   *                the value and/or type & class of the variable (if the type
-   *                is not specified, it will be inferred from the value)
-   *                e.g. ["someProp0": 42]
-   *                     ["someProp1": true]
-   *                     ["someProp2": "nasu"]
-   *                     ["someProp3": { type: "undefined" }]
-   *                     ["someProp4": { type: "null" }]
-   *                     ["someProp5": { type: "object", class: "Object" }]
-   * @param {String} aName
-   *                 optional, the property name
-   * @paarm {String} aId
-   *                 optional, an id for the property html node
-   *
-   * @return {Object} the newly created html node representing the added prop.
-   */
-  _addProperty: function DVP__addProperty(aVar, aProperty, aName, aId) {
-    // make sure the variable container exists
-    if (!aVar) {
-      return null;
-    }
-
-    // compute the id of the element if not specified
-    aId = aId || (aVar.id + "->" + aProperty[0] + "-property");
-
-    // contains generic nodes and functionality
-    let element = this._createPropertyElement(aName, aId, "property",
-                                              aVar.querySelector(".details"));
-
-    // make sure the element was created successfully
-    if (!element) {
-      dump("The debugger property container wasn't created properly.");
-      return null;
-    }
-
-    /**
-     * @see DebuggerView.Properties._setGrip
-     */
-    element.setGrip = this._setGrip.bind(this, element);
-
-    /**
-     * @see DebuggerView.Properties._addProperties
-     */
-    element.addProperties = this._addProperties.bind(this, element);
-
-    // setup the additional elements specific for a variable node
-    element.refresh(function(pKey, pGrip) {
-      let propertyString = this._propertyString(pGrip);
-      let propertyColor = this._propertyColor(pGrip);
-      let key = document.createElement("div");
-      let value = document.createElement("div");
-      let separator = document.createElement("span");
-      let title = element.querySelector(".title");
-      let arrow = element.querySelector(".arrow");
-
-      // use a key element to specify the property name
-      key.className = "key";
-      key.appendChild(document.createTextNode(pKey));
-
-      // use a value element to specify the property value
-      value.className = "value";
-      value.appendChild(document.createTextNode(propertyString));
-      value.classList.add(propertyColor);
-
-      // separator shouldn't be selected
-      separator.className = "unselectable";
-      separator.appendChild(document.createTextNode(": "));
-
-      if (pKey) {
-        title.appendChild(key);
-      }
-      if (pGrip) {
-        title.appendChild(separator);
-        title.appendChild(value);
-      }
-      arrow.classList.add("small");
-
-      // make the property also behave as a variable, to allow
-      // recursively adding properties to properties
-      element.target = {
-        info: value
-      };
-
-      // save the property to the variable for easier access
-      Object.defineProperty(aVar, pKey, { value: element,
-                                          writable: false,
-                                          enumerable: true,
-                                          configurable: true });
-    }.bind(this), aProperty);
-
-    // return the element for later use if necessary
-    return element;
-  },
-
-  /**
-   * Returns a custom formatted property string for a type and a value.
-   *
-   * @param {String} aGrip
-   *                 the variable grip
-   *
-   * @return {String} the formatted string
-   */
-  _propertyString: function DVP__propertyString(aGrip) {
-    if (aGrip && "object" === typeof aGrip) {
-      switch (aGrip["type"]) {
-        case "undefined":
-          return "undefined";
-        case "null":
-          return "null";
-        default:
-          return "[" + aGrip["type"] + " " + aGrip["class"] + "]";
-      }
-    } else {
-      switch (typeof aGrip) {
-        case "string":
-          return "\"" + aGrip + "\"";
-        case "boolean":
-          return aGrip ? "true" : "false";
-        default:
-          return aGrip + "";
-      }
-    }
-    return aGrip + "";
-  },
-
-  /**
-   * Returns a custom class style for a type and a value.
-   *
-   * @param {String} aGrip
-   *                 the variable grip
-   *
-   * @return {String} the class style
-   */
-  _propertyColor: function DVP__propertyColor(aGrip) {
-    if (aGrip && "object" === typeof aGrip) {
-      switch (aGrip["type"]) {
-        case "undefined":
-          return "token-undefined";
-        case "null":
-          return "token-null";
-      }
-    } else {
-      switch (typeof aGrip) {
-        case "string":
-          return "token-string";
-        case "boolean":
-          return "token-boolean";
-        case "number":
-          return "token-number";
-      }
-    }
-    return "token-other";
-  },
-
-  /**
-   * Creates an element which contains generic nodes and functionality used by
-   * any scope, variable or property added to the tree.
-   *
-   * @param {String} aName
-   *                 a generic name used in a title strip
-   * @param {String} aId
-   *                 obligatory id used by the created element node
-   * @param {String} aClass
-   *                 recommended style class used by the created element node
-   * @param {Object} aParent
-   *                 the parent node which will contain the element
-   *
-   * @return {Object} the newly created html node representing the generic elem.
-   */
-  _createPropertyElement: function DVP__createPropertyElement(aName, aId, aClass, aParent) {
-    // make sure we don't duplicate anything and the parent exists
-    if (document.getElementById(aId)) {
-      dump("Duplicating a property element id is not allowed.");
-      return null;
-    }
-    if (!aParent) {
-      dump("A property element must have a valid parent node specified.");
-      return null;
-    }
-
-    let element = document.createElement("div");
-    let arrow = document.createElement("span");
-    let name = document.createElement("span");
-    let title = document.createElement("div");
-    let details = document.createElement("div");
-
-    // create a scope node to contain all the elements
-    element.id = aId;
-    element.className = aClass;
-
-    // the expand/collapse arrow
-    arrow.className = "arrow collapsed";
-    arrow.style.visibility = "hidden";
-
-    // the name element
-    name.className = "name unselectable";
-    name.appendChild(document.createTextNode(aName || ""));
-
-    // the title element, containing the arrow and the name
-    title.className = "title";
-    title.addEventListener("click", function() { element.toggle(); }, true);
-
-    // the node element which will contain any added scope variables
-    details.className = "details";
-    details.style.display = "none";
-
-    title.appendChild(arrow);
-    title.appendChild(name);
-
-    element.appendChild(title);
-    element.appendChild(details);
-
-    aParent.appendChild(element);
-
-    /**
-     * Shows the element, setting the display style to "block".
-     * @return {Object} the same element
-     */
-    element.show = function DVP_element_show() {
-      element.style.display = "block";
-
-      if ("function" === typeof element.onshow) {
-        element.onshow(element);
-      }
-      return element;
-    };
-
-    /**
-     * Hides the element, setting the display style to "none".
-     * @return {Object} the same element
-     */
-    element.hide = function DVP_element_hide() {
-      element.style.display = "none";
-
-      if ("function" === typeof element.onhide) {
-        element.onhide(element);
-      }
-      return element;
-    };
-
-    /**
-     * Expands the element, showing all the added details.
-     * @return {Object} the same element
-     */
-    element.expand = function DVP_element_expand() {
-      arrow.classList.remove("collapsed");
-      arrow.classList.add("expanded");
-      details.style.display = "block";
-
-      if ("function" === typeof element.onexpand) {
-        element.onexpand(element);
-      }
-      return element;
-    };
-
-    /**
-     * Collapses the element, hiding all the added details.
-     * @return {Object} the same element
-     */
-    element.collapse = function DVP_element_collapse() {
-      arrow.classList.remove("expanded");
-      arrow.classList.add("collapsed");
-      details.style.display = "none";
-
-      if ("function" === typeof element.oncollapse) {
-        element.oncollapse(element);
-      }
-      return element;
-    };
-
-    /**
-     * Toggles between the element collapse/expand state.
-     * @return {Object} the same element
-     */
-    element.toggle = function DVP_element_toggle() {
-      element.expanded ^= true;
-
-      if ("function" === typeof element.ontoggle) {
-        element.ontoggle(element);
-      }
-      return element;
-    };
-
-    /**
-     * Returns if the element is visible.
-     * @return {Boolean} true if the element is visible
-     */
-    Object.defineProperty(element, "visible", {
-      get: function DVP_element_getVisible() {
-        return element.style.display !== "none";
-      },
-      set: function DVP_element_setVisible(value) {
-        if (value) {
-          element.show();
-        } else {
-          element.hide();
-        }
-      }
-    });
-
-    /**
-     * Returns if the element is expanded.
-     * @return {Boolean} true if the element is expanded
-     */
-    Object.defineProperty(element, "expanded", {
-      get: function DVP_element_getExpanded() {
-        return arrow.classList.contains("expanded");
-      },
-      set: function DVP_element_setExpanded(value) {
-        if (value) {
-          element.expand();
-        } else {
-          element.collapse();
-        }
-      }
-    });
-
-    /**
-     * Removes all added children in the details container tree.
-     * @return {Object} the same element
-     */
-    element.empty = function DVP_element_empty() {
-      // this details node won't have any elements, so hide the arrow
-      arrow.style.visibility = "hidden";
-      while (details.firstChild) {
-        details.removeChild(details.firstChild);
-      }
-
-      if ("function" === typeof element.onempty) {
-        element.onempty(element);
-      }
-      return element;
-    };
-
-    /**
-     * Removes the element from the parent node details container tree.
-     * @return {Object} the same element
-     */
-    element.remove = function DVP_element_remove() {
-      element.parentNode.removeChild(element);
-
-      if ("function" === typeof element.onremove) {
-        element.onremove(element);
-      }
-      return element;
-    };
-
-    /**
-     * Generic function refreshing the internal state of the element when
-     * it's modified (e.g. a child detail, variable, property is added).
-     *
-     * @param {Function} aFunction
-     *                   function logic used to modify the internal state
-     * @param {Array} aArguments
-     *                optional arguments array to be applied to aFunction
-     */
-    element.refresh = function DVP_element_refresh(aFunction, aArguments) {
-      if ("function" === typeof aFunction) {
-        aFunction.apply(this, aArguments);
-      }
-
-      let node = aParent.parentNode;
-      let arrow = node.querySelector(".arrow");
-      let children = node.querySelector(".details").childNodes.length;
-
-      // if the parent details node has at least one element, set the
-      // expand/collapse arrow visible
-      if (children) {
-        arrow.style.visibility = "visible";
-      } else {
-        arrow.style.visibility = "hidden";
-      }
-    }.bind(this);
-
-    // return the element for later use and customization
-    return element;
-  },
-
-  /**
-   * Returns the global scope container.
-   */
-  get globalScope() {
-    return this._globalScope;
-  },
-
-  /**
-   * Sets the display mode for the global scope container.
-   *
-   * @param {Boolean} value
-   *                  false to hide the container, true to show
-   */
-  set globalScope(value) {
-    if (value) {
-      this._globalScope.show();
-    } else {
-      this._globalScope.hide();
-    }
-  },
-
-  /**
-   * Returns the local scope container.
-   */
-  get localScope() {
-    return this._localScope;
-  },
-
-  /**
-   * Sets the display mode for the local scope container.
-   *
-   * @param {Boolean} value
-   *                  false to hide the container, true to show
-   */
-  set localScope(value) {
-    if (value) {
-      this._localScope.show();
-    } else {
-      this._localScope.hide();
-    }
-  },
-
-  /**
-   * Returns the with block scope container.
-   */
-  get withScope() {
-    return this._withScope;
-  },
-
-  /**
-   * Sets the display mode for the with block scope container.
-   *
-   * @param {Boolean} value
-   *                  false to hide the container, true to show
-   */
-  set withScope(value) {
-    if (value) {
-      this._withScope.show();
-    } else {
-      this._withScope.hide();
-    }
-  },
-
-  /**
-   * Returns the closure scope container.
-   */
-  get closureScope() {
-    return this._closureScope;
-  },
-
-  /**
-   * Sets the display mode for the with block scope container.
-   *
-   * @param {Boolean} value
-   *                  false to hide the container, true to show
-   */
-  set closureScope(value) {
-    if (value) {
-      this._closureScope.show();
-    } else {
-      this._closureScope.hide();
-    }
-  },
-
-  /**
-   * The cached variable properties container.
-   */
-  _vars: null,
-
-  /**
-   * Auto-created global, local, with block and closure scopes containing vars.
-   */
-  _globalScope: null,
-  _localScope: null,
-  _withScope: null,
-  _closureScope: null,
-
-  /**
-   * Initialization function, called when the debugger is initialized.
-   */
-  initialize: function DVP_initialize() {
-    let dvp = DebuggerView.Properties;
-    this._vars = document.getElementById("variables");
-    this._localScope = dvp._addScope(DebuggerView.getStr("localScope"))
-                          .expand();
-    this._withScope = dvp._addScope(DebuggerView.getStr("withScope"))
-                         .hide();
-    this._closureScope = dvp._addScope(DebuggerView.getStr("closureScope"))
-                            .hide();
-    this._globalScope = dvp._addScope(DebuggerView.getStr("globalScope"));
-  },
-
-  /**
-   * Destruction function, called when the debugger is shut down.
-   */
-  destroy: function DVP_destroy() {
-    this._vars = null;
-    this._globalScope = null;
-    this._localScope = null;
-    this._withScope = null;
-    this._closureScope = null;
-  }
-};
-
-/**
- * Functions handling the html scripts UI.
- */
-DebuggerView.Scripts = {
-
-  /**
-   * Sets the onClick listener for the stackframes container.
-   *
-   * @param {Function} aHandler
-   *                   the delegate used as the event listener
-   */
-  addChangeListener: function DVS_addChangeListener(aHandler) {
-    // save the handler so it can be removed on shutdown
-    this._onScriptsChange = aHandler;
-    this._scripts.addEventListener("change", aHandler, false);
-  },
-
-  /**
-   * Removes all elements from the scripts container, leaving it empty.
-   */
-  empty: function DVS_empty() {
-    while (this._scripts.firstChild) {
-      this._scripts.removeChild(this._scripts.firstChild);
-    }
-  },
-
-  /**
-   * Adds a script to the scripts container.
-   * If the script already exists (was previously added), null is returned.
-   * Otherwise, the newly created element is returned.
-   *
-   * @param {String} aUrl
-   *                 the script url
-   * @param {String} aSource
-   *                 the script source code
-   * @param {String} aScriptNameText
-   *                 optional, title displayed instead of url
-   *
-   * @return {Object} the newly created html node representing the added script
-   */
-  addScript: function DVS_addScript(aUrl, aSource, aScriptNameText) {
-    // make sure we don't duplicate anything
-    if (document.getElementById(aUrl)) {
-      return null;
-    }
-
-    let script = document.createElement("option");
-
-    // create a script item to be added to the scripts container
-    script.setAttribute("id", aUrl);
-    script.setAttribute("sourceScript", aSource);
-    script.appendChild(document.createTextNode(aScriptNameText || aUrl));
-
-    this._scripts.appendChild(script);
-    this._scripts.style.visibility = "visible";
-
-    // return the element for later use if necessary
-    return script;
-  },
-
-  /**
-   * The cached click listener for the scripts container.
-   */
-  _onScriptsChange: null,
-
-  /**
-   * The cached scripts container.
-   */
-  _scripts: null,
-
-  /**
-   * Initialization function, called when the debugger is initialized.
-   */
-  initialize: function DVS_initialize() {
-    this._scripts = document.getElementById("scripts");
-  },
-
-  /**
-   * Destruction function, called when the debugger is shut down.
-   */
-  destroy: function DVS_destroy() {
-    this._scripts.removeEventListener("change", this._onScriptsChange, false);
-    this._scripts = null;
-  }
-};
-
-
-let DVF = DebuggerView.Stackframes;
-let DVP = DebuggerView.Properties;
-let DVS = DebuggerView.Scripts;
-
-DVF._onFramesScroll = DVF._onFramesScroll.bind(DVF);
-DVF._onCloseButtonClick = DVF._onCloseButtonClick.bind(DVF);
-DVF._onResumeButtonClick = DVF._onResumeButtonClick.bind(DVF);
deleted file mode 100644
--- a/browser/devtools/debugger/content/debugger.xhtml
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is mozilla.org code.
-#
-# The Initial Developer of the Original Code is
-#   Mozilla Foundation
-# Portions created by the Initial Developer are Copyright (C) 2011
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#  Dave Camp <dcamp@mozilla.com>
-#  Panos Astithas <past@mozilla.com>
-#  Victor Porof <vporof@mozilla.com>
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either the GNU General Public License Version 2 or later (the "GPL"), or
-# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
-  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" [
-<!ENTITY % debuggerDTD SYSTEM "chrome://browser/locale/devtools/debugger.dtd" >
- %debuggerDTD;
-]>
-
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
-
-    <head>
-        <title>&nbsp;</title>
-        <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8"/>
-
-        <link rel="stylesheet" href="chrome://browser/skin/" type="text/css"/>
-        <link rel="stylesheet" href="chrome://browser/content/orion.css" type="text/css"/>
-        <link rel="stylesheet" href="debugger.css" type="text/css"/>
-
-        <script type="text/javascript;version=1.8" src="debugger.js"></script>
-        <script type="text/javascript;version=1.8" src="debugger-view.js"></script>
-    </head>
-
-    <body class="vbox">
-        <menu id="dbg-toolbar">
-            <button id="close">&closeButton;</button>
-            <button id="resume">&resumeButton;</button>
-            <select id="scripts"></select>
-        </menu>
-        <div id="dbg-content" class="hbox flex">
-            <div id="stack" class="vbox">
-                <div class="title unselectable">&stackTitle;</div>
-                <div id="stackframes" class="vbox flex"></div>
-            </div>
-            <div id="script" class="vbox flex">
-                <div class="title unselectable">&scriptTitle;</div>
-                <div id="editor" class="vbox flex"></div>
-            </div>
-            <div id="properties" class="vbox">
-                <div class="title unselectable">&propertiesTitle;</div>
-                <div id="variables" class="vbox flex"></div>
-            </div>
-        </div>
-        <div id="dbg-statusbar">
-            <span id="status"></span>
-        </div>
-    </body>
-
-</html>
new file mode 100644
--- /dev/null
+++ b/browser/devtools/debugger/debugger-view.js
@@ -0,0 +1,1137 @@
+/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ *   Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Victor Porof <vporof@mozilla.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the LGPL or the GPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ ***** END LICENSE BLOCK *****/
+"use strict";
+
+/*global Components, XPCOMUtils, Services, StackFrames, ThreadState, dump */
+const Cu = Components.utils;
+
+const DBG_STRINGS_URI = "chrome://browser/locale/devtools/debugger.properties";
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import('resource://gre/modules/Services.jsm');
+
+/**
+ * Object mediating visual changes and event listeners between the debugger and
+ * the html view.
+ */
+let DebuggerView = {
+
+  /**
+   * L10N shortcut function
+   *
+   * @param string aName
+   * @returns string
+   */
+  getStr: function DV_getStr(aName) {
+    return this.stringBundle.GetStringFromName(aName);
+  },
+
+  /**
+   * L10N shortcut function
+   *
+   * @param string aName
+   * @param array aArray
+   * @returns string
+   */
+  getFormatStr: function DV_getFormatStr(aName, aArray) {
+    return this.stringBundle.formatStringFromName(aName, aArray, aArray.length);
+  }
+};
+
+XPCOMUtils.defineLazyGetter(DebuggerView, "stringBundle", function() {
+  return Services.strings.createBundle(DBG_STRINGS_URI);
+});
+
+/**
+ * Functions handling the html stackframes UI.
+ */
+DebuggerView.Stackframes = {
+
+  /**
+   * Sets the current frames state based on the debugger active thread state.
+   *
+   * @param string aState
+   *        Either "paused" or "attached".
+   */
+  updateState: function DVF_updateState(aState) {
+    let resume = document.getElementById("resume");
+    let status = document.getElementById("status");
+
+    // if we're paused, show a pause label and disable the resume button
+    if (aState === "paused") {
+      status.textContent = DebuggerView.getStr("pausedState");
+      resume.disabled = false;
+    } else if (aState === "attached") {
+      // if we're attached, do the opposite
+      status.textContent = DebuggerView.getStr("runningState");
+      resume.disabled = true;
+    } else {
+      // no valid state parameter
+      status.textContent = "";
+    }
+  },
+
+  /**
+   * Sets the onClick listener for the stackframes container.
+   *
+   * @param function aHandler
+   *        The delegate used as the event listener.
+   */
+  addClickListener: function DVF_addClickListener(aHandler) {
+    // save the handler so it can be removed on shutdown
+    this._onFramesClick = aHandler;
+    this._frames.addEventListener("click", aHandler, false);
+  },
+
+  /**
+   * Removes all elements from the stackframes container, leaving it empty.
+   */
+  empty: function DVF_empty() {
+    while (this._frames.firstChild) {
+      this._frames.removeChild(this._frames.firstChild);
+    }
+  },
+
+  /**
+   * Removes all elements from the stackframes container, and adds a child node
+   * with an empty text note attached.
+   */
+  emptyText: function DVF_emptyText() {
+    // make sure the container is empty first
+    this.empty();
+
+    let item = document.createElement("div");
+
+    // the empty node should look grayed out to avoid confusion
+    item.className = "empty list-item";
+    item.appendChild(document.createTextNode(DebuggerView.getStr("emptyText")));
+
+    this._frames.appendChild(item);
+  },
+
+  /**
+   * Adds a frame to the stackframes container.
+   * If the frame already exists (was previously added), null is returned.
+   * Otherwise, the newly created element is returned.
+   *
+   * @param number aDepth
+   *        The frame depth specified by the debugger.
+   * @param string aFrameIdText
+   *        The id to be displayed in the list.
+   * @param string aFrameNameText
+   *        The name to be displayed in the list.
+   * @return object
+   *         The newly created html node representing the added frame.
+   */
+  addFrame: function DVF_addFrame(aDepth, aFrameIdText, aFrameNameText) {
+    // make sure we don't duplicate anything
+    if (document.getElementById("stackframe-" + aDepth)) {
+      return null;
+    }
+
+    let frame = document.createElement("div");
+    let frameId = document.createElement("span");
+    let frameName = document.createElement("span");
+
+    // create a list item to be added to the stackframes container
+    frame.id = "stackframe-" + aDepth;
+    frame.className = "dbg-stackframe list-item";
+
+    // this list should display the id and name of the frame
+    frameId.className = "dbg-stackframe-id";
+    frameName.className = "dbg-stackframe-name";
+    frameId.appendChild(document.createTextNode(aFrameIdText));
+    frameName.appendChild(document.createTextNode(aFrameNameText));
+
+    frame.appendChild(frameId);
+    frame.appendChild(frameName);
+
+    this._frames.appendChild(frame);
+
+    // return the element for later use if necessary
+    return frame;
+  },
+
+  /**
+   * Highlights a frame from the stackframe container as selected/deselected.
+   *
+   * @param number aDepth
+   *        The frame depth specified by the debugger.
+   * @param boolean aSelect
+   *        True if the frame should be selected, false otherwise.
+   */
+  highlightFrame: function DVF_highlightFrame(aDepth, aSelect) {
+    let frame = document.getElementById("stackframe-" + aDepth);
+
+    // the list item wasn't found in the stackframe container
+    if (!frame) {
+      dump("The frame list item wasn't found in the stackframes container.");
+      return;
+    }
+
+    // add the 'selected' css class if the frame isn't already selected
+    if (aSelect && !frame.classList.contains("selected")) {
+      frame.classList.add("selected");
+
+    // remove the 'selected' css class if the frame is already selected
+    } else if (!aSelect && frame.classList.contains("selected")) {
+      frame.classList.remove("selected");
+    }
+  },
+
+  /**
+   * Gets the current dirty state.
+   *
+   * @return boolean value
+   *         True if should load more frames.
+   */
+  get dirty() {
+    return this._dirty;
+  },
+
+  /**
+   * Sets if the active thread has more frames that need to be loaded.
+   *
+   * @param boolean value
+   *        True if should load more frames.
+   */
+  set dirty(value) {
+    this._dirty = value;
+  },
+
+  /**
+   * The cached click listener for the stackframes container.
+   */
+  _onFramesClick: null,
+
+  /**
+   * Listener handling the stackframes container scroll event.
+   */
+  _onFramesScroll: function DVF__onFramesScroll(e) {
+    // update the stackframes container only if we have to
+    if (this._dirty) {
+
+      let clientHeight = this._frames.clientHeight;
+      let scrollTop = this._frames.scrollTop;
+      let scrollHeight = this._frames.scrollHeight;
+
+      // if the stackframes container was scrolled past 95% of the height,
+      // load more content
+      if (scrollTop >= (scrollHeight - clientHeight) * 0.95) {
+        this._dirty = false;
+
+        StackFrames._addMoreFrames();
+      }
+    }
+  },
+
+  /**
+   * Listener handling the close button click event.
+   */
+  _onCloseButtonClick: function DVF__onCloseButtonClick() {
+    let root = document.documentElement;
+    let debuggerClose = document.createEvent("Events");
+
+    debuggerClose.initEvent("DebuggerClose", true, false);
+    root.dispatchEvent(debuggerClose);
+  },
+
+  /**
+   * Listener handling the resume button click event.
+   */
+  _onResumeButtonClick: function DVF__onResumeButtonClick() {
+    ThreadState.activeThread.resume();
+  },
+
+  /**
+   * Specifies if the active thread has more frames which need to be loaded.
+   */
+  _dirty: false,
+
+  /**
+   * The cached stackframes container.
+   */
+  _frames: null,
+
+  /**
+   * Initialization function, called when the debugger is initialized.
+   */
+  initialize: function DVF_initialize() {
+    let close = document.getElementById("close");
+    let resume = document.getElementById("resume");
+    let frames = document.getElementById("stackframes");
+
+    close.addEventListener("click", this._onCloseButtonClick, false);
+    resume.addEventListener("click", this._onResumeButtonClick, false);
+    frames.addEventListener("scroll", this._onFramesScroll, false);
+    window.addEventListener("resize", this._onFramesScroll, false);
+
+    this._frames = frames;
+  },
+
+  /**
+   * Destruction function, called when the debugger is shut down.
+   */
+  destroy: function DVF_destroy() {
+    let close = document.getElementById("close");
+    let resume = document.getElementById("resume");
+    let frames = this._frames;
+
+    close.removeEventListener("click", this._onCloseButtonClick, false);
+    resume.removeEventListener("click", this._onResumeButtonClick, false);
+    frames.removeEventListener("click", this._onFramesClick, false);
+    frames.removeEventListener("scroll", this._onFramesScroll, false);
+    window.removeEventListener("resize", this._onFramesScroll, false);
+
+    this._frames = null;
+  }
+};
+
+/**
+ * Functions handling the properties view.
+ */
+DebuggerView.Properties = {
+
+  /**
+   * Adds a scope to contain any inspected variables.
+   * If the optional id is not specified, the scope html node will have a
+   * default id set as aName-scope.
+   *
+   * @param string aName
+   *        The scope name (e.g. "Local", "Global" or "With block").
+   * @paarm string aId
+   *        Optional, an id for the scope html node.
+   * @return object
+   *         The newly created html node representing the added scope.
+   */
+  _addScope: function DVP__addScope(aName, aId) {
+    // make sure the parent container exists
+    if (!this._vars) {
+      return null;
+    }
+
+    // compute the id of the element if not specified
+    aId = aId || (aName + "-scope");
+
+    // contains generic nodes and functionality
+    let element = this._createPropertyElement(aName, aId, "scope", this._vars);
+
+    // make sure the element was created successfully
+    if (!element) {
+      dump("The debugger scope container wasn't created properly: " + aId);
+      return null;
+    }
+
+    /**
+     * @see DebuggerView.Properties._addVar
+     */
+    element.addVar = this._addVar.bind(this, element);
+
+    // return the element for later use if necessary
+    return element;
+  },
+
+  /**
+   * Adds a variable to a specified scope.
+   * If the optional id is not specified, the variable html node will have a
+   * default id set as aScope.id->aName-variable.
+   *
+   * @param object aScope
+   *        The parent scope element.
+   * @param string aName
+   *        The variable name.
+   * @paarm string aId
+   *        Optional, an id for the variable html node.
+   * @return object
+   *         The newly created html node representing the added var.
+   */
+  _addVar: function DVP__addVar(aScope, aName, aId) {
+    // make sure the scope container exists
+    if (!aScope) {
+      return null;
+    }
+
+    // compute the id of the element if not specified
+    aId = aId || (aScope.id + "->" + aName + "-variable");
+
+    // contains generic nodes and functionality
+    let element = this._createPropertyElement(aName, aId, "variable",
+                                              aScope.querySelector(".details"));
+
+    // make sure the element was created successfully
+    if (!element) {
+      dump("The debugger variable container wasn't created properly: " + aId);
+      return null;
+    }
+
+    /**
+     * @see DebuggerView.Properties._setGrip
+     */
+    element.setGrip = this._setGrip.bind(this, element);
+
+    /**
+     * @see DebuggerView.Properties._addProperties
+     */
+    element.addProperties = this._addProperties.bind(this, element);
+
+    // setup the additional elements specific for a variable node
+    element.refresh(function() {
+      let separator = document.createElement("span");
+      let info = document.createElement("span");
+      let title = element.querySelector(".title");
+      let arrow = element.querySelector(".arrow");
+
+      // separator shouldn't be selectable
+      separator.className = "unselectable";
+      separator.appendChild(document.createTextNode(": "));
+
+      // the variable information (type, class and/or value)
+      info.className = "info";
+
+      title.appendChild(separator);
+      title.appendChild(info);
+      arrow.classList.add("small");
+
+    }.bind(this));
+
+    // return the element for later use if necessary
+    return element;
+  },
+
+  /**
+   * Sets the specific grip for a variable.
+   * The grip should contain the value or the type & class, as defined in the
+   * remote debugger protocol. For convenience, undefined and null are
+   * both considered types.
+   *
+   * @param object aVar
+   *        The parent variable element.
+   * @param object aGrip
+   *        The primitive or object defining the grip, specifying
+   *        the value and/or type & class of the variable (if the type
+   *        is not specified, it will be inferred from the value).
+   *        e.g. 42
+   *             true
+   *             "nasu"
+   *             { type: "undefined" } }
+   *             { type: "null" } }
+   *             { type: "object", class: "Object" } }
+   * @return object
+   *         The same variable.
+   */
+  _setGrip: function DVP__setGrip(aVar, aGrip) {
+    // make sure the variable container exists
+    if (!aVar) {
+      return null;
+    }
+
+    let info = aVar.querySelector(".info") || aVar.target.info;
+
+    // make sure the info node exists
+    if (!info) {
+      dump("Could not set the grip for the corresponding variable: " + aVar.id);
+      return null;
+    }
+
+    info.textContent = this._propertyString(aGrip);
+    info.classList.add(this._propertyColor(aGrip));
+
+    return aVar;
+  },
+
+  /**
+   * Adds multiple properties to a specified variable.
+   * This function handles two types of properties: data properties and
+   * accessor properties, as defined in the remote debugger protocol spec.
+   *
+   * @param object aVar
+   *        The parent variable element.
+   * @param object aProperties
+   *        An object containing the key: descriptor data properties,
+   *        specifying the value and/or type & class of the variable,
+   *        or 'get' & 'set' accessor properties.
+   *        e.g. { "someProp0": { value: 42 },
+   *               "someProp1": { value: true },
+   *               "someProp2": { value: "nasu" },
+   *               "someProp3": { value: { type: "undefined" } },
+   *               "someProp4": { value: { type: "null" } },
+   *               "someProp5": { value: { type: "object", class: "Object" } },
+   *               "someProp6": { get: { "type": "object", "class": "Function" },
+   *                              set: { "type": "undefined" } } }
+   * @return object
+   *         The same variable.
+   */
+  _addProperties: function DVP__addProperties(aVar, aProperties) {
+    // for each property, add it using the passed object key/grip
+    for (let i in aProperties) {
+      if (aProperties.hasOwnProperty(i)) {
+
+        // get the specified descriptor for current property
+        let desc = aProperties[i];
+
+        // as described in the remote debugger protocol, the value grip must be
+        // contained in a 'value' property
+        let value = desc["value"];
+
+        // for accessor property descriptors, the two grips need to be
+        // contained in 'get' and 'set' properties
+        let getter = desc["get"];
+        let setter = desc["set"];
+
+        // handle data property and accessor property descriptors
+        if (value !== undefined) {
+          this._addProperty(aVar, [i, value]);
+        }
+        if (getter !== undefined || setter !== undefined) {
+          let prop = this._addProperty(aVar, [i]).expand();
+          prop.getter = this._addProperty(prop, ["get", getter]);
+          prop.setter = this._addProperty(prop, ["set", setter]);
+        }
+      }
+    }
+    return aVar;
+  },
+
+  /**
+   * Adds a property to a specified variable.
+   * If the optional id is not specified, the property html node will have a
+   * default id set as aVar.id->aKey-property.
+   *
+   * @param object aVar
+   *        The parent variable element.
+   * @param {Array} aProperty
+   *        An array containing the key and grip properties, specifying
+   *        the value and/or type & class of the variable (if the type
+   *        is not specified, it will be inferred from the value).
+   *        e.g. ["someProp0": 42]
+   *             ["someProp1": true]
+   *             ["someProp2": "nasu"]
+   *             ["someProp3": { type: "undefined" }]
+   *             ["someProp4": { type: "null" }]
+   *             ["someProp5": { type: "object", class: "Object" }]
+   * @param string aName
+   *        Optional, the property name.
+   * @paarm string aId
+   *        Optional, an id for the property html node.
+   * @return object
+   *         The newly created html node representing the added prop.
+   */
+  _addProperty: function DVP__addProperty(aVar, aProperty, aName, aId) {
+    // make sure the variable container exists
+    if (!aVar) {
+      return null;
+    }
+
+    // compute the id of the element if not specified
+    aId = aId || (aVar.id + "->" + aProperty[0] + "-property");
+
+    // contains generic nodes and functionality
+    let element = this._createPropertyElement(aName, aId, "property",
+                                              aVar.querySelector(".details"));
+
+    // make sure the element was created successfully
+    if (!element) {
+      dump("The debugger property container wasn't created properly.");
+      return null;
+    }
+
+    /**
+     * @see DebuggerView.Properties._setGrip
+     */
+    element.setGrip = this._setGrip.bind(this, element);
+
+    /**
+     * @see DebuggerView.Properties._addProperties
+     */
+    element.addProperties = this._addProperties.bind(this, element);
+
+    // setup the additional elements specific for a variable node
+    element.refresh(function(pKey, pGrip) {
+      let propertyString = this._propertyString(pGrip);
+      let propertyColor = this._propertyColor(pGrip);
+      let key = document.createElement("div");
+      let value = document.createElement("div");
+      let separator = document.createElement("span");
+      let title = element.querySelector(".title");
+      let arrow = element.querySelector(".arrow");
+
+      // use a key element to specify the property name
+      key.className = "key";
+      key.appendChild(document.createTextNode(pKey));
+
+      // use a value element to specify the property value
+      value.className = "value";
+      value.appendChild(document.createTextNode(propertyString));
+      value.classList.add(propertyColor);
+
+      // separator shouldn't be selected
+      separator.className = "unselectable";
+      separator.appendChild(document.createTextNode(": "));
+
+      if (pKey) {
+        title.appendChild(key);
+      }
+      if (pGrip) {
+        title.appendChild(separator);
+        title.appendChild(value);
+      }
+      arrow.classList.add("small");
+
+      // make the property also behave as a variable, to allow
+      // recursively adding properties to properties
+      element.target = {
+        info: value
+      };
+
+      // save the property to the variable for easier access
+      Object.defineProperty(aVar, pKey, { value: element,
+                                          writable: false,
+                                          enumerable: true,
+                                          configurable: true });
+    }.bind(this), aProperty);
+
+    // return the element for later use if necessary
+    return element;
+  },
+
+  /**
+   * Returns a custom formatted property string for a type and a value.
+   *
+   * @param string | object aGrip
+   *        The variable grip.
+   * @return string
+   *         The formatted property string.
+   */
+  _propertyString: function DVP__propertyString(aGrip) {
+    if (aGrip && "object" === typeof aGrip) {
+      switch (aGrip["type"]) {
+        case "undefined":
+          return "undefined";
+        case "null":
+          return "null";
+        default:
+          return "[" + aGrip["type"] + " " + aGrip["class"] + "]";
+      }
+    } else {
+      switch (typeof aGrip) {
+        case "string":
+          return "\"" + aGrip + "\"";
+        case "boolean":
+          return aGrip ? "true" : "false";
+        default:
+          return aGrip + "";
+      }
+    }
+    return aGrip + "";
+  },
+
+  /**
+   * Returns a custom class style for a type and a value.
+   *
+   * @param string | object aGrip
+   *        The variable grip.
+   *
+   * @return string
+   *         The css class style.
+   */
+  _propertyColor: function DVP__propertyColor(aGrip) {
+    if (aGrip && "object" === typeof aGrip) {
+      switch (aGrip["type"]) {
+        case "undefined":
+          return "token-undefined";
+        case "null":
+          return "token-null";
+      }
+    } else {
+      switch (typeof aGrip) {
+        case "string":
+          return "token-string";
+        case "boolean":
+          return "token-boolean";
+        case "number":
+          return "token-number";
+      }
+    }
+    return "token-other";
+  },
+
+  /**
+   * Creates an element which contains generic nodes and functionality used by
+   * any scope, variable or property added to the tree.
+   *
+   * @param string aName
+   *        A generic name used in a title strip.
+   * @param string aId
+   *        Obligatory id used by the created element node.
+   * @param string aClass
+   *        Recommended style class used by the created element node.
+   * @param object aParent
+   *        The parent node which will contain the element.
+   * @return object
+   *         The newly created html node representing the generic elem.
+   */
+  _createPropertyElement: function DVP__createPropertyElement(aName, aId, aClass, aParent) {
+    // make sure we don't duplicate anything and the parent exists
+    if (document.getElementById(aId)) {
+      dump("Duplicating a property element id is not allowed.");
+      return null;
+    }
+    if (!aParent) {
+      dump("A property element must have a valid parent node specified.");
+      return null;
+    }
+
+    let element = document.createElement("div");
+    let arrow = document.createElement("span");
+    let name = document.createElement("span");
+    let title = document.createElement("div");
+    let details = document.createElement("div");
+
+    // create a scope node to contain all the elements
+    element.id = aId;
+    element.className = aClass;
+
+    // the expand/collapse arrow
+    arrow.className = "arrow collapsed";
+    arrow.style.visibility = "hidden";
+
+    // the name element
+    name.className = "name unselectable";
+    name.appendChild(document.createTextNode(aName || ""));
+
+    // the title element, containing the arrow and the name
+    title.className = "title";
+    title.addEventListener("click", function() { element.toggle(); }, true);
+
+    // the node element which will contain any added scope variables
+    details.className = "details";
+    details.style.display = "none";
+
+    title.appendChild(arrow);
+    title.appendChild(name);
+
+    element.appendChild(title);
+    element.appendChild(details);
+
+    aParent.appendChild(element);
+
+    /**
+     * Shows the element, setting the display style to "block".
+     * @return object
+     *         The same element.
+     */
+    element.show = function DVP_element_show() {
+      element.style.display = "block";
+
+      if ("function" === typeof element.onshow) {
+        element.onshow(element);
+      }
+      return element;
+    };
+
+    /**
+     * Hides the element, setting the display style to "none".
+     * @return object
+     *         The same element.
+     */
+    element.hide = function DVP_element_hide() {
+      element.style.display = "none";
+
+      if ("function" === typeof element.onhide) {
+        element.onhide(element);
+      }
+      return element;
+    };
+
+    /**
+     * Expands the element, showing all the added details.
+     * @return object
+     *         The same element.
+     */
+    element.expand = function DVP_element_expand() {
+      arrow.classList.remove("collapsed");
+      arrow.classList.add("expanded");
+      details.style.display = "block";
+
+      if ("function" === typeof element.onexpand) {
+        element.onexpand(element);
+      }
+      return element;
+    };
+
+    /**
+     * Collapses the element, hiding all the added details.
+     * @return object
+     *         The same element.
+     */
+    element.collapse = function DVP_element_collapse() {
+      arrow.classList.remove("expanded");
+      arrow.classList.add("collapsed");
+      details.style.display = "none";
+
+      if ("function" === typeof element.oncollapse) {
+        element.oncollapse(element);
+      }
+      return element;
+    };
+
+    /**
+     * Toggles between the element collapse/expand state.
+     * @return object
+     *         The same element.
+     */
+    element.toggle = function DVP_element_toggle() {
+      element.expanded ^= true;
+
+      if ("function" === typeof element.ontoggle) {
+        element.ontoggle(element);
+      }
+      return element;
+    };
+
+    /**
+     * Returns if the element is visible.
+     * @return boolean
+     *         True if the element is visible.
+     */
+    Object.defineProperty(element, "visible", {
+      get: function DVP_element_getVisible() {
+        return element.style.display !== "none";
+      },
+      set: function DVP_element_setVisible(value) {
+        if (value) {
+          element.show();
+        } else {
+          element.hide();
+        }
+      }
+    });
+
+    /**
+     * Returns if the element is expanded.
+     * @return boolean
+     *         True if the element is expanded.
+     */
+    Object.defineProperty(element, "expanded", {
+      get: function DVP_element_getExpanded() {
+        return arrow.classList.contains("expanded");
+      },
+      set: function DVP_element_setExpanded(value) {
+        if (value) {
+          element.expand();
+        } else {
+          element.collapse();
+        }
+      }
+    });
+
+    /**
+     * Removes all added children in the details container tree.
+     * @return object
+     *         The same element.
+     */
+    element.empty = function DVP_element_empty() {
+      // this details node won't have any elements, so hide the arrow
+      arrow.style.visibility = "hidden";
+      while (details.firstChild) {
+        details.removeChild(details.firstChild);
+      }
+
+      if ("function" === typeof element.onempty) {
+        element.onempty(element);
+      }
+      return element;
+    };
+
+    /**
+     * Removes the element from the parent node details container tree.
+     * @return object
+     *         The same element.
+     */
+    element.remove = function DVP_element_remove() {
+      element.parentNode.removeChild(element);
+
+      if ("function" === typeof element.onremove) {
+        element.onremove(element);
+      }
+      return element;
+    };
+
+    /**
+     * Generic function refreshing the internal state of the element when
+     * it's modified (e.g. a child detail, variable, property is added).
+     *
+     * @param function aFunction
+     *        The function logic used to modify the internal state.
+     * @param array aArguments
+     *        Optional arguments array to be applied to aFunction.
+     */
+    element.refresh = function DVP_element_refresh(aFunction, aArguments) {
+      if ("function" === typeof aFunction) {
+        aFunction.apply(this, aArguments);
+      }
+
+      let node = aParent.parentNode;
+      let arrow = node.querySelector(".arrow");
+      let children = node.querySelector(".details").childNodes.length;
+
+      // if the parent details node has at least one element, set the
+      // expand/collapse arrow visible
+      if (children) {
+        arrow.style.visibility = "visible";
+      } else {
+        arrow.style.visibility = "hidden";
+      }
+    }.bind(this);
+
+    // return the element for later use and customization
+    return element;
+  },
+
+  /**
+   * Returns the global scope container.
+   */
+  get globalScope() {
+    return this._globalScope;
+  },
+
+  /**
+   * Sets the display mode for the global scope container.
+   *
+   * @param boolean value
+   *        False to hide the container, true to show.
+   */
+  set globalScope(value) {
+    if (value) {
+      this._globalScope.show();
+    } else {
+      this._globalScope.hide();
+    }
+  },
+
+  /**
+   * Returns the local scope container.
+   */
+  get localScope() {
+    return this._localScope;
+  },
+
+  /**
+   * Sets the display mode for the local scope container.
+   *
+   * @param boolean value
+   *        False to hide the container, true to show.
+   */
+  set localScope(value) {
+    if (value) {
+      this._localScope.show();
+    } else {
+      this._localScope.hide();
+    }
+  },
+
+  /**
+   * Returns the with block scope container.
+   */
+  get withScope() {
+    return this._withScope;
+  },
+
+  /**
+   * Sets the display mode for the with block scope container.
+   *
+   * @param boolean value
+   *        False to hide the container, true to show.
+   */
+  set withScope(value) {
+    if (value) {
+      this._withScope.show();
+    } else {
+      this._withScope.hide();
+    }
+  },
+
+  /**
+   * Returns the closure scope container.
+   */
+  get closureScope() {
+    return this._closureScope;
+  },
+
+  /**
+   * Sets the display mode for the with block scope container.
+   *
+   * @param boolean value
+   *        False to hide the container, true to show.
+   */
+  set closureScope(value) {
+    if (value) {
+      this._closureScope.show();
+    } else {
+      this._closureScope.hide();
+    }
+  },
+
+  /**
+   * The cached variable properties container.
+   */
+  _vars: null,
+
+  /**
+   * Auto-created global, local, with block and closure scopes containing vars.
+   */
+  _globalScope: null,
+  _localScope: null,
+  _withScope: null,
+  _closureScope: null,
+
+  /**
+   * Initialization function, called when the debugger is initialized.
+   */
+  initialize: function DVP_initialize() {
+    this._vars = document.getElementById("variables");
+    this._localScope = this._addScope(DebuggerView.getStr("localScope")).expand();
+    this._withScope = this._addScope(DebuggerView.getStr("withScope")).hide();
+    this._closureScope = this._addScope(DebuggerView.getStr("closureScope")).hide();
+    this._globalScope = this._addScope(DebuggerView.getStr("globalScope"));
+  },
+
+  /**
+   * Destruction function, called when the debugger is shut down.
+   */
+  destroy: function DVP_destroy() {
+    this._vars = null;
+    this._globalScope = null;
+    this._localScope = null;
+    this._withScope = null;
+    this._closureScope = null;
+  }
+};
+
+/**
+ * Functions handling the html scripts UI.
+ */
+DebuggerView.Scripts = {
+
+  /**
+   * Sets the onClick listener for the stackframes container.
+   *
+   * @param function aHandler
+   *        The delegate used as the event listener.
+   */
+  addChangeListener: function DVS_addChangeListener(aHandler) {
+    // save the handler so it can be removed on shutdown
+    this._onScriptsChange = aHandler;
+    this._scripts.addEventListener("change", aHandler, false);
+  },
+
+  /**
+   * Removes all elements from the scripts container, leaving it empty.
+   */
+  empty: function DVS_empty() {
+    while (this._scripts.firstChild) {
+      this._scripts.removeChild(this._scripts.firstChild);
+    }
+  },
+
+  /**
+   * Adds a script to the scripts container.
+   * If the script already exists (was previously added), null is returned.
+   * Otherwise, the newly created element is returned.
+   *
+   * @param string aUrl
+   *        The script url.
+   * @param string aSource
+   *        The script source code.
+   * @param string aScriptNameText
+   *        Optional, title displayed instead of url.
+   * @return object
+   *         The newly created html node representing the added script.
+   */
+  addScript: function DVS_addScript(aUrl, aSource, aScriptNameText) {
+    // make sure we don't duplicate anything
+    if (document.getElementById(aUrl)) {
+      return null;
+    }
+
+    let script = document.createElement("option");
+
+    // create a script item to be added to the scripts container
+    script.setAttribute("id", aUrl);
+    script.setAttribute("sourceScript", aSource);
+    script.appendChild(document.createTextNode(aScriptNameText || aUrl));
+
+    this._scripts.appendChild(script);
+    this._scripts.style.visibility = "visible";
+
+    // return the element for later use if necessary
+    return script;
+  },
+
+  /**
+   * The cached click listener for the scripts container.
+   */
+  _onScriptsChange: null,
+
+  /**
+   * The cached scripts container.
+   */
+  _scripts: null,
+
+  /**
+   * Initialization function, called when the debugger is initialized.
+   */
+  initialize: function DVS_initialize() {
+    this._scripts = document.getElementById("scripts");
+  },
+
+  /**
+   * Destruction function, called when the debugger is shut down.
+   */
+  destroy: function DVS_destroy() {
+    this._scripts.removeEventListener("change", this._onScriptsChange, false);
+    this._scripts = null;
+  }
+};
+
+
+let DVF = DebuggerView.Stackframes;
+DVF._onFramesScroll = DVF._onFramesScroll.bind(DVF);
+DVF._onCloseButtonClick = DVF._onCloseButtonClick.bind(DVF);
+DVF._onResumeButtonClick = DVF._onResumeButtonClick.bind(DVF);
rename from browser/devtools/debugger/content/debugger.css
rename to browser/devtools/debugger/debugger.css
rename from browser/devtools/debugger/content/debugger.js
rename to browser/devtools/debugger/debugger.js
new file mode 100644
--- /dev/null
+++ b/browser/devtools/debugger/debugger.xhtml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8"?>
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+#   Mozilla Foundation
+# Portions created by the Initial Developer are Copyright (C) 2011
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#  Dave Camp <dcamp@mozilla.com>
+#  Panos Astithas <past@mozilla.com>
+#  Victor Porof <vporof@mozilla.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" [
+<!ENTITY % debuggerDTD SYSTEM "chrome://browser/locale/devtools/debugger.dtd" >
+ %debuggerDTD;
+]>
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+
+    <head>
+        <title>&nbsp;</title>
+        <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8"/>
+
+        <link rel="stylesheet" href="chrome://browser/skin/" type="text/css"/>
+        <link rel="stylesheet" href="chrome://browser/content/orion.css" type="text/css"/>
+        <link rel="stylesheet" href="debugger.css" type="text/css"/>
+
+        <script type="text/javascript;version=1.8" src="debugger.js"></script>
+        <script type="text/javascript;version=1.8" src="debugger-view.js"></script>
+    </head>
+
+    <body class="vbox">
+        <menu id="dbg-toolbar">
+            <button id="close">&debuggerUI.closeButton;</button>
+            <button id="resume">&debuggerUI.resumeButton;</button>
+            <select id="scripts"></select>
+        </menu>
+        <div id="dbg-content" class="hbox flex">
+            <div id="stack" class="vbox">
+                <div class="title unselectable">&debuggerUI.stackTitle;</div>
+                <div id="stackframes" class="vbox flex"></div>
+            </div>
+            <div id="script" class="vbox flex">
+                <div class="title unselectable">&debuggerUI.scriptTitle;</div>
+                <div id="editor" class="vbox flex"></div>
+            </div>
+            <div id="properties" class="vbox">
+                <div class="title unselectable">&debuggerUI.propertiesTitle;</div>
+                <div id="variables" class="vbox flex"></div>
+            </div>
+        </div>
+        <div id="dbg-statusbar">
+            <span id="status"></span>
+        </div>
+    </body>
+
+</html>
--- a/browser/devtools/debugger/test/Makefile.in
+++ b/browser/devtools/debugger/test/Makefile.in
@@ -15,16 +15,17 @@
 #
 # The Initial Developer of the Original Code is
 #   Mozilla Foundation
 # Portions created by the Initial Developer are Copyright (C) 2011
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
 #  Dave Camp <dcamp@mozilla.com>
+#  Victor Porof <vporof@mozilla.com>
 #
 # Alternatively, the contents of this file may be used under the terms of
 # either the GNU General Public License Version 2 or later (the "GPL"), or
 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 # in which case the provisions of the GPL or the LGPL are applicable instead
 # of those above. If you wish to allow use of your version of this file only
 # under the terms of either the GPL or the LGPL, and not to allow others to
 # use your version of this file under the terms of the MPL, indicate your
@@ -34,16 +35,57 @@
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
 DEPTH           = ../../../..
 topsrcdir       = @top_srcdir@
 srcdir          = @srcdir@
 VPATH           = @srcdir@
+relativesrcdir  = browser/devtools/debugger/test
 
 include $(DEPTH)/config/autoconf.mk
-
-MODULE          = test_browserdebugger
+include $(topsrcdir)/config/rules.mk
 
-DIRS = browser
+_BROWSER_TEST_FILES = \
+	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 \
+	browser_dbg_openpane.js \
+	browser_dbg_propertyview-01.js \
+	browser_dbg_propertyview-02.js \
+	browser_dbg_propertyview-03.js \
+	browser_dbg_propertyview-04.js \
+	browser_dbg_propertyview-05.js \
+	browser_dbg_propertyview-06.js \
+	browser_dbg_propertyview-07.js \
+	browser_dbg_propertyview-08.js \
+	browser_dbg_panesize.js \
+	browser_dbg_stack-01.js \
+	browser_dbg_stack-02.js \
+	browser_dbg_stack-03.js \
+	browser_dbg_stack-04.js \
+	browser_dbg_location-changes.js \
+	browser_dbg_script-switching.js \
+	head.js \
+	$(NULL)
 
-include $(topsrcdir)/config/rules.mk
+_BROWSER_TEST_PAGES = \
+	browser_dbg_tab1.html \
+	browser_dbg_tab2.html \
+	browser_dbg_debuggerstatement.html \
+	browser_dbg_stack.html \
+	browser_dbg_script-switching.html \
+	test-script-switching-01.js \
+	test-script-switching-02.js \
+	browser_dbg_frame-parameters.html \
+	$(NULL)
+
+libs:: $(_BROWSER_TEST_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
+
+libs:: $(_BROWSER_TEST_PAGES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
deleted file mode 100644
--- a/browser/devtools/debugger/test/browser/Makefile.in
+++ /dev/null
@@ -1,90 +0,0 @@
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is mozilla.org code.
-#
-# The Initial Developer of the Original Code is
-#   Mozilla Foundation
-# Portions created by the Initial Developer are Copyright (C) 2011
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#  Dave Camp <dcamp@mozilla.com>
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either the GNU General Public License Version 2 or later (the "GPL"), or
-# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-DEPTH           = ../../../../..
-topsrcdir       = @top_srcdir@
-srcdir          = @srcdir@
-VPATH           = @srcdir@
-relativesrcdir  = browser/devtools/debugger/test/browser
-
-include $(DEPTH)/config/autoconf.mk
-include $(topsrcdir)/config/rules.mk
-
-_BROWSER_TEST_FILES = \
-	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 \
-	browser_dbg_openpane.js \
-	browser_dbg_propertyview-01.js \
-	browser_dbg_propertyview-02.js \
-	browser_dbg_propertyview-03.js \
-	browser_dbg_propertyview-04.js \
-	browser_dbg_propertyview-05.js \
-	browser_dbg_propertyview-06.js \
-	browser_dbg_propertyview-07.js \
-	browser_dbg_propertyview-08.js \
-	browser_dbg_panesize.js \
-	browser_dbg_stack-01.js \
-	browser_dbg_stack-02.js \
-	browser_dbg_stack-03.js \
-	browser_dbg_stack-04.js \
-	browser_dbg_location-changes.js \
-	browser_dbg_script-switching.js \
-	head.js \
-	$(NULL)
-
-_BROWSER_TEST_PAGES = \
-	browser_dbg_tab1.html \
-	browser_dbg_tab2.html \
-	browser_dbg_debuggerstatement.html \
-	browser_dbg_stack.html \
-	browser_dbg_script-switching.html \
-	test-script-switching-01.js \
-	test-script-switching-02.js \
-	browser_dbg_frame-parameters.html \
-	$(NULL)
-
-libs:: $(_BROWSER_TEST_FILES)
-	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
-
-libs:: $(_BROWSER_TEST_PAGES)
-	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
deleted file mode 100644
--- a/browser/devtools/debugger/test/browser/browser_dbg_panesize.js
+++ /dev/null
@@ -1,40 +0,0 @@
-/* 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 = addTab(TAB1_URL, function() {
-    gBrowser.selectedTab = tab1;
-
-    ok(!DebuggerUI.getDebugger(gBrowser.selectedTab),
-      "Shouldn't have a debugger pane for this tab yet.");
-
-    let pane = DebuggerUI.startDebugger();
-    let someHeight = parseInt(Math.random() * 200) + 200;
-
-    ok(pane, "startDebugger() should return a pane.");
-
-    is(DebuggerUI.getDebugger(gBrowser.selectedTab), pane,
-      "getDebugger() should return the same pane as startDebugger().");
-
-    ok(DebuggerPreferences.UI.height,
-      "The debugger preferences should have a saved height value.");
-
-    is(DebuggerPreferences.UI.height, pane.frame.height,
-      "The debugger pane height should be the same as the preferred value.");
-
-    pane.frame.height = someHeight;
-    ok(DebuggerPreferences.UI.height !== someHeight,
-      "Height preferences shouldn't have been updated yet.");
-
-    pane.onConnected = function() {
-      removeTab(tab1);
-      finish();
-
-      is(DebuggerPreferences.UI.height, someHeight,
-        "Height preferences should have been updated by now.");
-    };
-  });
-}
rename from browser/devtools/debugger/test/browser/browser_dbg_contextactor-01.js
rename to browser/devtools/debugger/test/browser_dbg_contextactor-01.js
--- a/browser/devtools/debugger/test/browser/browser_dbg_contextactor-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_contextactor-01.js
@@ -7,17 +7,17 @@
 
 var gTab1 = null;
 var gTab1Actor = null;
 
 var gClient = null;
 
 function test()
 {
-  DebuggerServer.addActors("chrome://mochitests/content/browser/browser/devtools/debugger/test/browser/testactors.js");
+  DebuggerServer.addActors("chrome://mochitests/content/browser/browser/devtools/debugger/test/testactors.js");
 
   let transport = DebuggerServer.connectPipe();
   gClient = new DebuggerClient(transport);
   gClient.ready(function(aType, aTraits) {
     is(aType, "browser", "Root actor should identify itself as a browser.");
     get_tab();
   });
 }
rename from browser/devtools/debugger/test/browser/browser_dbg_contextactor-02.js
rename to browser/devtools/debugger/test/browser_dbg_contextactor-02.js
--- a/browser/devtools/debugger/test/browser/browser_dbg_contextactor-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_contextactor-02.js
@@ -7,17 +7,17 @@
 
 var gTab1 = null;
 var gTab1Actor = null;
 
 var gClient = null;
 
 function test()
 {
-  DebuggerServer.addActors("chrome://mochitests/content/browser/browser/devtools/debugger/test/browser/testactors.js");
+  DebuggerServer.addActors("chrome://mochitests/content/browser/browser/devtools/debugger/test/testactors.js");
 
   let transport = DebuggerServer.connectPipe();
   gClient = new DebuggerClient(transport);
   gClient.ready(function(aType, aTraits) {
     is(aType, "browser", "Root actor should identify itself as a browser.");
     get_tab();
   });
 }
rename from browser/devtools/debugger/test/browser/browser_dbg_debuggerstatement.html
rename to browser/devtools/debugger/test/browser_dbg_debuggerstatement.html
rename from browser/devtools/debugger/test/browser/browser_dbg_debuggerstatement.js
rename to browser/devtools/debugger/test/browser_dbg_debuggerstatement.js
--- a/browser/devtools/debugger/test/browser/browser_dbg_debuggerstatement.js
+++ b/browser/devtools/debugger/test/browser_dbg_debuggerstatement.js
@@ -4,17 +4,17 @@
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 // Tests the behavior of the debugger statement.
 
 var gClient = null;
 var gTab = null;
 const DEBUGGER_TAB_URL = "http://example.com/browser/browser/devtools/" +
-                         "debugger/test/browser/" +
+                         "debugger/test/" +
                          "browser_dbg_debuggerstatement.html";
 
 function test()
 {
   let transport = DebuggerServer.connectPipe();
   gClient = new DebuggerClient(transport);
   gClient.ready(function(aType, aTraits) {
     gTab = addTab(DEBUGGER_TAB_URL, function() {
rename from browser/devtools/debugger/test/browser/browser_dbg_frame-parameters.html
rename to browser/devtools/debugger/test/browser_dbg_frame-parameters.html
rename from browser/devtools/debugger/test/browser/browser_dbg_listtabs.js
rename to browser/devtools/debugger/test/browser_dbg_listtabs.js
rename from browser/devtools/debugger/test/browser/browser_dbg_location-changes.js
rename to browser/devtools/debugger/test/browser_dbg_location-changes.js
rename from browser/devtools/debugger/test/browser/browser_dbg_nav-01.js
rename to browser/devtools/debugger/test/browser_dbg_nav-01.js
rename from browser/devtools/debugger/test/browser/browser_dbg_openpane.js
rename to browser/devtools/debugger/test/browser_dbg_openpane.js
new file mode 100644
--- /dev/null
+++ b/browser/devtools/debugger/test/browser_dbg_panesize.js
@@ -0,0 +1,40 @@
+/* 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 = addTab(TAB1_URL, function() {
+    gBrowser.selectedTab = tab1;
+
+    ok(!DebuggerUI.getDebugger(gBrowser.selectedTab),
+      "Shouldn't have a debugger pane for this tab yet.");
+
+    let pane = DebuggerUI.startDebugger();
+    let someHeight = parseInt(Math.random() * 200) + 200;
+
+    ok(pane, "startDebugger() should return a pane.");
+
+    is(DebuggerUI.getDebugger(gBrowser.selectedTab), pane,
+      "getDebugger() should return the same pane as startDebugger().");
+
+    ok(DebuggerUI.getPreferences().height,
+      "The debugger preferences should have a saved height value.");
+
+    is(DebuggerUI.getPreferences().height, pane.frame.height,
+      "The debugger pane height should be the same as the preferred value.");
+
+    pane.frame.height = someHeight;
+    ok(DebuggerUI.getPreferences().height !== someHeight,
+      "Height preferences shouldn't have been updated yet.");
+
+    pane.onConnected = function() {
+      removeTab(tab1);
+      finish();
+
+      is(DebuggerUI.getPreferences().height, someHeight,
+        "Height preferences should have been updated by now.");
+    };
+  });
+}
rename from browser/devtools/debugger/test/browser/browser_dbg_propertyview-01.js
rename to browser/devtools/debugger/test/browser_dbg_propertyview-01.js
rename from browser/devtools/debugger/test/browser/browser_dbg_propertyview-02.js
rename to browser/devtools/debugger/test/browser_dbg_propertyview-02.js
rename from browser/devtools/debugger/test/browser/browser_dbg_propertyview-03.js
rename to browser/devtools/debugger/test/browser_dbg_propertyview-03.js
rename from browser/devtools/debugger/test/browser/browser_dbg_propertyview-04.js
rename to browser/devtools/debugger/test/browser_dbg_propertyview-04.js
rename from browser/devtools/debugger/test/browser/browser_dbg_propertyview-05.js
rename to browser/devtools/debugger/test/browser_dbg_propertyview-05.js
rename from browser/devtools/debugger/test/browser/browser_dbg_propertyview-06.js
rename to browser/devtools/debugger/test/browser_dbg_propertyview-06.js
rename from browser/devtools/debugger/test/browser/browser_dbg_propertyview-07.js
rename to browser/devtools/debugger/test/browser_dbg_propertyview-07.js
--- a/browser/devtools/debugger/test/browser/browser_dbg_propertyview-07.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-07.js
@@ -2,17 +2,17 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Make sure that the property view displays function parameters.
  */
 
 const TAB_URL = "http://example.com/browser/browser/devtools/debugger/test/" +
-                "browser/browser_dbg_frame-parameters.html";
+                "browser_dbg_frame-parameters.html";
 
 var gPane = null;
 var gTab = null;
 var gDebuggee = null;
 var gDebugger = null;
 
 function test()
 {
rename from browser/devtools/debugger/test/browser/browser_dbg_propertyview-08.js
rename to browser/devtools/debugger/test/browser_dbg_propertyview-08.js
--- a/browser/devtools/debugger/test/browser/browser_dbg_propertyview-08.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-08.js
@@ -2,17 +2,17 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Make sure that the property view displays the properties of objects.
  */
 
 const TAB_URL = "http://example.com/browser/browser/devtools/debugger/test/" +
-                "browser/browser_dbg_frame-parameters.html";
+                "browser_dbg_frame-parameters.html";
 
 var gPane = null;
 var gTab = null;
 var gDebuggee = null;
 var gDebugger = null;
 
 function test()
 {
rename from browser/devtools/debugger/test/browser/browser_dbg_script-switching.html
rename to browser/devtools/debugger/test/browser_dbg_script-switching.html
--- a/browser/devtools/debugger/test/browser/browser_dbg_script-switching.html
+++ b/browser/devtools/debugger/test/browser_dbg_script-switching.html
@@ -1,12 +1,12 @@
 <!DOCTYPE HTML>
 <html>
 	<head>
 		<title>Browser Debugger Script Switching Test</title>
     <!-- Any copyright is dedicated to the Public Domain.
          http://creativecommons.org/publicdomain/zero/1.0/ -->
-    <script type="text/javascript" src="http://example.com/browser/browser/devtools/debugger/test/browser/test-script-switching-01.js"></script>
-    <script type="text/javascript" src="http://example.com/browser/browser/devtools/debugger/test/browser/test-script-switching-02.js"></script>
+    <script type="text/javascript" src="http://example.com/browser/browser/devtools/debugger/test/test-script-switching-01.js"></script>
+    <script type="text/javascript" src="http://example.com/browser/browser/devtools/debugger/test/test-script-switching-02.js"></script>
 	</head>
 	<body>
 	</body>
 </html>
rename from browser/devtools/debugger/test/browser/browser_dbg_script-switching.js
rename to browser/devtools/debugger/test/browser_dbg_script-switching.js
--- a/browser/devtools/debugger/test/browser/browser_dbg_script-switching.js
+++ b/browser/devtools/debugger/test/browser_dbg_script-switching.js
@@ -1,18 +1,18 @@
 /* vim:set ts=2 sw=2 sts=2 et: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Make sure that switching the displayed script in the UI works as advertised.
  */
 
-const TAB_URL = "http://example.com/browser/browser/devtools/debugger/test/" +
-                "browser/browser_dbg_script-switching.html";
+const TAB_URL = "http://example.com/browser/browser/devtools/debugger/" +
+                "test/browser_dbg_script-switching.html";
 
 var gPane = null;
 var gTab = null;
 var gDebuggee = null;
 var gDebugger = null;
 var gScripts = null;
 
 function test()
rename from browser/devtools/debugger/test/browser/browser_dbg_stack-01.js
rename to browser/devtools/debugger/test/browser_dbg_stack-01.js
rename from browser/devtools/debugger/test/browser/browser_dbg_stack-02.js
rename to browser/devtools/debugger/test/browser_dbg_stack-02.js
rename from browser/devtools/debugger/test/browser/browser_dbg_stack-03.js
rename to browser/devtools/debugger/test/browser_dbg_stack-03.js
rename from browser/devtools/debugger/test/browser/browser_dbg_stack-04.js
rename to browser/devtools/debugger/test/browser_dbg_stack-04.js
rename from browser/devtools/debugger/test/browser/browser_dbg_stack.html
rename to browser/devtools/debugger/test/browser_dbg_stack.html
rename from browser/devtools/debugger/test/browser/browser_dbg_tab1.html
rename to browser/devtools/debugger/test/browser_dbg_tab1.html
rename from browser/devtools/debugger/test/browser/browser_dbg_tab2.html
rename to browser/devtools/debugger/test/browser_dbg_tab2.html
rename from browser/devtools/debugger/test/browser/browser_dbg_tabactor-01.js
rename to browser/devtools/debugger/test/browser_dbg_tabactor-01.js
--- a/browser/devtools/debugger/test/browser/browser_dbg_tabactor-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_tabactor-01.js
@@ -7,17 +7,17 @@
 
 var gTab1 = null;
 var gTab1Actor = null;
 
 var gClient = null;
 
 function test()
 {
-  DebuggerServer.addActors("chrome://mochitests/content/browser/browser/devtools/debugger/test/browser/testactors.js");
+  DebuggerServer.addActors("chrome://mochitests/content/browser/browser/devtools/debugger/test/testactors.js");
 
   let transport = DebuggerServer.connectPipe();
   gClient = new DebuggerClient(transport);
   gClient.ready(function (aType, aTraits) {
     is(aType, "browser", "Root actor should identify itself as a browser.");
     get_tab();
   });
 }
rename from browser/devtools/debugger/test/browser/browser_dbg_tabactor-02.js
rename to browser/devtools/debugger/test/browser_dbg_tabactor-02.js
--- a/browser/devtools/debugger/test/browser/browser_dbg_tabactor-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_tabactor-02.js
@@ -7,17 +7,17 @@
 
 var gTab1 = null;
 var gTab1Actor = null;
 
 var gClient = null;
 
 function test()
 {
-  DebuggerServer.addActors("chrome://mochitests/content/browser/browser/devtools/debugger/test/browser/testactors.js");
+  DebuggerServer.addActors("chrome://mochitests/content/browser/browser/devtools/debugger/test/testactors.js");
 
   let transport = DebuggerServer.connectPipe();
   gClient = new DebuggerClient(transport);
   gClient.ready(function (aType, aTraits) {
     is(aType, "browser", "Root actor should identify itself as a browser.");
     get_tab();
   });
 }
rename from browser/devtools/debugger/test/browser/head.js
rename to browser/devtools/debugger/test/head.js
--- a/browser/devtools/debugger/test/browser/head.js
+++ b/browser/devtools/debugger/test/head.js
@@ -4,21 +4,21 @@
 "use strict";
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 Cu.import("resource:///modules/dbg-server.jsm");
 Cu.import("resource:///modules/dbg-client.jsm");
 Cu.import("resource:///modules/Services.jsm");
 
-const TAB1_URL = "http://example.com/browser/browser/devtools/debugger/test/browser/browser_dbg_tab1.html";
+const TAB1_URL = "http://example.com/browser/browser/devtools/debugger/test/browser_dbg_tab1.html";
 
-const TAB2_URL = "http://example.com/browser/browser/devtools/debugger/test/browser/browser_dbg_tab2.html";
+const TAB2_URL = "http://example.com/browser/browser/devtools/debugger/test/browser_dbg_tab2.html";
 
-const STACK_URL = "http://example.com/browser/browser/devtools/debugger/test/browser/browser_dbg_stack.html";
+const STACK_URL = "http://example.com/browser/browser/devtools/debugger/test/browser_dbg_stack.html";
 
 if (!DebuggerServer.initialized) {
   DebuggerServer.init();
   DebuggerServer.addBrowserActors();
 }
 
 waitForExplicitFinish();
 
rename from browser/devtools/debugger/test/browser/test-script-switching-01.js
rename to browser/devtools/debugger/test/test-script-switching-01.js
rename from browser/devtools/debugger/test/browser/test-script-switching-02.js
rename to browser/devtools/debugger/test/test-script-switching-02.js
rename from browser/devtools/debugger/test/browser/testactors.js
rename to browser/devtools/debugger/test/testactors.js
--- a/browser/devtools/jar.mn
+++ b/browser/devtools/jar.mn
@@ -4,17 +4,12 @@ browser.jar:
 *   content/browser/scratchpad.xul                (scratchpad/scratchpad.xul)
 *   content/browser/scratchpad.js                 (scratchpad/scratchpad.js)
     content/browser/devtools/csshtmltree.xul      (styleinspector/csshtmltree.xul)
     content/browser/devtools/cssruleview.xul      (styleinspector/cssruleview.xul)
     content/browser/devtools/styleinspector.css   (styleinspector/styleinspector.css)
     content/browser/orion.js                      (sourceeditor/orion/orion.js)
     content/browser/orion.css                     (sourceeditor/orion/orion.css)
     content/browser/orion-mozilla.css             (sourceeditor/orion/mozilla.css)
-*   content/browser/debugger.xhtml                (debugger/content/debugger.xhtml)
-*   content/browser/debugger.css                  (debugger/content/debugger.css)
-*   content/browser/debugger.js                   (debugger/content/debugger.js)
-*   content/browser/debugger-view.js              (debugger/content/debugger-view.js)
-*   content/browser/debugger-prefs.js             (debugger/content/debugger-prefs.js)
-*   content/browser/debugger-overlay.js           (debugger/content/debugger-overlay.js)
-*   content/browser/debugger-overlay.xul          (debugger/content/debugger-overlay.xul)
-%   overlay chrome://browser/content/browser.xul  chrome://browser/content/debugger-overlay.xul
-
+*   content/browser/debugger.xhtml                (debugger/debugger.xhtml)
+    content/browser/debugger.css                  (debugger/debugger.css)
+    content/browser/debugger.js                   (debugger/debugger.js)
+    content/browser/debugger-view.js              (debugger/debugger-view.js)
--- a/browser/locales/en-US/chrome/browser/devtools/debugger.dtd
+++ b/browser/locales/en-US/chrome/browser/devtools/debugger.dtd
@@ -1,34 +1,34 @@
 <!-- LOCALIZATION NOTE : FILE This file contains the Script Debugger strings -->
-<!-- LOCALIZATION NOTE : FILE Do not translate menuKey -->
+<!-- LOCALIZATION NOTE : FILE Do not translate commandkey -->
 
-<!-- LOCALIZATION NOTE (applicationMenuLabel): This is the label for the
+<!-- LOCALIZATION NOTE (debuggerMenu.label): This is the label for the
   -  application menu item that opens the debugger UI. -->
-<!ENTITY applicationMenuLabel        "Script Debugger">
-<!ENTITY contextMenuLabel            "Script Debugger">
+<!ENTITY debuggerMenu.label          "Script Debugger">
 
-<!-- LOCALIZATION NOTE (menuKey): This is the shortcut key that launches the
-  -  debugger UI. Do not translate this one! -->
-<!ENTITY menuKey                     "I">
+<!-- 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 (closeButton): This is the label for the button that
-  -  closes the debugger UI. -->
-<!ENTITY closeButton                 "Close">
+<!-- LOCALIZATION NOTE (debuggerUI.closeButton): This is the label for the
+  -  button that closes the debugger UI. -->
+<!ENTITY debuggerUI.closeButton      "Close">
 
-<!-- LOCALIZATION NOTE (resumeButton): This is the label for the button that
-  -  resumes the debugger, after it has reached a paused state. In a paused
-  - state the debugger can be used to inspect stack frames, local variables,
-  - etc. -->
-<!ENTITY resumeButton                "Resume">
+<!-- LOCALIZATION NOTE (debuggerUI.resumeButton): This is the label for the
+  -  button that resumes the debugger, after it has reached a paused state. In
+  -  a paused state the debugger can be used to inspect stack frames, local,
+  -  variables etc. -->
+<!ENTITY debuggerUI.resumeButton     "Resume">
+
+<!-- LOCALIZATION NOTE (debuggerUI.stackTitle): This is the label for the
+  -  widget that displays the call stack frames in the debugger. -->
+<!ENTITY debuggerUI.stackTitle       "Call stack">
 
-<!-- LOCALIZATION NOTE (stackTitle): This is the label for the widget that
-  -  displays the call stack frames in the debugger. -->
-<!ENTITY stackTitle                  "Call stack">
+<!-- LOCALIZATION NOTE (debuggerUI.scriptTitle): This is the label for the
+  -  widget that displays the source code for the script that is currently
+  -  being inspected in the debugger. -->
+<!ENTITY debuggerUI.scriptTitle      "Script">
 
-<!-- LOCALIZATION NOTE (scriptTitle): This is the label for the widget that
-  -  displays the source code for the script that is currently being inspected
-  - in the debugger. -->
-<!ENTITY scriptTitle                 "Script">
-
-<!-- LOCALIZATION NOTE (propertiesTitle): This is the label for the widget that
-  -  displays the variables in the various available scopes in the debugger. -->
-<!ENTITY propertiesTitle             "Scope variables">
+<!-- LOCALIZATION NOTE (debuggerUI.propertiesTitle): This is the label for the
+  -  widget that displays the variables in the various available scopes in the
+  -  debugger. -->
+<!ENTITY debuggerUI.propertiesTitle  "Scope variables">