Merge mozilla-central to mozilla-inbound
authorEhsan Akhgari <ehsan@mozilla.com>
Fri, 30 Nov 2012 13:20:05 -0500
changeset 114623 d188dbaa49b1ec2d7fc560635f5169726cf2b3eb
parent 114617 fc50a21277387ea331fd6241e0722aaab4398301 (current diff)
parent 114622 d2fbc67f69f54f096db0f202fa862c6e53284d0f (diff)
child 114624 743f9704f2337035e978c65efeeaca63c22eb42a
push id18880
push usereakhgari@mozilla.com
push dateFri, 30 Nov 2012 18:20:10 +0000
treeherdermozilla-inbound@d188dbaa49b1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone20.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to mozilla-inbound
browser/base/content/nsContextMenu.js
browser/devtools/debugger/test/browser_dbg_panesize.js
browser/devtools/highlighter/CmdInspect.jsm
browser/devtools/highlighter/Makefile.in
browser/devtools/highlighter/highlighter.jsm
browser/devtools/highlighter/inspector.jsm
browser/devtools/highlighter/test/Makefile.in
browser/devtools/highlighter/test/browser_inspector_breadcrumbs.html
browser/devtools/highlighter/test/browser_inspector_breadcrumbs.js
browser/devtools/highlighter/test/browser_inspector_bug_566084_location_changed.js
browser/devtools/highlighter/test/browser_inspector_bug_665880.js
browser/devtools/highlighter/test/browser_inspector_bug_672902_keyboard_shortcuts.js
browser/devtools/highlighter/test/browser_inspector_bug_674871.js
browser/devtools/highlighter/test/browser_inspector_bug_690361.js
browser/devtools/highlighter/test/browser_inspector_bug_699308_iframe_navigation.js
browser/devtools/highlighter/test/browser_inspector_changes.js
browser/devtools/highlighter/test/browser_inspector_cmd_inspect.html
browser/devtools/highlighter/test/browser_inspector_cmd_inspect.js
browser/devtools/highlighter/test/browser_inspector_destroyselection.html
browser/devtools/highlighter/test/browser_inspector_destroyselection.js
browser/devtools/highlighter/test/browser_inspector_highlighter.js
browser/devtools/highlighter/test/browser_inspector_highlighter_autohide.js
browser/devtools/highlighter/test/browser_inspector_iframeTest.js
browser/devtools/highlighter/test/browser_inspector_infobar.js
browser/devtools/highlighter/test/browser_inspector_initialization.js
browser/devtools/highlighter/test/browser_inspector_invalidate.js
browser/devtools/highlighter/test/browser_inspector_keybindings.js
browser/devtools/highlighter/test/browser_inspector_menu.js
browser/devtools/highlighter/test/browser_inspector_pseudoClass_menu.js
browser/devtools/highlighter/test/browser_inspector_pseudoclass_lock.js
browser/devtools/highlighter/test/browser_inspector_ruleviewstore.js
browser/devtools/highlighter/test/browser_inspector_scrolling.js
browser/devtools/highlighter/test/browser_inspector_sidebarstate.js
browser/devtools/highlighter/test/browser_inspector_tab_switch.js
browser/devtools/highlighter/test/browser_inspector_treeSelection.js
browser/devtools/highlighter/test/browser_inspector_tree_height.js
browser/devtools/highlighter/test/head.js
browser/devtools/highlighter/test/helpers.js
browser/devtools/layoutview/LayoutView.jsm
browser/devtools/tilt/test/browser_tilt_04_initialization-key.js
browser/devtools/webconsole/test/browser_webconsole_bug_581231_close_button.js
browser/devtools/webconsole/test/browser_webconsole_bug_601909_remember_height.js
browser/devtools/webconsole/test/browser_webconsole_bug_663443_panel_title.js
browser/devtools/webconsole/test/browser_webconsole_menustatus.js
browser/devtools/webconsole/test/browser_webconsole_position_ui.js
browser/devtools/webconsole/test/browser_webconsole_window_zombie.js
browser/locales/en-US/chrome/browser/browser.dtd
browser/themes/gnomestripe/devtools/layout-background.png
browser/themes/gnomestripe/devtools/layout-buttons.png
browser/themes/gnomestripe/devtools/treepanel-button.png
browser/themes/pinstripe/devtools/layout-background.png
browser/themes/pinstripe/devtools/layout-buttons.png
browser/themes/pinstripe/devtools/treepanel-button.png
browser/themes/winstripe/devtools/layout-background.png
browser/themes/winstripe/devtools/layout-buttons.png
browser/themes/winstripe/devtools/treepanel-button.png
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -998,21 +998,26 @@ pref("services.sync.prefs.sync.xpinstall
 pref("devtools.errorconsole.enabled", false);
 
 // Developer toolbar and GCLI preferences
 pref("devtools.toolbar.enabled", true);
 pref("devtools.toolbar.visible", false);
 pref("devtools.gcli.allowSet", false);
 pref("devtools.commands.dir", "");
 
+// Toolbox preferences
+pref("devtools.toolbox.footer.height", 250);
+pref("devtools.toolbox.sidebar.width", 500);
+pref("devtools.toolbox.host", "bottom");
+pref("devtools.toolbox.selectedTool", "webconsole");
+pref("devtools.toolbox.toolbarSpec", '["tilt toggle","scratchpad","resize toggle"]');
+pref("devtools.toolbox.sideEnabled", false);
+
 // Enable the Inspector
 pref("devtools.inspector.enabled", true);
-pref("devtools.inspector.htmlHeight", 112);
-pref("devtools.inspector.htmlPanelOpen", false);
-pref("devtools.inspector.sidebarOpen", false);
 pref("devtools.inspector.activeSidebar", "ruleview");
 pref("devtools.inspector.markupPreview", false);
 
 // Enable the Layout View
 pref("devtools.layoutview.enabled", true);
 pref("devtools.layoutview.open", false);
 
 // Enable the Responsive UI tool
@@ -1034,27 +1039,21 @@ pref("devtools.debugger.ui.win-width", 9
 pref("devtools.debugger.ui.win-height", 400);
 pref("devtools.debugger.ui.stackframes-width", 200);
 pref("devtools.debugger.ui.variables-width", 300);
 pref("devtools.debugger.ui.panes-visible-on-startup", false);
 pref("devtools.debugger.ui.variables-sorting-enabled", true);
 pref("devtools.debugger.ui.variables-non-enum-visible", true);
 pref("devtools.debugger.ui.variables-searchbox-visible", false);
 
-// Enable the style inspector
-pref("devtools.styleinspector.enabled", true);
-
 // Enable the Tilt inspector
 pref("devtools.tilt.enabled", true);
 pref("devtools.tilt.intro_transition", true);
 pref("devtools.tilt.outro_transition", true);
 
-// Enable the rules view
-pref("devtools.ruleview.enabled", true);
-
 // Enable the Scratchpad tool.
 pref("devtools.scratchpad.enabled", true);
 
 // The maximum number of recently-opened files stored.
 // Setting this preference to 0 will not clear any recent files, but rather hide
 // the 'Open Recent'-menu.
 pref("devtools.scratchpad.recentFilesMax", 10);
 
@@ -1069,27 +1068,16 @@ pref("devtools.chrome.enabled", false);
 pref("devtools.gcli.hideIntro", false);
 
 // How eager are we to show help: never=1, sometimes=2, always=3
 pref("devtools.gcli.eagerHelper", 2);
 
 // Do we allow the 'pref set' command
 pref("devtools.gcli.allowSet", false);
 
-// The last Web Console height. This is initially 0 which means that the Web
-// Console will use the default height next time it shows.
-// Change to -1 if you do not want the Web Console to remember its last height.
-pref("devtools.hud.height", 0);
-
-// Remember the Web Console position. Possible values:
-//   above - above the web page,
-//   below - below the web page,
-//   window - in a separate window/popup panel.
-pref("devtools.webconsole.position", "below");
-
 // Remember the Web Console filters
 pref("devtools.webconsole.filter.network", true);
 pref("devtools.webconsole.filter.networkinfo", true);
 pref("devtools.webconsole.filter.csserror", true);
 pref("devtools.webconsole.filter.cssparser", true);
 pref("devtools.webconsole.filter.exception", true);
 pref("devtools.webconsole.filter.jswarn", true);
 pref("devtools.webconsole.filter.error", true);
--- a/browser/base/content/browser-appmenu.inc
+++ b/browser/base/content/browser-appmenu.inc
@@ -145,30 +145,37 @@
                       label="&printSetupCmd.label;"
                       command="cmd_pageSetup"/>
           </menupopup>
       </splitmenu>
       <menuseparator class="appmenu-menuseparator"/>
       <menu id="appmenu_webDeveloper"
             label="&appMenuWebDeveloper.label;">
         <menupopup id="appmenu_webDeveloper_popup">
-          <menuitem id="appmenu_devToolbar" observes="devtoolsMenuBroadcaster_DevToolbar"/>
-          <menuitem id="appmenu_webConsole" observes="devtoolsMenuBroadcaster_WebConsole"/>
-          <menuitem id="appmenu_remoteWebConsole" observes="devtoolsMenuBroadcaster_RemoteWebConsole"/>
-          <menuitem id="appmenu_pageinspect" observes="devtoolsMenuBroadcaster_Inspect"/>
-          <menuitem id="appmenu_responsiveUI" observes="devtoolsMenuBroadcaster_ResponsiveUI"/>
-          <menuitem id="appmenu_debugger" observes="devtoolsMenuBroadcaster_Debugger"/>
-          <menuitem id="appmenu_remoteDebugger" observes="devtoolsMenuBroadcaster_RemoteDebugger"/>
-          <menuitem id="appmenu_chromeDebugger" observes="devtoolsMenuBroadcaster_ChromeDebugger"/>
-          <menuitem id="appmenu_scratchpad" observes="devtoolsMenuBroadcaster_Scratchpad"/>
-          <menuitem id="appmenu_styleeditor" observes="devtoolsMenuBroadcaster_StyleEditor"/>
-          <menuitem id="appmenu_pageSource" observes="devtoolsMenuBroadcaster_PageSource"/>
-          <menuitem id="appmenu_errorConsole" observes="devtoolsMenuBroadcaster_ErrorConsole"/>
+          <menuitem id="appmenu_devToolbox"
+                    observes="devtoolsMenuBroadcaster_DevToolbox"/>
+          <menuseparator id="appmenu_devtools_separator"/>
+          <menuitem id="appmenu_devToolbar"
+                    observes="devtoolsMenuBroadcaster_DevToolbar"/>
+          <menuitem id="appmenu_chromeDebugger"
+                    observes="devtoolsMenuBroadcaster_ChromeDebugger"/>
+          <menuitem id="appmenu_responsiveUI"
+                    observes="devtoolsMenuBroadcaster_ResponsiveUI"/>
+          <menuitem id="appmenu_scratchpad"
+                    observes="devtoolsMenuBroadcaster_Scratchpad"/>
+          <menuitem id="appmenu_pageSource"
+                    observes="devtoolsMenuBroadcaster_PageSource"/>
+          <menuitem id="appmenu_errorConsole"
+                    observes="devtoolsMenuBroadcaster_ErrorConsole"/>
+          <menuseparator id="appmenu_devToolsConnectSeparator"/>
+          <menuitem id="appmenu_devtools_connect"
+                    observes="devtoolsMenuBroadcaster_connect"/>
           <menuseparator id="appmenu_devToolsEndSeparator"/>
-          <menuitem id="appmenu_getMoreDevtools" observes="devtoolsMenuBroadcaster_GetMoreTools"/>
+          <menuitem id="appmenu_getMoreDevtools"
+                    observes="devtoolsMenuBroadcaster_GetMoreTools"/>
           <menuseparator/>
 #define ID_PREFIX appmenu_developer_
 #define OMIT_ACCESSKEYS
 #include browser-charsetmenu.inc
 #undef ID_PREFIX
 #undef OMIT_ACCESSKEYS
           <menuitem label="&goOfflineCmd.label;"
                     type="checkbox"
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -559,30 +559,44 @@
                         observes="sync-syncnow-state"
                         oncommand="gSyncUI.doSync(event);"/>
 #endif
               <menuseparator id="devToolsSeparator"/>
               <menu id="webDeveloperMenu"
                     label="&webDeveloperMenu.label;"
                     accesskey="&webDeveloperMenu.accesskey;">
                 <menupopup id="menuWebDeveloperPopup">
-                  <menuitem id="menu_devToolbar" observes="devtoolsMenuBroadcaster_DevToolbar" accesskey="&devToolbarMenu.accesskey;"/>
-                  <menuitem id="webConsole" observes="devtoolsMenuBroadcaster_WebConsole" accesskey="&webConsoleCmd.accesskey;"/>
-                  <menuitem id="menu_remoteWebConsole" observes="devtoolsMenuBroadcaster_RemoteWebConsole"/>
-                  <menuitem id="menu_pageinspect" observes="devtoolsMenuBroadcaster_Inspect" accesskey="&inspectMenu.accesskey;"/>
-                  <menuitem id="menu_responsiveUI" observes="devtoolsMenuBroadcaster_ResponsiveUI" accesskey="&responsiveDesignTool.accesskey;"/>
-                  <menuitem id="menu_debugger" observes="devtoolsMenuBroadcaster_Debugger" accesskey="&debuggerMenu.accesskey;"/>
-                  <menuitem id="menu_remoteDebugger" observes="devtoolsMenuBroadcaster_RemoteDebugger"/>
-                  <menuitem id="menu_chromeDebugger" observes="devtoolsMenuBroadcaster_ChromeDebugger"/>
-                  <menuitem id="menu_scratchpad" observes="devtoolsMenuBroadcaster_Scratchpad" accesskey="&scratchpad.accesskey;"/>
-                  <menuitem id="menu_styleeditor" observes="devtoolsMenuBroadcaster_StyleEditor" accesskey="&styleeditor.accesskey;"/>
-                  <menuitem id="menu_pageSource" observes="devtoolsMenuBroadcaster_PageSource" accesskey="&pageSourceCmd.accesskey;"/>
-                  <menuitem id="javascriptConsole" observes="devtoolsMenuBroadcaster_ErrorConsole" accesskey="&errorConsoleCmd.accesskey;"/>
+                  <menuitem id="menu_devToolbox"
+                            observes="devtoolsMenuBroadcaster_DevToolbox"
+                            accesskey="&devToolbox.accesskey;"/>
+                  <menuseparator id="menu_devtools_separator"/>
+                  <menuitem id="menu_devToolbar"
+                            observes="devtoolsMenuBroadcaster_DevToolbar"
+                            accesskey="&devToolbarMenu.accesskey;"/>
+                  <menuitem id="menu_chromeDebugger"
+                            observes="devtoolsMenuBroadcaster_ChromeDebugger"/>
+                  <menuitem id="menu_responsiveUI"
+                            observes="devtoolsMenuBroadcaster_ResponsiveUI"
+                            accesskey="&responsiveDesignTool.accesskey;"/>
+                  <menuitem id="menu_scratchpad"
+                            observes="devtoolsMenuBroadcaster_Scratchpad"
+                            accesskey="&scratchpad.accesskey;"/>
+                  <menuitem id="menu_pageSource"
+                            observes="devtoolsMenuBroadcaster_PageSource"
+                            accesskey="&pageSourceCmd.accesskey;"/>
+                  <menuitem id="javascriptConsole"
+                            observes="devtoolsMenuBroadcaster_ErrorConsole"
+                            accesskey="&errorConsoleCmd.accesskey;"/>
+                  <menuseparator id="menu_devToolsConnectSeparator"/>
+                  <menuitem id="menu_devtools_connect"
+                            observes="devtoolsMenuBroadcaster_connect"/>
                   <menuseparator id="devToolsEndSeparator"/>
-                  <menuitem id="getMoreDevtools" observes="devtoolsMenuBroadcaster_GetMoreTools" accesskey="&getMoreDevtoolsCmd.accesskey;"/>
+                  <menuitem id="getMoreDevtools"
+                            observes="devtoolsMenuBroadcaster_GetMoreTools"
+                            accesskey="&getMoreDevtoolsCmd.accesskey;"/>
                 </menupopup>
               </menu>
               <menuitem id="menu_pageInfo"
                         accesskey="&pageInfoCmd.accesskey;"
                         label="&pageInfoCmd.label;"
 #ifndef XP_WIN
                         key="key_viewInfo"
 #endif
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -83,29 +83,25 @@
     <command id="cmd_fullZoomReduce"  oncommand="FullZoom.reduce()"/>
     <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:DevToolbox" oncommand="gDevTools.toggleToolboxCommand(gBrowser);"/>
     <command id="Tools:DevToolbar" oncommand="DeveloperToolbar.toggle();" disabled="true" hidden="true"/>
     <command id="Tools:DevToolbarFocus" oncommand="DeveloperToolbar.focusToggle();" disabled="true"/>
-    <command id="Tools:WebConsole" oncommand="HUDConsoleUI.toggleHUD();"/>
-    <command id="Tools:RemoteWebConsole" oncommand="HUDConsoleUI.toggleRemoteHUD();" disabled="true" hidden="true"/>
-    <command id="Tools:Inspect" oncommand="InspectorUI.toggleInspectorUI();"/>
-    <command id="Tools:Debugger" oncommand="DebuggerUI.toggleDebugger();" disabled="true" hidden="true"/>
-    <command id="Tools:RemoteDebugger" oncommand="DebuggerUI.toggleRemoteDebugger();" disabled="true" hidden="true"/>
     <command id="Tools:ChromeDebugger" oncommand="DebuggerUI.toggleChromeDebugger();" disabled="true" hidden="true"/>
     <command id="Tools:Scratchpad" oncommand="Scratchpad.openScratchpad();" disabled="true" hidden="true"/>
-    <command id="Tools:StyleEditor" oncommand="StyleEditor.toggle();" disabled="true" hidden="true"/>
     <command id="Tools:ResponsiveUI" oncommand="ResponsiveUI.toggle();" disabled="true" hidden="true"/>
     <command id="Tools:Addons" oncommand="BrowserOpenAddonsMgr();"/>
     <command id="Tools:ErrorConsole" oncommand="toJavaScriptConsole()" disabled="true" hidden="true"/>
+    <command id="Tools:DevToolsConnect" oncommand="DevToolsXULCommands.openConnectScreen(gBrowser)"/>
     <command id="Tools:Sanitize"
      oncommand="Cc['@mozilla.org/browser/browserglue;1'].getService(Ci.nsIBrowserGlue).sanitize(window);"/>
     <command id="Tools:PrivateBrowsing"
 #ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
       oncommand="OpenBrowserWindow({private: true});"/>
 #else
       oncommand="gPrivateBrowsingUI.toggleMode();"/>
 #endif
@@ -123,37 +119,16 @@
 
   <commandset id="placesCommands">
     <command id="Browser:ShowAllBookmarks"
              oncommand="PlacesCommandHook.showPlacesOrganizer('AllBookmarks');"/>
     <command id="Browser:ShowAllHistory"
              oncommand="PlacesCommandHook.showPlacesOrganizer('History');"/>
   </commandset>
 
-  <commandset id="inspectorCommands">
-    <command id="Inspector:Inspect"
-             oncommand="InspectorUI.toggleInspection();"/>
-    <command id="Inspector:Sidebar"
-             oncommand="InspectorUI.toggleSidebar();"/>
-    <command id="Inspector:Tilt"
-             oncommand="Tilt.initialize();"/>
-    <command id="Inspector:HTMLPanel"
-             oncommand="InspectorUI.toggleHTMLPanel();"/>
-    <command id="Inspector:CopyInner"
-             oncommand="InspectorUI.copyInnerHTML();"/>
-    <command id="Inspector:CopyOuter"
-             oncommand="InspectorUI.copyOuterHTML();"/>
-    <command id="Inspector:DeleteNode"
-             oncommand="InspectorUI.deleteNode();"/>
-    <command id="Inspector:ToggleVeil"
-             oncommand="InspectorUI.toggleVeil();"/>
-    <command id="Inspector:ToggleInfobar"
-             oncommand="InspectorUI.toggleInfobar();"/>
-  </commandset>
-
   <broadcasterset id="mainBroadcasterSet">
     <broadcaster id="viewBookmarksSidebar" autoCheck="false" label="&bookmarksButton.label;"
                  type="checkbox" group="sidebar" sidebarurl="chrome://browser/content/bookmarks/bookmarksPanel.xul"
                  oncommand="toggleSidebar('viewBookmarksSidebar');"/>
 
     <!-- for both places and non-places, the sidebar lives at
          chrome://browser/content/history/history-panel.xul so there are no
          problems when switching between versions -->
@@ -192,71 +167,51 @@
     <broadcaster id="sync-setup-state"/>
     <broadcaster id="sync-syncnow-state"/>
 #endif
     <broadcaster id="workOfflineMenuitemState"/>
     <broadcaster id="socialSidebarBroadcaster" hidden="true"/>
     <broadcaster id="socialActiveBroadcaster" hidden="true"/>
 
     <!-- DevTools broadcasters -->
+    <broadcaster id="devtoolsMenuBroadcaster_DevToolbox"
+                 label="&devToolbarToolsButton.label;"
+                 type="checkbox" autocheck="false"
+                 command="Tools:DevToolbox"/>
     <broadcaster id="devtoolsMenuBroadcaster_DevToolbar"
                  label="&devToolbarMenu.label;"
                  type="checkbox" autocheck="false"
                  command="Tools:DevToolbar"
                  key="key_devToolbar"/>
-    <broadcaster id="devtoolsMenuBroadcaster_WebConsole"
-                 label="&webConsoleCmd.label;"
-                 type="checkbox" autocheck="false"
-                 key="key_webConsole"
-                 command="Tools:WebConsole"/>
-    <broadcaster id="devtoolsMenuBroadcaster_RemoteWebConsole"
-                 label="&remoteWebConsoleCmd.label;"
-                 type="checkbox" autocheck="false"
-                 command="Tools:RemoteWebConsole"/>
-    <broadcaster id="devtoolsMenuBroadcaster_Inspect"
-                 label="&inspectMenu.label;"
-                 type="checkbox" autocheck="false"
-                 command="Tools:Inspect"
-                 key="key_inspect"/>
-    <broadcaster id="devtoolsMenuBroadcaster_Debugger"
-                 label="&debuggerMenu.label2;"
-                 type="checkbox" autocheck="false"
-                 command="Tools:Debugger"
-                 key="key_debugger"/>
-    <broadcaster id="devtoolsMenuBroadcaster_RemoteDebugger"
-                 label="&remoteDebuggerMenu.label;"
-                 command="Tools:RemoteDebugger"/>
     <broadcaster id="devtoolsMenuBroadcaster_ChromeDebugger"
                  label="&chromeDebuggerMenu.label;"
                  command="Tools:ChromeDebugger"/>
     <broadcaster id="devtoolsMenuBroadcaster_Scratchpad"
                  label="&scratchpad.label;"
                  command="Tools:Scratchpad"
                  key="key_scratchpad"/>
-    <broadcaster id="devtoolsMenuBroadcaster_StyleEditor"
-                 label="&styleeditor.label;"
-                 type="checkbox" autocheck="false"
-                 command="Tools:StyleEditor"
-                 key="key_styleeditor"/>
     <broadcaster id="devtoolsMenuBroadcaster_ResponsiveUI"
                  label="&responsiveDesignTool.label;"
                  type="checkbox" autocheck="false"
                  command="Tools:ResponsiveUI"
                  key="key_responsiveUI"/>
     <broadcaster id="devtoolsMenuBroadcaster_PageSource"
                  label="&pageSourceCmd.label;"
                  key="key_viewSource"
                  command="View:PageSource"/>
     <broadcaster id="devtoolsMenuBroadcaster_ErrorConsole"
                  label="&errorConsoleCmd.label;"
                  key="key_errorConsole"
                  command="Tools:ErrorConsole"/>
     <broadcaster id="devtoolsMenuBroadcaster_GetMoreTools"
                  label="&getMoreDevtoolsCmd.label;"
                  oncommand="openUILinkIn('https://addons.mozilla.org/firefox/collections/mozilla/webdeveloper/', 'tab');"/>
+    <broadcaster id="devtoolsMenuBroadcaster_connect"
+                 label="&devtoolsConnect.label;"
+                 command="Tools:DevToolsConnect"/>
 
     <!-- SocialAPI broadcasters -->
     <broadcaster id="socialBroadcaster_userDetails"
                  notLoggedInLabel="&social.notLoggedIn.label;"/>
   </broadcasterset>
 
   <keyset id="mainKeyset">
     <key id="key_newNavigator"
@@ -268,17 +223,17 @@
          modifiers="accel"/>
 #ifndef XP_MACOSX
     <key id="focusURLBar2" key="&urlbar.accesskey;" command="Browser:OpenLocation"
          modifiers="alt"/>
 #endif
 
 #
 # Search Command Key Logic works like this:
-# 
+#
 # Unix: Ctrl+K (cross platform binding)
 #       Ctrl+J (in case of emacs Ctrl-K conflict)
 # Mac:  Cmd+K (cross platform binding)
 #       Cmd+Opt+F (platform convention)
 # Win:  Ctrl+K (cross platform binding)
 #       Ctrl+E (IE compat)
 #
 # We support Ctrl+K on all platforms now and advertise it in the menu since it is
@@ -300,48 +255,25 @@
     <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;" command="Tools:ErrorConsole" modifiers="accel,shift"/>
     <key id="key_devToolbar" keycode="&devToolbar.keycode;" modifiers="shift"
          keytext="&devToolbar.keytext;" command="Tools:DevToolbarFocus"/>
-    <key id="key_webConsole" key="&webConsoleCmd.commandkey;" oncommand="HUDConsoleUI.toggleHUD();"
-#ifdef XP_MACOSX
-        modifiers="accel,alt"
-#else
-        modifiers="accel,shift"
-#endif
-    />
-    <key id="key_debugger" key="&debuggerMenu.commandkey;" command="Tools:Debugger"
-#ifdef XP_MACOSX
-        modifiers="accel,alt"
-#else
-        modifiers="accel,shift"
-#endif
-    />
-    <key id="key_inspect" key="&inspectMenu.commandkey;" command="Inspector:Inspect"
-#ifdef XP_MACOSX
-        modifiers="accel,alt"
-#else
-        modifiers="accel,shift"
-#endif
-    />
     <key id="key_responsiveUI" key="&responsiveDesignTool.commandkey;" command="Tools:ResponsiveUI"
 #ifdef XP_MACOSX
         modifiers="accel,alt"
 #else
         modifiers="accel,shift"
 #endif
     />
     <key id="key_scratchpad" keycode="&scratchpad.keycode;" modifiers="shift"
          keytext="&scratchpad.keytext;" command="Tools:Scratchpad"/>
-    <key id="key_styleeditor" keycode="&styleeditor.keycode;" modifiers="shift"
-         keytext="&styleeditor.keytext;" command="Tools:StyleEditor"/>
     <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"
          key="&undoCmd.key;"
          modifiers="accel"/>
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -557,20 +557,16 @@ statuspanel[inactive][previoustype=overL
 }
 
 .statuspanel-inner {
   height: 3em;
   width: 100%;
   -moz-box-align: end;
 }
 
-.styleInspector {
-  min-width: 350px;
-}
-
 .panel-inner-arrowcontentfooter[footertype="promobox"] {
   -moz-binding: url("chrome://browser/content/urlbarBindings.xml#promobox");
 }
 
 /* tabview menus */
 .tabview-menuitem {
   max-width: 32em;
 }
@@ -588,32 +584,26 @@ html|*#gcli-output-frame,
 }
 
 .gclitoolbar-input-node,
 .gclitoolbar-complete-node,
 .gclitoolbar-prompt {
   direction: ltr;
 }
 
-#developer-toolbar-webconsole[error-count] > .toolbarbutton-icon {
+#developer-toolbar-toolbox-button[error-count] > .toolbarbutton-icon {
   display: none;
 }
 
-#developer-toolbar-webconsole[error-count]:before {
+#developer-toolbar-toolbox-button[error-count]:before {
   content: attr(error-count);
   display: -moz-box;
   -moz-box-pack: center;
 }
 
-/* We don't show the Style Editor button in the developer toolbar for now.
-   See bug 771203 */
-#developer-toolbar-styleeditor {
-  display: none;
-}
-
 /* Responsive Mode */
 
 .browserContainer[responsivemode] {
   overflow: auto;
 }
 
 .devtools-responsiveui-toolbar:-moz-locale-dir(rtl) {
   -moz-box-pack: end;
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -110,38 +110,25 @@ XPCOMUtils.defineLazyGetter(this, "Popup
 });
 
 XPCOMUtils.defineLazyGetter(this, "DeveloperToolbar", function() {
   let tmp = {};
   Cu.import("resource:///modules/devtools/DeveloperToolbar.jsm", tmp);
   return new tmp.DeveloperToolbar(window, document.getElementById("developer-toolbar"));
 });
 
-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);
 });
 
-XPCOMUtils.defineLazyGetter(this, "Tilt", function() {
-  let tmp = {};
-  Cu.import("resource:///modules/devtools/Tilt.jsm", tmp);
-  return new tmp.Tilt(window);
-});
-
 XPCOMUtils.defineLazyModuleGetter(this, "Social",
   "resource:///modules/Social.jsm");
 
-
 XPCOMUtils.defineLazyModuleGetter(this, "PageThumbs",
   "resource:///modules/PageThumbs.jsm");
 
 #ifdef MOZ_SAFE_BROWSING
 XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
   "resource://gre/modules/SafeBrowsing.jsm");
 #endif
 
@@ -1423,36 +1410,16 @@ var gBrowserInit = {
       document.getElementById("Tools:DevToolbarFocus").removeAttribute("disabled");
 
       // Show the toolbar if it was previously visible
       if (gPrefService.getBoolPref("devtools.toolbar.visible")) {
         DeveloperToolbar.show(false);
       }
     }
 
-    // Enable Debugger?
-    let enabled = gPrefService.getBoolPref("devtools.debugger.enabled");
-    if (enabled) {
-      let cmd = document.getElementById("Tools:Debugger");
-      cmd.removeAttribute("disabled");
-      cmd.removeAttribute("hidden");
-    }
-
-    // Enable Remote Debugger?
-    let enabled = gPrefService.getBoolPref("devtools.debugger.remote-enabled");
-    if (enabled) {
-      let cmd = document.getElementById("Tools:RemoteDebugger");
-      cmd.removeAttribute("disabled");
-      cmd.removeAttribute("hidden");
-
-      cmd = document.getElementById("Tools:RemoteWebConsole");
-      cmd.removeAttribute("disabled");
-      cmd.removeAttribute("hidden");
-    }
-
     // Enable Chrome Debugger?
     let enabled = gPrefService.getBoolPref("devtools.chrome.enabled") &&
                   gPrefService.getBoolPref("devtools.debugger.chrome-enabled") &&
                   gPrefService.getBoolPref("devtools.debugger.remote-enabled");
     if (enabled) {
       let cmd = document.getElementById("Tools:ChromeDebugger");
       cmd.removeAttribute("disabled");
       cmd.removeAttribute("hidden");
@@ -1471,24 +1438,16 @@ var gBrowserInit = {
     // Enable Scratchpad in the UI, if the preference allows this.
     let scratchpadEnabled = gPrefService.getBoolPref(Scratchpad.prefEnabledName);
     if (scratchpadEnabled) {
       let cmd = document.getElementById("Tools:Scratchpad");
       cmd.removeAttribute("disabled");
       cmd.removeAttribute("hidden");
     }
 
-    // Enable Style Editor?
-    let styleEditorEnabled = gPrefService.getBoolPref(StyleEditor.prefEnabledName);
-    if (styleEditorEnabled) {
-      let cmd = document.getElementById("Tools:StyleEditor");
-      cmd.removeAttribute("disabled");
-      cmd.removeAttribute("hidden");
-    }
-
 #ifdef MENUBAR_CAN_AUTOHIDE
     // If the user (or the locale) hasn't enabled the top-level "Character
     // Encoding" menu via the "browser.menu.showCharacterEncoding" preference,
     // hide it.
     if ("true" != gPrefService.getComplexValue("browser.menu.showCharacterEncoding",
                                                Ci.nsIPrefLocalizedString).data)
       document.getElementById("appmenu_charsetMenu").hidden = true;
 #endif
@@ -1496,16 +1455,19 @@ var gBrowserInit = {
     // Enable Responsive UI?
     let responsiveUIEnabled = gPrefService.getBoolPref("devtools.responsiveUI.enabled");
     if (responsiveUIEnabled) {
       let cmd = document.getElementById("Tools:ResponsiveUI");
       cmd.removeAttribute("disabled");
       cmd.removeAttribute("hidden");
     }
 
+    // Add Devtools menuitems and listeners
+    gDevTools.registerBrowserWindow(window);
+
     let appMenuButton = document.getElementById("appmenu-button");
     let appMenuPopup = document.getElementById("appmenu-popup");
     if (appMenuButton && appMenuPopup) {
       let appMenuOpening = null;
       appMenuButton.addEventListener("mousedown", function(event) {
         if (event.button == 0)
           appMenuOpening = new Date();
       }, false);
@@ -1538,18 +1500,17 @@ var gBrowserInit = {
 
   onUnload: function() {
     // In certain scenarios it's possible for unload to be fired before onload,
     // (e.g. if the window is being closed after browser.js loads but before the
     // load completes). In that case, there's nothing to do here.
     if (!gStartupRan)
       return;
 
-    if (!__lookupGetter__("InspectorUI"))
-      InspectorUI.destroy();
+    gDevTools.forgetBrowserWindow(window);
 
     // First clean up services initialized in gBrowserInit.onLoad (or those whose
     // uninit methods don't depend on the services having been initialized).
     allTabs.uninit();
 
     CombinedStopReload.uninit();
 
     gGestureSupport.init(false);
@@ -1637,17 +1598,17 @@ var gBrowserInit = {
   // macBrowserOverlay
   nonBrowserWindowStartup: function() {
     // Disable inappropriate commands / submenus
     var disabledItems = ['Browser:SavePage',
                          'Browser:SendLink', 'cmd_pageSetup', 'cmd_print', 'cmd_find', 'cmd_findAgain',
                          'viewToolbarsMenu', 'viewSidebarMenuMenu', 'Browser:Reload',
                          'viewFullZoomMenu', 'pageStyleMenu', 'charsetMenu', 'View:PageSource', 'View:FullScreen',
                          'viewHistorySidebar', 'Browser:AddBookmarkAs', 'Browser:BookmarkAllTabs',
-                         'View:PageInfo', 'Tasks:InspectPage', 'Browser:ToggleTabView', 'Browser:ToggleAddonBar'];
+                         'View:PageInfo', 'Browser:ToggleTabView', 'Browser:ToggleAddonBar'];
     var element;
 
     for (let disabledItem of disabledItems) {
       element = document.getElementById(disabledItem);
       if (element)
         element.setAttribute("disabled", "true");
     }
 
@@ -7443,16 +7404,22 @@ var TabContextMenu = {
       PlacesCommandHook.updateBookmarkAllTabsCommand();
 
     // Hide "Move to Group" if it's a pinned tab.
     document.getElementById("context_tabViewMenu").hidden =
       (this.contextTab.pinned || !TabView.firstUseExperienced);
   }
 };
 
+XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
+                                  "resource:///modules/devtools/gDevTools.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "DevToolsXULCommands",
+                                  "resource:///modules/devtools/gDevTools.jsm");
+
 XPCOMUtils.defineLazyGetter(this, "HUDConsoleUI", function () {
   let tempScope = {};
   Cu.import("resource:///modules/HUDService.jsm", tempScope);
   try {
     return tempScope.HUDService.consoleUI;
   }
   catch (ex) {
     Components.utils.reportError(ex);
@@ -7539,51 +7506,16 @@ var ResponsiveUI = {
 };
 
 XPCOMUtils.defineLazyGetter(ResponsiveUI, "ResponsiveUIManager", function() {
   let tmp = {};
   Cu.import("resource:///modules/devtools/responsivedesign.jsm", tmp);
   return tmp.ResponsiveUIManager;
 });
 
-var StyleEditor = {
-  prefEnabledName: "devtools.styleeditor.enabled",
-  /**
-   * Opens the style editor. If the UI is already open, it will be focused.
-   *
-   * @param {CSSStyleSheet} [aSelectedStyleSheet] default Stylesheet.
-   * @param {Number} [aLine] Line to which the caret should be moved (one-indexed).
-   * @param {Number} [aCol] Column to which the caret should be moved (one-indexed).
-   */
-  openChrome: function SE_openChrome(aSelectedStyleSheet, aLine, aCol)
-  {
-    let contentWindow = gBrowser.selectedBrowser.contentWindow;
-    let win = this.StyleEditorManager.getEditorForWindow(contentWindow);
-    if (win) {
-      this.StyleEditorManager.selectEditor(win);
-      return win;
-    } else {
-      return this.StyleEditorManager.newEditor(contentWindow, window,
-                                               aSelectedStyleSheet, aLine, aCol);
-    }
-  },
-
-  toggle: function SE_toggle()
-  {
-    this.StyleEditorManager.toggleEditor(gBrowser.contentWindow, window);
-  }
-};
-
-XPCOMUtils.defineLazyGetter(StyleEditor, "StyleEditorManager", function() {
-  let tmp = {};
-  Cu.import("resource:///modules/devtools/StyleEditor.jsm", tmp);
-  return new tmp.StyleEditorManager(window);
-});
-
-
 XPCOMUtils.defineLazyGetter(window, "gShowPageResizers", function () {
 #ifdef XP_WIN
   // Only show resizers on Windows 2000 and XP
   let sysInfo = Components.classes["@mozilla.org/system-info;1"]
                           .getService(Components.interfaces.nsIPropertyBag2);
   return parseFloat(sysInfo.getProperty("version")) < 6;
 #else
   return false;
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -273,32 +273,16 @@
            onpopupshown="SocialFlyout.onShown()"
            onpopuphidden="SocialFlyout.onHidden()"
            side="right"
            type="arrow"
            hidden="true"
            noautofocus="true"
            position="topcenter topright"/>
 
-    <menupopup id="inspector-node-popup">
-      <menuitem id="inspectorHTMLCopyInner"
-                label="&inspectorHTMLCopyInner.label;"
-                accesskey="&inspectorHTMLCopyInner.accesskey;"
-                command="Inspector:CopyInner"/>
-      <menuitem id="inspectorHTMLCopyOuter"
-                label="&inspectorHTMLCopyOuter.label;"
-                accesskey="&inspectorHTMLCopyOuter.accesskey;"
-                command="Inspector:CopyOuter"/>
-      <menuseparator/>
-      <menuitem id="inspectorHTMLDelete"
-                label="&inspectorHTMLDelete.label;"
-                accesskey="&inspectorHTMLDelete.accesskey;"
-                command="Inspector:DeleteNode"/>
-    </menupopup>
-
     <menupopup id="toolbar-context-menu"
                onpopupshowing="onViewToolbarsPopupShowing(event);">
       <menuseparator/>
       <menuitem command="cmd_ToggleTabsOnTop"
                 type="checkbox"
                 label="&viewTabsOnTop.label;"
                 accesskey="&viewTabsOnTop.accesskey;"/>
       <menuitem command="cmd_CustomizeToolbars"
@@ -1060,29 +1044,16 @@
                   flex="1" contenttooltip="aHTMLTooltip"
                   tabcontainer="tabbrowser-tabs"
                   contentcontextmenu="contentAreaContextMenu"
                   autocompletepopup="PopupAutoComplete"
                   onclick="contentAreaClick(event, false);"/>
       <chatbar id="pinnedchats" layer="true" mousethrough="always" hidden="true"/>
       <statuspanel id="statusbar-display" inactive="true"/>
     </vbox>
-    <splitter id="devtools-side-splitter" hidden="true"/>
-    <vbox id="devtools-sidebar-box" hidden="true"
-          style="min-width: 18em; width: 22em; max-width: 42em;" persist="width">
-      <toolbar id="devtools-sidebar-toolbar"
-               class="devtools-toolbar"
-               nowindowdrag="true">
-        <spacer flex="1"/>
-        <toolbarbutton tooltiptext="&inspectSidebarCloseButton.tooltiptext;"
-                       class="devtools-closebutton"
-                       command="Inspector:Sidebar"/>
-      </toolbar>
-      <deck id="devtools-sidebar-deck" flex="1"/>
-    </vbox>
     <splitter id="social-sidebar-splitter"
               class="chromeclass-extrachrome sidebar-splitter"
               observes="socialSidebarBroadcaster"/>
     <vbox id="social-sidebar-box"
           class="chromeclass-extrachrome"
           observes="socialSidebarBroadcaster"
           persist="width">
       <browser id="social-sidebar-browser"
@@ -1111,108 +1082,35 @@
           </hbox>
           <checkbox id="full-screen-remember-decision"/>
         </vbox>
       </vbox>
     </hbox>
   </hbox>
 
   <vbox id="browser-bottombox" layer="true">
-    <toolbar id="inspector-toolbar"
-             class="devtools-toolbar"
-             nowindowdrag="true"
-             hidden="true">
-#ifdef XP_MACOSX
-      <toolbarbutton id="highlighter-closebutton"
-                     class="devtools-closebutton"
-                     oncommand="InspectorUI.closeInspectorUI(false);"
-                     tooltiptext="&inspectCloseButton.tooltiptext;"/>
-#endif
-      <toolbarbutton id="inspector-inspect-toolbutton"
-                     class="devtools-toolbarbutton"
-                     command="Inspector:Inspect"/>
-      <toolbarbutton id="inspector-treepanel-toolbutton"
-                     class="devtools-toolbarbutton"
-                     tabindex="0"
-                     aria-label="&markupButton.arialabel;"
-                     accesskey="&markupButton.accesskey;"
-                     command="Inspector:HTMLPanel"/>
-      <arrowscrollbox id="inspector-breadcrumbs"
-                      flex="1" orient="horizontal"
-                      clicktoscroll="true"/>
-      <hbox id="inspector-tools">
-        <toolbarbutton id="inspector-3D-button"
-                       class="devtools-toolbarbutton"
-                       hidden="true"
-                       label="&inspect3DViewButton.label;"
-                       accesskey="&inspect3DViewButton.accesskey;"
-                       tabindex="0"
-                       command="Inspector:Tilt"/>
-        <toolbarbutton id="inspector-style-button"
-                       class="devtools-toolbarbutton"
-                       label="&inspectStyleButton.label;"
-                       accesskey="&inspectStyleButton.accesskey;"
-                       tabindex="0"
-                       command="Inspector:Sidebar"/>
-        <!-- registered tools go here -->
-      </hbox>
-#ifndef XP_MACOSX
-      <toolbarbutton id="highlighter-closebutton"
-                     class="devtools-closebutton"
-                     oncommand="InspectorUI.closeInspectorUI(false);"
-                     tooltiptext="&inspectCloseButton.tooltiptext;"/>
-#endif
-    </toolbar>
-
     <toolbar id="developer-toolbar"
              class="devtools-toolbar"
              hidden="true">
 #ifdef XP_MACOSX
           <toolbarbutton id="developer-toolbar-closebutton"
                          class="devtools-closebutton"
                          oncommand="DeveloperToolbar.hide();"
                          tooltiptext="&devToolbarCloseButton.tooltiptext;"/>
 #endif
           <stack class="gclitoolbar-stack-node" flex="1">
             <hbox class="gclitoolbar-prompt">
               <label class="gclitoolbar-prompt-label">&#187;</label>
             </hbox>
             <hbox class="gclitoolbar-complete-node"/>
             <textbox class="gclitoolbar-input-node" rows="1"/>
           </stack>
-          <toolbarbutton id="developer-toolbar-webconsole"
-                         class="developer-toolbar-button"
-                         observes="devtoolsMenuBroadcaster_WebConsole"/>
-          <toolbarbutton id="developer-toolbar-inspector"
-                         class="developer-toolbar-button"
-                         observes="devtoolsMenuBroadcaster_Inspect"/>
-          <toolbarbutton id="developer-toolbar-styleeditor"
-                         class="developer-toolbar-button"
-                         observes="devtoolsMenuBroadcaster_StyleEditor"/>
-          <toolbarbutton id="developer-toolbar-debugger"
-                         class="developer-toolbar-button"
-                         observes="devtoolsMenuBroadcaster_Debugger"/>
-          <toolbarbutton id="developer-toolbar-other-tools"
-                         type="menu"
+          <toolbarbutton id="developer-toolbar-toolbox-button"
                          class="developer-toolbar-button"
-                         label="&devToolbarOtherToolsButton.label;">
-            <menupopup position="before_end">
-               <menuitem observes="devtoolsMenuBroadcaster_DevToolbar"/>
-               <menuitem observes="devtoolsMenuBroadcaster_ResponsiveUI"/>
-               <menuitem observes="devtoolsMenuBroadcaster_RemoteDebugger"/>
-               <menuitem observes="devtoolsMenuBroadcaster_ChromeDebugger"/>
-               <menuitem observes="devtoolsMenuBroadcaster_Scratchpad"/>
-               <menuitem observes="devtoolsMenuBroadcaster_StyleEditor"/>
-               <menuitem observes="devtoolsMenuBroadcaster_PageSource"/>
-               <menuitem observes="devtoolsMenuBroadcaster_ErrorConsole"/>
-               <menuseparator/>
-               <menuitem observes="devtoolsMenuBroadcaster_GetMoreTools"/>
-            </menupopup>
-          </toolbarbutton>
-
+                         observes="devtoolsMenuBroadcaster_DevToolbox"/>
 #ifndef XP_MACOSX
           <toolbarbutton id="developer-toolbar-closebutton"
                          class="devtools-closebutton"
                          oncommand="DeveloperToolbar.hide();"
                          tooltiptext="&devToolbarCloseButton.tooltiptext;"/>
 #endif
    </toolbar>
 
--- a/browser/base/content/highlighter.css
+++ b/browser/base/content/highlighter.css
@@ -1,131 +1,104 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  
-#highlighter-container {
+.highlighter-container {
   pointer-events: none;
 }
 
-#highlighter-controls {
+.highlighter-controls {
   position: absolute;
   top: 0;
   left: 0;
 }
 
-#highlighter-outline-container {
+.highlighter-outline-container {
   overflow: hidden;
   position: relative;
 }
 
-#highlighter-outline {
+.highlighter-outline {
   position: absolute;
 }
 
-#highlighter-outline[hidden] {
+.highlighter-outline[hidden] {
   opacity: 0;
   pointer-events: none;
   display: -moz-box;
 }
 
-#highlighter-outline:not([disable-transitions]) {
+.highlighter-outline:not([disable-transitions]) {
   transition-property: opacity, top, left, width, height;
   transition-duration: 0.1s;
   transition-timing-function: linear;
 }
 
-.inspector-breadcrumbs-button {
-  direction: ltr;
-}
-
 /*
  * Node Infobar
  */
 
-#highlighter-nodeinfobar-container {
+.highlighter-nodeinfobar-container {
   position: absolute;
   max-width: 95%;
 }
 
-#highlighter-nodeinfobar-container[hidden] {
+.highlighter-nodeinfobar-container[hidden] {
   opacity: 0;
   pointer-events: none;
   display: -moz-box;
 }
 
-#highlighter-nodeinfobar-container:not([disable-transitions]),
-#highlighter-nodeinfobar-container[disable-transitions][force-transitions] {
+.highlighter-nodeinfobar-container:not([disable-transitions]),
+.highlighter-nodeinfobar-container[disable-transitions][force-transitions] {
   transition-property: transform, opacity, top, left;
   transition-duration: 0.1s;
   transition-timing-function: linear;
 }
 
-#highlighter-nodeinfobar-text {
+.highlighter-nodeinfobar-text {
   overflow: hidden;
   white-space: nowrap;
   text-overflow: ellipsis;
   direction: ltr;
 }
 
 .highlighter-nodeinfobar-button > .toolbarbutton-text {
   display: none;
 }
 
-#highlighter-nodeinfobar-container:not([locked]):not(:hover) > #highlighter-nodeinfobar > .highlighter-nodeinfobar-button {
+.highlighter-nodeinfobar-container:not([locked]):not(:hover) > .highlighter-nodeinfobar > .highlighter-nodeinfobar-button {
   visibility: hidden;
 }
 
-#highlighter-nodeinfobar-container[locked] > #highlighter-nodeinfobar,
-#highlighter-nodeinfobar-container:not([locked]):hover > #highlighter-nodeinfobar {
+.highlighter-nodeinfobar-container[locked] > .highlighter-nodeinfobar,
+.highlighter-nodeinfobar-container:not([locked]):hover > .highlighter-nodeinfobar {
   pointer-events: auto;
 }
 
-html|*#highlighter-nodeinfobar-id,
-html|*#highlighter-nodeinfobar-classes,
-html|*#highlighter-nodeinfobar-pseudo-classes,
-html|*#highlighter-nodeinfobar-tagname {
+html|*.highlighter-nodeinfobar-id,
+html|*.highlighter-nodeinfobar-classes,
+html|*.highlighter-nodeinfobar-pseudo-classes,
+html|*.highlighter-nodeinfobar-tagname {
   -moz-user-select: text;
   cursor: text;
 }
 
 .highlighter-nodeinfobar-arrow {
   display: none;
 }
 
-#highlighter-nodeinfobar-container[position="top"]:not([hide-arrow]) > #highlighter-nodeinfobar-arrow-bottom {
+.highlighter-nodeinfobar-container[position="top"]:not([hide-arrow]) > .highlighter-nodeinfobar-arrow-bottom {
   display: block;
 }
 
-#highlighter-nodeinfobar-container[position="bottom"]:not([hide-arrow]) > #highlighter-nodeinfobar-arrow-top {
+.highlighter-nodeinfobar-container[position="bottom"]:not([hide-arrow]) > .highlighter-nodeinfobar-arrow-top {
   display: block;
 }
 
-#highlighter-nodeinfobar-container[disabled] {
+.highlighter-nodeinfobar-container[disabled] {
   visibility: hidden;
 }
 
-html|*#highlighter-nodeinfobar-tagname {
+html|*.highlighter-nodeinfobar-tagname {
   text-transform: lowercase;
 }
-
-.devtools-toolbarbutton:not([label]) > .toolbarbutton-text {
-  display: none;
-}
-
-#inspector-option-toolbarbutton > .toolbarbutton-menu-dropmarker {
-  display: none;
-}
-
-#inspector-layoutview-container > iframe {
-  /* header size */
-  height: 28px;
-}
-
-#inspector-layoutview-container:not([disable-transitions]) > iframe {
-  transition-property: height;
-  transition-duration: 0.2s;
-}
-
-#inspector-layoutview-container > iframe[open] {
-  /* header size + layout view size: 28px + 145px */
-  height: 173px;
-}
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -413,21 +413,29 @@ nsContextMenu.prototype = {
         this.setItemAttr("context-video-showstats", "disabled", hasError);
         this.setItemAttr("context-video-hidestats", "disabled", hasError);
       }
     }
     this.showItem("context-media-sep-commands",  onMedia);
   },
 
   inspectNode: function CM_inspectNode() {
-    if (InspectorUI.isTreePanelOpen) {
-      InspectorUI.inspectNode(this.target);
-      InspectorUI.stopInspecting();
+    let gBrowser = this.browser.ownerDocument.defaultView.gBrowser;
+    let imported = {};
+    Cu.import("resource:///modules/devtools/Target.jsm", imported);
+    var target = imported.TargetFactory.forTab(gBrowser.selectedTab);
+    let inspector = gDevTools.getPanelForTarget("inspector", target);
+    if (inspector && inspector.isReady) {
+      inspector.selection.setNode(this.target);
     } else {
-      InspectorUI.openInspectorUI(this.target);
+      let toolbox = gDevTools.openToolboxForTab(target, "inspector");
+      toolbox.once("inspector-ready", function(event, panel) {
+        let inspector = gDevTools.getPanelForTarget("inspector", target);
+        inspector.selection.setNode(this.target, "browser-context-menu");
+      }.bind(this));
     }
   },
 
   // Set various context menu attributes based on the state of the world.
   setTarget: function (aNode, aRangeParent, aRangeOffset) {
     const xulNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
     if (aNode.namespaceURI == xulNS ||
         aNode.nodeType == Node.DOCUMENT_NODE ||
--- a/browser/components/search/content/search.xml
+++ b/browser/components/search/content/search.xml
@@ -623,17 +623,17 @@
                               .getService(Components.interfaces.nsIPrefBranch);
           prefs.addObserver("browser.search.suggest.enabled", this, false);
         ]]></body>
       </method>
 
       <!--
         This overrides the searchParam property in autocomplete.xml.  We're
         hijacking this property as a vehicle for delivering the privacy
-        information about the window into the guys of nsSearchSuggestions.
+        information about the window into the guts of nsSearchSuggestions.
 
         Note that the setter is the same as the parent.  We were not sure whether
         we can override just the getter.  If that proves to be the case, the setter
         can be removed.
       -->
       <property name="searchParam"
                 onget="return this.getAttribute('autocompletesearchparam') +
                        (PrivateBrowsingUtils.isWindowPrivate(window) ? '|private' : '');"
--- a/browser/devtools/Makefile.in
+++ b/browser/devtools/Makefile.in
@@ -8,24 +8,25 @@ topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH   = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 include $(topsrcdir)/config/config.mk
 
 DIRS = \
-  highlighter \
+  inspector \
   markupview \
   webconsole \
   commandline \
   sourceeditor \
   styleeditor \
   styleinspector \
   tilt \
   scratchpad \
   debugger \
   layoutview \
   shared \
   responsivedesign \
+  framework \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/browser/devtools/commandline/CmdBreak.jsm
+++ b/browser/devtools/commandline/CmdBreak.jsm
@@ -7,16 +7,22 @@ const { classes: Cc, interfaces: Ci, uti
 this.EXPORTED_SYMBOLS = [ ];
 
 Cu.import("resource:///modules/devtools/gcli.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "HUDService",
                                   "resource:///modules/HUDService.jsm");
 
+XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
+                                  "resource:///modules/devtools/Target.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
+                                  "resource:///modules/devtools/gDevTools.jsm");
+
 /**
  * 'break' command
  */
 gcli.addCommand({
   name: "break",
   description: gcli.lookup("breakDesc"),
   manual: gcli.lookup("breakManual")
 });
@@ -25,22 +31,25 @@ gcli.addCommand({
 /**
  * 'break list' command
  */
 gcli.addCommand({
   name: "break list",
   description: gcli.lookup("breaklistDesc"),
   returnType: "html",
   exec: function(args, context) {
-    let win = HUDService.currentContext();
-    let dbg = win.DebuggerUI.getDebugger();
+    let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
+
     if (!dbg) {
       return gcli.lookup("breakaddDebuggerStopped");
     }
-    let breakpoints = dbg.breakpoints;
+
+    let breakpoints = dbg.getAllBreakpoints();
 
     if (Object.keys(breakpoints).length === 0) {
       return gcli.lookup("breaklistNone");
     }
 
     let reply = gcli.lookup("breaklistIntro");
     reply += "<ol>";
     for each (let breakpoint in breakpoints) {
@@ -71,21 +80,23 @@ gcli.addCommand({
   name: "break add line",
   description: gcli.lookup("breakaddlineDesc"),
   params: [
     {
       name: "file",
       type: {
         name: "selection",
         data: function() {
-          let win = HUDService.currentContext();
-          let dbg = win.DebuggerUI.getDebugger();
+          let gBrowser = HUDService.currentContext().gBrowser;
+          let target = TargetFactory.forTab(gBrowser.selectedTab);
+          let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
+
           let files = [];
           if (dbg) {
-            let sourcesView = dbg.contentWindow.DebuggerView.Sources;
+            let sourcesView = dbg.panelWin.DebuggerView.Sources;
             for (let item in sourcesView) {
               files.push(item.value);
             }
           }
           return files;
         }
       },
       description: gcli.lookup("breakaddlineFileDesc")
@@ -94,18 +105,21 @@ gcli.addCommand({
       name: "line",
       type: { name: "number", min: 1, step: 10 },
       description: gcli.lookup("breakaddlineLineDesc")
     }
   ],
   returnType: "html",
   exec: function(args, context) {
     args.type = "line";
-    let win = HUDService.currentContext();
-    let dbg = win.DebuggerUI.getDebugger();
+
+    let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
+
     if (!dbg) {
       return gcli.lookup("breakaddDebuggerStopped");
     }
     var promise = context.createPromise();
     let position = { url: args.file, line: args.line };
     dbg.addBreakpoint(position, function(aBreakpoint, aError) {
       if (aError) {
         promise.resolve(gcli.lookupFormat("breakaddFailed", [aError]));
@@ -126,37 +140,41 @@ gcli.addCommand({
   description: gcli.lookup("breakdelDesc"),
   params: [
     {
       name: "breakid",
       type: {
         name: "number",
         min: 0,
         max: function() {
-          let win = HUDService.currentContext();
-          let dbg = win.DebuggerUI.getDebugger();
+          let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
+          let target = TargetFactory.forTab(gBrowser.selectedTab);
+          let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
+
           if (!dbg) {
             return gcli.lookup("breakaddDebuggerStopped");
           }
-          return Object.keys(dbg.breakpoints).length - 1;
+          return Object.keys(dbg.getAllBreakpoints()).length - 1;
         },
       },
       description: gcli.lookup("breakdelBreakidDesc")
     }
   ],
   returnType: "html",
   exec: function(args, context) {
-    let win = HUDService.currentContext();
-    let dbg = win.DebuggerUI.getDebugger();
+    let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
+
     if (!dbg) {
       return gcli.lookup("breakaddDebuggerStopped");
     }
 
-    let breakpoints = dbg.breakpoints;
-    let id = Object.keys(dbg.breakpoints)[args.breakid];
+    let breakpoints = dbg.getAllBreakpoints();
+    let id = Object.keys(breakpoints)[args.breakid];
     if (!id || !(id in breakpoints)) {
       return gcli.lookup("breakNotFound");
     }
 
     let promise = context.createPromise();
     try {
       dbg.removeBreakpoint(breakpoints[id], function() {
         promise.resolve(gcli.lookup("breakdelRemoved"));
--- a/browser/devtools/commandline/CmdCalllog.jsm
+++ b/browser/devtools/commandline/CmdCalllog.jsm
@@ -4,29 +4,32 @@
 
 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
 this.EXPORTED_SYMBOLS = [ ];
 
 Cu.import("resource:///modules/devtools/gcli.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "HUDService",
-                                  "resource:///modules/HUDService.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
+                                  "resource:///modules/devtools/gDevTools.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "Debugger", function() {
   let JsDebugger = {};
   Components.utils.import("resource://gre/modules/jsdebugger.jsm", JsDebugger);
 
   let global = Components.utils.getGlobalForObject({});
   JsDebugger.addDebuggerToGlobal(global);
 
   return global.Debugger;
 });
 
+XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
+                                  "resource:///modules/devtools/Target.jsm");
+
 let debuggers = [];
 
 /**
  * 'calllog' command
  */
 gcli.addCommand({
   name: "calllog",
   description: gcli.lookup("calllogDesc")
@@ -45,18 +48,19 @@ gcli.addCommand({
     let dbg = new Debugger(contentWindow);
     dbg.onEnterFrame = function(frame) {
       // BUG 773652 -  Make the output from the GCLI calllog command nicer
       contentWindow.console.log("Method call: " + this.callDescription(frame));
     }.bind(this);
 
     debuggers.push(dbg);
 
-    let tab = context.environment.chromeDocument.defaultView.gBrowser.selectedTab;
-    HUDService.activateHUDForContext(tab);
+    let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    gDevTools.openToolboxForTab(target, "webconsole");
 
     return gcli.lookup("calllogStartReply");
   },
 
   callDescription: function(frame) {
     let name = "<anonymous>";
     if (frame.callee.name) {
       name = frame.callee.name;
--- a/browser/devtools/commandline/CmdCalllogChrome.jsm
+++ b/browser/devtools/commandline/CmdCalllogChrome.jsm
@@ -5,18 +5,20 @@
 
 this.EXPORTED_SYMBOLS = [ ];
 
 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
 Cu.import("resource:///modules/devtools/gcli.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "HUDService",
-                                  "resource:///modules/HUDService.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
+                                  "resource:///modules/devtools/gDevTools.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
+                                  "resource:///modules/devtools/Target.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "Debugger", function() {
   let JsDebugger = {};
   Cu.import("resource://gre/modules/jsdebugger.jsm", JsDebugger);
 
   let global = Components.utils.getGlobalForObject({});
   JsDebugger.addDebuggerToGlobal(global);
 
@@ -103,18 +105,19 @@ gcli.addCommand({
     debuggers.push(dbg);
 
     dbg.onEnterFrame = function(frame) {
       // BUG 773652 -  Make the output from the GCLI calllog command nicer
       contentWindow.console.log(gcli.lookup("callLogChromeMethodCall") +
                                 ": " + this.callDescription(frame));
     }.bind(this);
 
-    let tab = context.environment.chromeDocument.defaultView.gBrowser.selectedTab;
-    HUDService.activateHUDForContext(tab);
+    let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    gDevTools.openToolboxForTab(target, "webconsole");
 
     return gcli.lookup("calllogChromeStartReply");
   },
 
   valueToString: function(value) {
     if (typeof value !== "object" || value === null)
       return uneval(value);
     return "[object " + value.class + "]";
--- a/browser/devtools/commandline/CmdConsole.jsm
+++ b/browser/devtools/commandline/CmdConsole.jsm
@@ -6,16 +6,20 @@ const { classes: Cc, interfaces: Ci, uti
 
 this.EXPORTED_SYMBOLS = [ ];
 
 Cu.import("resource:///modules/devtools/gcli.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "HUDService",
                                   "resource:///modules/HUDService.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
+                                  "resource:///modules/devtools/gDevTools.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
+                                  "resource:///modules/devtools/Target.jsm");
 
 /**
  * 'console' command
  */
 gcli.addCommand({
   name: "console",
   description: gcli.lookup("consoleDesc"),
   manual: gcli.lookup("consoleManual")
@@ -39,24 +43,26 @@ gcli.addCommand({
 
 /**
  * 'console close' command
  */
 gcli.addCommand({
   name: "console close",
   description: gcli.lookup("consolecloseDesc"),
   exec: function Command_consoleClose(args, context) {
-    let tab = context.environment.chromeDocument.defaultView.gBrowser.selectedTab
-    HUDService.deactivateHUDForContext(tab);
+    let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    gDevTools.closeToolbox(target);
   }
 });
 
 /**
  * 'console open' command
  */
 gcli.addCommand({
   name: "console open",
   description: gcli.lookup("consoleopenDesc"),
   exec: function Command_consoleOpen(args, context) {
-    let tab = context.environment.chromeDocument.defaultView.gBrowser.selectedTab
-    HUDService.activateHUDForContext(tab);
+    let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    gDevTools.openToolboxForTab(target, "webconsole");
   }
 });
--- a/browser/devtools/commandline/CmdDbg.jsm
+++ b/browser/devtools/commandline/CmdDbg.jsm
@@ -4,16 +4,21 @@
 
 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
 this.EXPORTED_SYMBOLS = [ ];
 
 Cu.import("resource:///modules/devtools/gcli.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
+XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
+                                  "resource:///modules/devtools/gDevTools.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
+                                  "resource:///modules/devtools/Target.jsm");
+
 /**
  * 'dbg' command
  */
 gcli.addCommand({
   name: "dbg",
   description: gcli.lookup("dbgDesc"),
   manual: gcli.lookup("dbgManual")
 });
@@ -21,84 +26,76 @@ gcli.addCommand({
 /**
  * 'dbg open' command
  */
 gcli.addCommand({
   name: "dbg open",
   description: gcli.lookup("dbgOpen"),
   params: [],
   exec: function (args, context) {
-    let win = context.environment.chromeDocument.defaultView;
-    let tab = win.gBrowser.selectedTab;
-    let dbg = win.DebuggerUI.findDebugger();
-
-    if (dbg) {
-      if (dbg.ownerTab !== tab) {
-        win.DebuggerUI.toggleDebugger();
-      }
-
-      return;
-    }
-
-    win.DebuggerUI.toggleDebugger();
+    let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    gDevTools.openToolboxForTab(target, "jsdebugger");
   }
 });
 
 /**
  * 'dbg close' command
  */
 gcli.addCommand({
   name: "dbg close",
   description: gcli.lookup("dbgClose"),
   params: [],
   exec: function (args, context) {
-    let win = context.environment.chromeDocument.defaultView;
-    let tab = win.gBrowser.selectedTab;
-    let dbg = win.DebuggerUI.findDebugger();
+    let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
 
-    if (dbg) {
-      dbg.close();
+    if (dbg /* FIXME: and debugger panel is currently active */) {
+      gDevTools.closeToolbox(target);
     }
   }
 });
 
 /**
  * 'dbg interrupt' command
  */
 gcli.addCommand({
   name: "dbg interrupt",
   description: gcli.lookup("dbgInterrupt"),
   params: [],
   exec: function(args, context) {
-    let win = context.environment.chromeDocument.defaultView;
-    let dbg = win.DebuggerUI.getDebugger();
+    let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
 
     if (dbg) {
-      let controller = dbg.contentWindow.DebuggerController;
+      let controller = dbg._controller;
       let thread = controller.activeThread;
       if (!thread.paused) {
         thread.interrupt();
       }
     }
   }
 });
 
 /**
  * 'dbg continue' command
  */
 gcli.addCommand({
   name: "dbg continue",
   description: gcli.lookup("dbgContinue"),
   params: [],
   exec: function(args, context) {
-    let win = context.environment.chromeDocument.defaultView;
-    let dbg = win.DebuggerUI.getDebugger();
+    let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
 
     if (dbg) {
-      let controller = dbg.contentWindow.DebuggerController;
+      let controller = dbg._controller;
       let thread = controller.activeThread;
       if (thread.paused) {
         thread.resume();
       }
     }
   }
 });
 
@@ -116,62 +113,65 @@ gcli.addCommand({
 /**
  * 'dbg step over' command
  */
 gcli.addCommand({
   name: "dbg step over",
   description: gcli.lookup("dbgStepOverDesc"),
   params: [],
   exec: function(args, context) {
-    let win = context.environment.chromeDocument.defaultView;
-    let dbg = win.DebuggerUI.getDebugger();
+    let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
 
     if (dbg) {
-      let controller = dbg.contentWindow.DebuggerController;
+      let controller = dbg._controller;
       let thread = controller.activeThread;
       if (thread.paused) {
         thread.stepOver();
       }
     }
   }
 });
 
 /**
  * 'dbg step in' command
  */
 gcli.addCommand({
   name: 'dbg step in',
   description: gcli.lookup("dbgStepInDesc"),
   params: [],
   exec: function(args, context) {
-    let win = context.environment.chromeDocument.defaultView;
-    let dbg = win.DebuggerUI.getDebugger();
+    let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
 
     if (dbg) {
-      let controller = dbg.contentWindow.DebuggerController;
+      let controller = dbg._controller;
       let thread = controller.activeThread;
       if (thread.paused) {
         thread.stepIn();
       }
     }
   }
 });
 
 /**
  * 'dbg step over' command
  */
 gcli.addCommand({
   name: 'dbg step out',
   description: gcli.lookup("dbgStepOutDesc"),
   params: [],
   exec: function(args, context) {
-    let win = context.environment.chromeDocument.defaultView;
-    let dbg = win.DebuggerUI.getDebugger();
+    let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
 
     if (dbg) {
-      let controller = dbg.contentWindow.DebuggerController;
+      let controller = dbg._controller;
       let thread = controller.activeThread;
       if (thread.paused) {
         thread.stepOut();
       }
     }
   }
 });
--- a/browser/devtools/commandline/Commands.jsm
+++ b/browser/devtools/commandline/Commands.jsm
@@ -19,8 +19,9 @@ Cu.import("resource:///modules/devtools/
 Cu.import("resource:///modules/devtools/CmdExport.jsm");
 Cu.import("resource:///modules/devtools/CmdInspect.jsm");
 Cu.import("resource:///modules/devtools/CmdJsb.jsm");
 Cu.import("resource:///modules/devtools/CmdPagemod.jsm");
 Cu.import("resource:///modules/devtools/CmdResize.jsm");
 Cu.import("resource:///modules/devtools/CmdRestart.jsm");
 Cu.import("resource:///modules/devtools/CmdScreenshot.jsm");
 Cu.import("resource:///modules/devtools/CmdTilt.jsm");
+Cu.import("resource:///modules/devtools/CmdScratchpad.jsm");
--- a/browser/devtools/commandline/test/browser_dbg_cmd.js
+++ b/browser/devtools/commandline/test/browser_dbg_cmd.js
@@ -1,82 +1,97 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let tempScope = {};
+Cu.import("resource:///modules/devtools/Target.jsm", tempScope);
+let TargetFactory = tempScope.TargetFactory;
+
 function test() {
   const TEST_URI = "http://example.com/browser/browser/devtools/commandline/" +
                    "test/browser_dbg_cmd.html";
 
   DeveloperToolbarTest.test(TEST_URI, function() {
     testDbgCmd();
   });
 }
 
+function testCommands(dbg, cmd) {
+  // Wait for the initial resume...
+  dbg._controller.activeThread.addOneTimeListener("resumed", function () {
+    info("Starting tests.");
+
+    let contentDoc = content.window.document;
+    let output = contentDoc.querySelector("input[type=text]");
+    let btnDoit = contentDoc.querySelector("input[type=button]");
+
+    cmd("dbg interrupt", function() {
+      ok(true, "debugger is paused");
+      dbg._controller.activeThread.addOneTimeListener("resumed", function () {
+        ok(true, "debugger continued");
+        dbg._controller.activeThread.addOneTimeListener("paused", function() {
+          cmd("dbg step in", function() {
+            cmd("dbg step in", function() {
+              cmd("dbg step in", function() {
+                is(output.value, "step in", "debugger stepped in");
+                cmd("dbg step over", function() {
+                  is(output.value, "step over", "debugger stepped over");
+                  cmd("dbg step out", function() {
+                    is(output.value, "step out", "debugger stepped out");
+                    cmd("dbg continue", function() {
+                      cmd("dbg continue", function() {
+                        is(output.value, "dbg continue", "debugger continued");
+                        DeveloperToolbarTest.exec({
+                          typed: "dbg close",
+                          blankOutput: true
+                        });
+
+                        let target = TargetFactory.forTab(gBrowser.selectedTab);
+                        ok(!gDevTools.getToolboxForTarget(target),
+                          "Debugger was closed.");
+                        finish();
+                      });
+                    });
+                  });
+                });
+              });
+            });
+          });
+        });
+        EventUtils.sendMouseEvent({type:"click"}, btnDoit);
+      });
+      DeveloperToolbarTest.exec({
+        typed: "dbg continue",
+        blankOutput: true
+      });
+    });
+  });
+}
+
 function testDbgCmd() {
   DeveloperToolbarTest.exec({
     typed: "dbg open",
     blankOutput: true
   });
 
-  let pane = DebuggerUI.findDebugger();
-  ok(pane, "Debugger was opened.");
-  let frame = pane._frame;
-
-  frame.addEventListener("Debugger:Connected", function dbgConnected(aEvent) {
-    frame.removeEventListener("Debugger:Connected", dbgConnected, true);
-
-    // Wait for the initial resume...
-    aEvent.target.ownerDocument.defaultView.gClient
-        .addOneTimeListener("resumed", function() {
-
-      info("Starting tests.");
-
-      let contentDoc = content.window.document;
-      let output = contentDoc.querySelector("input[type=text]");
-      let btnDoit = contentDoc.querySelector("input[type=button]");
+  let target = TargetFactory.forTab(gBrowser.selectedTab);
+  let toolbox = gDevTools.getToolboxForTarget(target);
 
-      cmd("dbg interrupt", function() {
-        ok(true, "debugger is paused");
-        pane.contentWindow.gClient.addOneTimeListener("resumed", function() {
-          ok(true, "debugger continued");
-          pane.contentWindow.gClient.addOneTimeListener("paused", function() {
-            cmd("dbg step in", function() {
-              cmd("dbg step in", function() {
-                cmd("dbg step in", function() {
-                  is(output.value, "step in", "debugger stepped in");
-                  cmd("dbg step over", function() {
-                    is(output.value, "step over", "debugger stepped over");
-                    cmd("dbg step out", function() {
-                      is(output.value, "step out", "debugger stepped out");
-                      cmd("dbg continue", function() {
-                        cmd("dbg continue", function() {
-                          is(output.value, "dbg continue", "debugger continued");
-                          DeveloperToolbarTest.exec({
-                            typed: "dbg close",
-                            blankOutput: true
-                          });
-
-                          let dbg = DebuggerUI.findDebugger();
-                          ok(!dbg, "Debugger was closed.");
-                          finish();
-                        });
-                      });
-                    });
-                  });
-                });
-              });
-            });
-          });
-          EventUtils.sendMouseEvent({type:"click"}, btnDoit);
-        });
-        DeveloperToolbarTest.exec({
-          typed: "dbg continue",
-          blankOutput: true
-        });
-      });
-    });
+  toolbox.once("jsdebugger-ready", function dbgReady() {
+    let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
+    ok(dbg, "DebuggerPanel exists");
 
     function cmd(aTyped, aCallback) {
-      pane.contentWindow.gClient.addOneTimeListener("paused", aCallback);
+      dbg._controller.activeThread.addOneTimeListener("paused", aCallback);
       DeveloperToolbarTest.exec({
         typed: aTyped,
         blankOutput: true
       });
     }
+
+    if (dbg._controller.activeThread) {
+      testCommands(dbg, cmd);
+    } else {
+      dbg.once("connected", testCommands.bind(null, dbg, cmd));
+    }
   });
 }
--- a/browser/devtools/commandline/test/browser_dbg_cmd_break.js
+++ b/browser/devtools/commandline/test/browser_dbg_cmd_break.js
@@ -1,16 +1,20 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests that the break command works as it should
 
 const TEST_URI = "http://example.com/browser/browser/devtools/commandline/" +
                  "test/browser_dbg_cmd_break.html";
 
+let tempScope = {};
+Cu.import("resource:///modules/devtools/Target.jsm", tempScope);
+let TargetFactory = tempScope.TargetFactory;
+
 function test() {
   DeveloperToolbarTest.test(TEST_URI, [ testBreakCommands ]);
 }
 
 function testBreakCommands() {
   helpers.setInput('break');
   helpers.check({
     input:  'break',
@@ -30,91 +34,89 @@ function testBreakCommands() {
   helpers.setInput('break add line');
   helpers.check({
     input:  'break add line',
     hints:                ' <file> <line>',
     markup: 'VVVVVVVVVVVVVV',
     status: 'ERROR'
   });
 
-  let pane = DebuggerUI.toggleDebugger();
-
-  var dbgConnected = DeveloperToolbarTest.checkCalled(function() {
-    pane._frame.removeEventListener("Debugger:Connected", dbgConnected, true);
-
-    // Wait for the initial resume.
-    let client = pane.contentWindow.gClient;
-
-    var resumed = DeveloperToolbarTest.checkCalled(function() {
-
-      var framesAdded = DeveloperToolbarTest.checkCalled(function() {
-        helpers.setInput('break add line ' + TEST_URI + ' ' + content.wrappedJSObject.line0);
-        helpers.check({
-          hints: '',
-          status: 'VALID',
-          args: {
-            file: { value: TEST_URI },
-            line: { value: content.wrappedJSObject.line0 },
-          }
-        });
+  let target = TargetFactory.forTab(gBrowser.selectedTab);
+  let toolbox = gDevTools.openToolboxForTab(target, "jsdebugger");
+  toolbox.once("jsdebugger-ready", function dbgReady() {
+    let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
+    ok(dbg, "DebuggerPanel exists");
+    dbg.once("connected", function() {
+      // Wait for the initial resume...
+      dbg.panelWin.gClient.addOneTimeListener("resumed", function() {
+        dbg._view.Variables.lazyEmpty = false;
 
-        DeveloperToolbarTest.exec({
-          args: {
-            type: 'line',
-            file: TEST_URI,
-            line: content.wrappedJSObject.line0
-          },
-          completed: false
-        });
-
-        helpers.setInput('break list');
-        helpers.check({
-          input:  'break list',
-          hints:            '',
-          markup: 'VVVVVVVVVV',
-          status: 'VALID'
-        });
-
-        DeveloperToolbarTest.exec();
-
-        var cleanup = DeveloperToolbarTest.checkCalled(function() {
-          helpers.setInput('break del 9');
+        var client = dbg.panelWin.gClient;
+        var framesAdded = DeveloperToolbarTest.checkCalled(function() {
+          helpers.setInput('break add line ' + TEST_URI + ' ' + content.wrappedJSObject.line0);
           helpers.check({
-            input:  'break del 9',
-            hints:             '',
-            markup: 'VVVVVVVVVVE',
-            status: 'ERROR',
-            args: {
-              breakid: { status: 'ERROR', message: '9 is greater than maximum allowed: 0.' },
-            }
-          });
-
-          helpers.setInput('break del 0');
-          helpers.check({
-            input:  'break del 0',
-            hints:             '',
-            markup: 'VVVVVVVVVVV',
+            hints: '',
             status: 'VALID',
             args: {
-              breakid: { value: 0 },
+              file: { value: TEST_URI },
+              line: { value: content.wrappedJSObject.line0 },
             }
           });
 
           DeveloperToolbarTest.exec({
-            args: { breakid: 0 },
+            args: {
+              type: 'line',
+              file: TEST_URI,
+              line: content.wrappedJSObject.line0
+            },
             completed: false
           });
+
+          helpers.setInput('break list');
+          helpers.check({
+            input:  'break list',
+            hints:            '',
+            markup: 'VVVVVVVVVV',
+            status: 'VALID'
+          });
+
+          DeveloperToolbarTest.exec();
+
+          var cleanup = DeveloperToolbarTest.checkCalled(function() {
+            helpers.setInput('break del 9');
+            helpers.check({
+              input:  'break del 9',
+              hints:             '',
+              markup: 'VVVVVVVVVVE',
+              status: 'ERROR',
+              args: {
+                breakid: { status: 'ERROR', message: '9 is greater than maximum allowed: 0.' },
+              }
+            });
+
+            helpers.setInput('break del 0');
+            helpers.check({
+              input:  'break del 0',
+              hints:             '',
+              markup: 'VVVVVVVVVVV',
+              status: 'VALID',
+              args: {
+                breakid: { value: 0 },
+              }
+            });
+
+            DeveloperToolbarTest.exec({
+              args: { breakid: 0 },
+              completed: false
+            });
+          });
+
+          client.activeThread.resume(cleanup);
         });
 
-        client.activeThread.resume(cleanup);
-      });
-
-      client.activeThread.addOneTimeListener("framesadded", framesAdded);
+        client.activeThread.addOneTimeListener("framesadded", framesAdded);
 
-      // Trigger newScript notifications using eval.
-      content.wrappedJSObject.firstCall();
+        // Trigger newScript notifications using eval.
+        content.wrappedJSObject.firstCall();
+      });
     });
-
-    client.addOneTimeListener("resumed", resumed);
   });
-
-  pane._frame.addEventListener("Debugger:Connected", dbgConnected, true);
 }
new file mode 100644
--- /dev/null
+++ b/browser/devtools/debugger/DebuggerPanel.jsm
@@ -0,0 +1,89 @@
+/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+const Cu = Components.utils;
+
+this.EXPORTED_SYMBOLS = ["DebuggerPanel"];
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource:///modules/devtools/EventEmitter.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "DebuggerServer",
+  "resource://gre/modules/devtools/dbg-server.jsm");
+
+function DebuggerPanel(iframeWindow, toolbox) {
+  this._toolbox = toolbox;
+  this._controller = iframeWindow.DebuggerController;
+  this._view = iframeWindow.DebuggerView;
+  this._controller._target = this.target;
+  this._bkp = this._controller.Breakpoints;
+  this.panelWin = iframeWindow;
+
+  this._ensureOnlyOneRunningDebugger();
+  if (!this.target.isRemote) {
+    if (!DebuggerServer.initialized) {
+      DebuggerServer.init();
+      DebuggerServer.addBrowserActors();
+    }
+  }
+
+  let onDebuggerLoaded = function () {
+    iframeWindow.removeEventListener("Debugger:Loaded", onDebuggerLoaded, true);
+    this.setReady();
+  }.bind(this);
+
+  let onDebuggerConnected = function () {
+    iframeWindow.removeEventListener("Debugger:Connected",
+      onDebuggerConnected, true);
+    this.emit("connected");
+  }.bind(this);
+
+  iframeWindow.addEventListener("Debugger:Loaded", onDebuggerLoaded, true);
+  iframeWindow.addEventListener("Debugger:Connected",
+    onDebuggerConnected, true);
+
+  new EventEmitter(this);
+}
+
+DebuggerPanel.prototype = {
+  // DevToolPanel API
+  get target() this._toolbox.target,
+
+  get isReady() this._isReady,
+
+  setReady: function() {
+    this._isReady = true;
+    this.emit("ready");
+  },
+
+  destroy: function() {
+  },
+
+  // DebuggerPanel API
+
+  addBreakpoint: function() {
+    this._bkp.addBreakpoint.apply(this._bkp, arguments);
+  },
+
+  removeBreakpoint: function() {
+    this._bkp.removeBreakpoint.apply(this._bkp, arguments);
+  },
+
+  getBreakpoint: function() {
+    return this._bkp.getBreakpoint.apply(this._bkp, arguments);
+  },
+
+  getAllBreakpoints: function() {
+    return this._bkp.store;
+  },
+
+  // Private
+
+  _ensureOnlyOneRunningDebugger: function() {
+    // FIXME
+  },
+};
--- a/browser/devtools/debugger/debugger-controller.js
+++ b/browser/devtools/debugger/debugger-controller.js
@@ -43,16 +43,17 @@ let DebuggerController = {
   /**
    * Initializes the view and connects a debugger client to the server.
    */
   _startupDebugger: function DC__startupDebugger() {
     if (this._isInitialized) {
       return;
     }
     this._isInitialized = true;
+
     window.removeEventListener("load", this._startupDebugger, true);
 
     DebuggerView.initialize(function() {
       DebuggerView._isInitialized = true;
 
       window.dispatchEvent("Debugger:Loaded");
       this._connect();
     }.bind(this));
@@ -140,54 +141,76 @@ let DebuggerController = {
       Prefs.remoteHost + ":" + Prefs.remotePort);
   },
 
   /**
    * Initializes a debugger client and connects it to the debugger server,
    * wiring event handlers as necessary.
    */
   _connect: function DC__connect() {
-    if (window._isRemoteDebugger && !this._prepareConnection()) {
+    function callback() {
+      window.dispatchEvent("Debugger:Connected");
+    }
+
+    let client;
+    // Remote debugging gets the debuggee from a RemoteTarget object.
+    if (this._target && this._target.isRemote) {
+      client = this.client = this._target.client;
+
+      this._target.on("close", this._onTabDetached);
+      this._target.on("navigate", this._onTabNavigated);
+
+      if (this._target.chrome) {
+        let dbg = this._target.form.chromeDebugger;
+        this._startChromeDebugging(client, dbg, callback);
+      } else {
+        this._startDebuggingTab(client, this._target.form, callback);
+      }
       return;
     }
-    let transport = (window._isChromeDebugger || window._isRemoteDebugger)
+
+    // Content debugging can connect directly to the page.
+    // TODO: convert this to use a TabTarget.
+    let transport = window._isChromeDebugger
       ? debuggerSocketConnect(Prefs.remoteHost, Prefs.remotePort)
       : DebuggerServer.connectPipe();
+    client = this.client = new DebuggerClient(transport);
 
-    let client = this.client = new DebuggerClient(transport);
     client.addListener("tabNavigated", this._onTabNavigated);
     client.addListener("tabDetached", this._onTabDetached);
 
     client.connect(function(aType, aTraits) {
       client.listTabs(function(aResponse) {
         if (window._isChromeDebugger) {
           let dbg = aResponse.chromeDebugger;
-          this._startChromeDebugging(client, dbg);
+          this._startChromeDebugging(client, dbg, callback);
         } else {
           let tab = aResponse.tabs[aResponse.selected];
-          this._startDebuggingTab(client, tab);
+          this._startDebuggingTab(client, tab, callback);
         }
-        window.dispatchEvent("Debugger:Connected");
       }.bind(this));
     }.bind(this));
   },
 
   /**
    * Disconnects the debugger client and removes event handlers as necessary.
    */
   _disconnect: function DC__disconnect() {
     // Return early if the client didn't even have a chance to instantiate.
     if (!this.client) {
       return;
     }
     this.client.removeListener("tabNavigated", this._onTabNavigated);
     this.client.removeListener("tabDetached", this._onTabDetached);
-    this.client.close();
 
-    this.client = null;
+    if (!this._target.isRemote) {
+      this.client.close();
+      this.client = null;
+    }
+
     this.tabClient = null;
     this.activeThread = null;
   },
 
   /**
    * Called for each location change in the debugged tab.
    */
   _onTabNavigated: function DC__onTabNavigated() {
@@ -207,17 +230,18 @@ let DebuggerController = {
   /**
    * Sets up a debugging session.
    *
    * @param DebuggerClient aClient
    *        The debugger client.
    * @param object aTabGrip
    *        The remote protocol grip of the tab.
    */
-  _startDebuggingTab: function DC__startDebuggingTab(aClient, aTabGrip) {
+  _startDebuggingTab: function DC__startDebuggingTab
+      (aClient, aTabGrip, aCallback=function(){}) {
     if (!aClient) {
       Cu.reportError("No client found!");
       return;
     }
     this.client = aClient;
 
     aClient.attachTab(aTabGrip.actor, function(aResponse, aTabClient) {
       if (!aTabClient) {
@@ -233,29 +257,31 @@ let DebuggerController = {
         }
         this.activeThread = aThreadClient;
 
         this.ThreadState.connect();
         this.StackFrames.connect();
         this.SourceScripts.connect();
         aThreadClient.resume();
 
+        aCallback();
       }.bind(this));
     }.bind(this));
   },
 
   /**
    * Sets up a chrome debugging session.
    *
    * @param DebuggerClient aClient
    *        The debugger client.
    * @param object aChromeDebugger
    *        The remote protocol grip of the chrome debugger.
    */
-  _startChromeDebugging: function DC__startChromeDebugging(aClient, aChromeDebugger) {
+  _startChromeDebugging: function DC__startChromeDebugging
+      (aClient, aChromeDebugger, aCallback=function(){}) {
     if (!aClient) {
       Cu.reportError("No client found!");
       return;
     }
     this.client = aClient;
 
     aClient.attachThread(aChromeDebugger, function(aResponse, aThreadClient) {
       if (!aThreadClient) {
@@ -264,16 +290,17 @@ let DebuggerController = {
       }
       this.activeThread = aThreadClient;
 
       this.ThreadState.connect();
       this.StackFrames.connect();
       this.SourceScripts.connect();
       aThreadClient.resume();
 
+      aCallback();
     }.bind(this));
   },
 
   /**
    * Attempts to quit the current process if allowed.
    */
   _quitApp: function DC__quitApp() {
     let canceled = Cc["@mozilla.org/supports-PRBool;1"]
--- a/browser/devtools/debugger/debugger-toolbar.js
+++ b/browser/devtools/debugger/debugger-toolbar.js
@@ -20,17 +20,16 @@ function ToolbarView() {
 }
 
 ToolbarView.prototype = {
   /**
    * Initialization function, called when the debugger is started.
    */
   initialize: function DVT_initialize() {
     dumpn("Initializing the ToolbarView");
-    this._closeButton = document.getElementById("close");
     this._togglePanesButton = document.getElementById("toggle-panes");
     this._resumeButton = document.getElementById("resume");
     this._stepOverButton = document.getElementById("step-over");
     this._stepInButton = document.getElementById("step-in");
     this._stepOutButton = document.getElementById("step-out");
     this._chromeGlobals = document.getElementById("chrome-globals");
     this._scripts = document.getElementById("sources");
 
@@ -39,56 +38,43 @@ ToolbarView.prototype = {
     let stepInKey = LayoutHelpers.prettyKey(document.getElementById("stepInKey"), true);
     let stepOutKey = LayoutHelpers.prettyKey(document.getElementById("stepOutKey"), true);
     this._resumeTooltip = L10N.getFormatStr("resumeButtonTooltip", [resumeKey]);
     this._pauseTooltip = L10N.getFormatStr("pauseButtonTooltip", [resumeKey]);
     this._stepOverTooltip = L10N.getFormatStr("stepOverTooltip", [stepOverKey]);
     this._stepInTooltip = L10N.getFormatStr("stepInTooltip", [stepInKey]);
     this._stepOutTooltip = L10N.getFormatStr("stepOutTooltip", [stepOutKey]);
 
-    this._closeButton.addEventListener("click", this._onCloseClick, false);
     this._togglePanesButton.addEventListener("mousedown", this._onTogglePanesPressed, false);
     this._resumeButton.addEventListener("mousedown", this._onResumePressed, false);
     this._stepOverButton.addEventListener("mousedown", this._onStepOverPressed, false);
     this._stepInButton.addEventListener("mousedown", this._onStepInPressed, false);
     this._stepOutButton.addEventListener("mousedown", this._onStepOutPressed, false);
 
     this._stepOverButton.setAttribute("tooltiptext", this._stepOverTooltip);
     this._stepInButton.setAttribute("tooltiptext", this._stepInTooltip);
     this._stepOutButton.setAttribute("tooltiptext", this._stepOutTooltip);
 
-    this.toggleCloseButton(!window._isRemoteDebugger && !window._isChromeDebugger);
     // TODO: bug 806775
     // this.toggleChromeGlobalsContainer(window._isChromeDebugger);
   },
 
   /**
    * Destruction function, called when the debugger is closed.
    */
   destroy: function DVT_destroy() {
     dumpn("Destroying the ToolbarView");
-    this._closeButton.removeEventListener("click", this._onCloseClick, false);
     this._togglePanesButton.removeEventListener("mousedown", this._onTogglePanesPressed, false);
     this._resumeButton.removeEventListener("mousedown", this._onResumePressed, false);
     this._stepOverButton.removeEventListener("mousedown", this._onStepOverPressed, false);
     this._stepInButton.removeEventListener("mousedown", this._onStepInPressed, false);
     this._stepOutButton.removeEventListener("mousedown", this._onStepOutPressed, false);
   },
 
   /**
-   * Sets the close button hidden or visible. It's hidden by default.
-   *
-   * @param boolean aVisibleFlag
-   *        Specifies the intended visibility.
-   */
-  toggleCloseButton: function DVT_toggleCloseButton(aVisibleFlag) {
-    this._closeButton.setAttribute("hidden", !aVisibleFlag);
-  },
-
-  /**
    * Sets the resume button state based on the debugger active thread.
    *
    * @param string aState
    *        Either "paused" or "attached".
    */
   toggleResumeButtonState: function DVT_toggleResumeButtonState(aState) {
     // If we're paused, check and show a resume label on the button.
     if (aState == "paused") {
@@ -172,17 +158,16 @@ ToolbarView.prototype = {
    * Listener handling the step out button click event.
    */
   _onStepOutPressed: function DVT__onStepOutPressed() {
     if (DebuggerController.activeThread.paused) {
       DebuggerController.activeThread.stepOut();
     }
   },
 
-  _closeButton: null,
   _togglePanesButton: null,
   _resumeButton: null,
   _stepOverButton: null,
   _stepInButton: null,
   _stepOutButton: null,
   _chromeGlobals: null,
   _sources: null,
   _resumeTooltip: "",
--- a/browser/devtools/debugger/debugger.xul
+++ b/browser/devtools/debugger/debugger.xul
@@ -169,21 +169,16 @@
     <key id="addConditionalBreakpointKey"
          key="&debuggerUI.seMenuCondBreak.key;"
          modifiers="accel shift"
          command="addConditionalBreakpointCommand"/>
   </keyset>
 
   <vbox id="body" flex="1">
     <toolbar id="dbg-toolbar" class="devtools-toolbar">
-#ifdef XP_MACOSX
-      <toolbarbutton id="close"
-                     class="devtools-closebutton"
-                     tooltiptext="&debuggerUI.closeButton.tooltip;"/>
-#endif
       <hbox id="debugger-controls">
         <toolbarbutton id="resume"
                        class="devtools-toolbarbutton"
                        tabindex="0"/>
         <toolbarbutton id="step-over"
                        class="devtools-toolbarbutton"
                        tabindex="0"/>
         <toolbarbutton id="step-in"
@@ -203,21 +198,16 @@
       <toolbarbutton id="toggle-panes"
                      class="devtools-toolbarbutton"
                      tooltiptext="&debuggerUI.panesButton.tooltip;"
                      tabindex="0"/>
       <toolbarbutton id="debugger-options"
                      class="devtools-option-toolbarbutton"
                      tooltiptext="&debuggerUI.optsButton.tooltip;"
                      popup="debuggerPrefsContextMenu"/>
-#ifndef XP_MACOSX
-      <toolbarbutton id="close"
-                     class="devtools-closebutton"
-                     tooltiptext="&debuggerUI.closeButton.tooltip;"/>
-#endif
     </toolbar>
 
     <panel id="searchbox-panel"
            type="arrow"
            noautofocus="true"
            position="before_start">
       <vbox>
         <label class="description" value="&debuggerUI.searchPanelTitle;"/>
--- a/browser/devtools/debugger/test/Makefile.in
+++ b/browser/devtools/debugger/test/Makefile.in
@@ -8,18 +8,18 @@ srcdir          = @srcdir@
 VPATH           = @srcdir@
 relativesrcdir  = @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_BROWSER_TESTS = \
 	browser_dbg_leaktest.js \
 	browser_dbg_createChrome.js \
-	browser_dbg_debugger-tab-switch.js \
-	browser_dbg_debugger-tab-switch-window.js \
+	$(browser_dbg_debugger-tab-switch.js disabled until issues 106, 40 are fixed) \
+	$(browser_dbg_debugger-tab-switch-window.js disabled until issues 106, 40 are fixed) \
 	browser_dbg_debuggerstatement.js \
 	browser_dbg_listtabs.js \
 	browser_dbg_tabactor-01.js \
 	browser_dbg_tabactor-02.js \
 	browser_dbg_globalactor-01.js \
 	testactors.js \
 	browser_dbg_nav-01.js \
 	browser_dbg_propertyview-01.js \
@@ -42,17 +42,16 @@ MOCHITEST_BROWSER_TESTS = \
 	browser_dbg_propertyview-filter-05.js \
 	browser_dbg_propertyview-filter-06.js \
 	browser_dbg_propertyview-filter-07.js \
 	browser_dbg_propertyview-filter-08.js \
 	browser_dbg_propertyview-reexpand.js \
 	browser_dbg_reload-same-script.js \
 	browser_dbg_reload-preferred-script.js \
 	browser_dbg_pane-collapse.js \
-	browser_dbg_panesize.js \
 	browser_dbg_panesize-inner.js \
 	browser_dbg_stack-01.js \
 	browser_dbg_stack-02.js \
 	browser_dbg_stack-03.js \
 	browser_dbg_stack-04.js \
 	browser_dbg_stack-05.js \
 	browser_dbg_location-changes.js \
 	browser_dbg_location-changes-new.js \
@@ -79,17 +78,16 @@ MOCHITEST_BROWSER_TESTS = \
 	browser_dbg_bug727429_watch-expressions-01.js \
 	browser_dbg_bug727429_watch-expressions-02.js \
 	browser_dbg_bug731394_editor-contextmenu.js \
 	browser_dbg_bug786070_hide_nonenums.js \
 	browser_dbg_displayName.js \
 	browser_dbg_iframes.js \
 	browser_dbg_pause-exceptions.js \
 	browser_dbg_multiple-windows.js \
-	browser_dbg_menustatus.js \
 	browser_dbg_bfcache.js \
 	browser_dbg_breakpoint-new-script.js \
 	browser_dbg_bug737803_editor_actual_location.js \
 	browser_dbg_progress-listener-bug.js \
 	browser_dbg_chrome-debugging.js \
 	$(filter disabled-for-intermittent-failures--bug-753225, browser_dbg_createRemote.js) \
 	head.js \
 	$(NULL)
--- a/browser/devtools/debugger/test/browser_dbg_bfcache.js
+++ b/browser/devtools/debugger/test/browser_dbg_bfcache.js
@@ -15,17 +15,17 @@ var gDebugger = null;
 var gScripts = null;
 
 function test()
 {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     testInitialLoad();
   });
 }
 
 function testInitialLoad() {
   gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
     executeSoon(function() {
--- a/browser/devtools/debugger/test/browser_dbg_breakpoint-new-script.js
+++ b/browser/devtools/debugger/test/browser_dbg_breakpoint-new-script.js
@@ -12,17 +12,17 @@ var gTab = null;
 var gDebugger = null;
 var gDebuggee = null;
 
 function test()
 {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gDebuggee = aDebuggee;
 
     testAddBreakpoint();
   });
 }
 
 function testAddBreakpoint()
 {
--- a/browser/devtools/debugger/test/browser_dbg_bug723069_editor-breakpoints.js
+++ b/browser/devtools/debugger/test/browser_dbg_bug723069_editor-breakpoints.js
@@ -26,41 +26,41 @@ function test()
   let framesAdded = false;
   let resumed = false;
   let testStarted = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     resumed = true;
 
+    gDebugger.addEventListener("Debugger:SourceShown", onScriptShown);
+
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
       executeSoon(startTest);
     });
 
     executeSoon(function() {
       gDebuggee.firstCall();
     });
   });
 
   function onScriptShown(aEvent)
   {
     scriptShown = aEvent.detail.url.indexOf("-02.js") != -1;
     executeSoon(startTest);
   }
 
-  window.addEventListener("Debugger:SourceShown", onScriptShown);
-
   function startTest()
   {
     if (scriptShown && framesAdded && resumed && !testStarted) {
-      window.removeEventListener("Debugger:SourceShown", onScriptShown);
+      gDebugger.removeEventListener("Debugger:SourceShown", onScriptShown);
       testStarted = true;
       Services.tm.currentThread.dispatch({ run: performTest }, 0);
     }
   }
 
   function performTest()
   {
     gScripts = gDebugger.DebuggerView.Sources;
@@ -72,17 +72,17 @@ function test()
 
     gEditor = gDebugger.editor;
 
     isnot(gEditor.getText().indexOf("debugger"), -1,
           "The correct script was loaded initially.");
     isnot(gScripts.selectedValue, gScripts.values[0],
           "the correct script is selected");
 
-    gBreakpoints = gPane.breakpoints;
+    gBreakpoints = gPane.getAllBreakpoints();
     is(Object.keys(gBreakpoints), 0, "no breakpoints");
     ok(!gPane.getBreakpoint("foo", 3), "getBreakpoint('foo', 3) returns falsey");
 
     is(gEditor.getBreakpoints().length, 0, "no breakpoints in the editor");
 
     gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,
                              onEditorBreakpointAddFirst);
     let location = {url: gScripts.selectedValue, line: 6};
@@ -122,17 +122,17 @@ function test()
        "breakpoint1 client line is correct");
 
     executeSoon(function() {
       ok(aBreakpointClient.actor in gBreakpoints,
          "breakpoint1 client found in the list of debugger breakpoints");
       is(Object.keys(gBreakpoints).length, 1,
          "the list of debugger breakpoints holds only one breakpoint");
       is(gPane.getBreakpoint(gScripts.selectedValue, 6), aBreakpointClient,
-         "getBreakpoint(selectedScript, 2) returns the correct breakpoint");
+         "getBreakpoint returns the correct breakpoint");
 
       info("remove the first breakpoint");
       gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,
                                onEditorBreakpointRemoveFirst);
       gPane.removeBreakpoint(aBreakpointClient, onBreakpointRemoveFirst);
     });
   }
 
--- a/browser/devtools/debugger/test/browser_dbg_bug723071_editor-breakpoints-pane.js
+++ b/browser/devtools/debugger/test/browser_dbg_bug723071_editor-breakpoints-pane.js
@@ -24,41 +24,41 @@ function test()
   let framesAdded = false;
   let resumed = false;
   let testStarted = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     resumed = true;
 
+    gDebugger.addEventListener("Debugger:SourceShown", onScriptShown);
+
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
       executeSoon(startTest);
     });
 
     executeSoon(function() {
       gDebuggee.firstCall();
     });
   });
 
   function onScriptShown(aEvent)
   {
     scriptShown = aEvent.detail.url.indexOf("-02.js") != -1;
     executeSoon(startTest);
   }
 
-  window.addEventListener("Debugger:SourceShown", onScriptShown);
-
   function startTest()
   {
     if (scriptShown && framesAdded && resumed && !testStarted) {
-      window.removeEventListener("Debugger:SourceShown", onScriptShown);
+      gDebugger.removeEventListener("Debugger:SourceShown", onScriptShown);
       testStarted = true;
       Services.tm.currentThread.dispatch({ run: performTest }, 0);
     }
   }
 
   let breakpointsAdded = 0;
   let breakpointsDisabled = 0;
   let breakpointsRemoved = 0;
@@ -74,17 +74,17 @@ function test()
 
     let editor = gDebugger.editor;
 
     isnot(editor.getText().indexOf("debugger"), -1,
           "The correct script was loaded initially.");
     isnot(gScripts.selectedValue, gScripts.values[0],
           "the correct script is selected");
 
-    gBreakpoints = gPane.breakpoints;
+    gBreakpoints = gPane.getAllBreakpoints();
     is(Object.keys(gBreakpoints), 0, "no breakpoints");
     ok(!gPane.getBreakpoint("chocolate", 3), "getBreakpoint('chocolate', 3) returns falsey");
 
     is(editor.getBreakpoints().length, 0, "no breakpoints in the editor");
 
     gBreakpointsContainer = gDebugger.DebuggerView.Breakpoints;
     gBreakpointsParent = gBreakpointsContainer._container._parent;
     gBreakpointsList = gBreakpointsContainer._container._list;
--- a/browser/devtools/debugger/test/browser_dbg_bug727429_watch-expressions-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_bug727429_watch-expressions-01.js
@@ -14,17 +14,17 @@ let gDebugger = null;
 let gWatch = null;
 
 function test()
 {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gWatch = gDebugger.DebuggerView.WatchExpressions;
 
     gDebugger.DebuggerView.togglePanes({ visible: true, animated: false });
 
     executeSoon(function() {
       performTest();
     });
   });
--- a/browser/devtools/debugger/test/browser_dbg_bug727429_watch-expressions-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_bug727429_watch-expressions-02.js
@@ -15,17 +15,17 @@ let gWatch = null;
 let gVars = null;
 
 function test()
 {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gWatch = gDebugger.DebuggerView.WatchExpressions;
     gVars = gDebugger.DebuggerView.Variables;
 
     gDebugger.DebuggerView.togglePanes({ visible: true, animated: false });
     addExpressions();
     performTest();
   });
 
--- a/browser/devtools/debugger/test/browser_dbg_bug731394_editor-contextmenu.js
+++ b/browser/devtools/debugger/test/browser_dbg_bug731394_editor-contextmenu.js
@@ -23,17 +23,17 @@ function test()
   let framesAdded = false;
   let resumed = false;
   let testStarted = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     resumed = true;
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
       executeSoon(startTest);
     });
 
     executeSoon(function() {
--- a/browser/devtools/debugger/test/browser_dbg_bug737803_editor_actual_location.js
+++ b/browser/devtools/debugger/test/browser_dbg_bug737803_editor_actual_location.js
@@ -25,48 +25,48 @@ function test() {
   let framesAdded = false;
   let testStarted = false;
   let resumed = false;
 
   debug_tab_pane(TAB_URL, function (aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
     gDebuggee = aDebuggee;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     resumed = true;
 
+    gDebugger.addEventListener("Debugger:SourceShown", onScriptShown);
+
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function () {
       framesAdded = true;
       executeSoon(startTest);
     });
 
     executeSoon(function () {
       gDebuggee.firstCall();
     });
   });
 
   function onScriptShown(aEvent) {
     scriptShown = aEvent.detail.url.indexOf("-02.js") != -1;
     executeSoon(startTest);
   }
 
-  window.addEventListener("Debugger:SourceShown", onScriptShown);
-
   function startTest() {
     if (scriptShown && framesAdded && resumed && !testStarted) {
-      window.removeEventListener("Debugger:SourceShown", onScriptShown);
+      gDebugger.removeEventListener("Debugger:SourceShown", onScriptShown);
       testStarted = true;
       Services.tm.currentThread.dispatch({ run: performTest }, 0);
     }
   }
 
   function performTest() {
     gScripts = gDebugger.DebuggerView.Sources;
     gEditor = gDebugger.editor;
-    gBreakpoints = gPane.breakpoints;
+    gBreakpoints = gPane.getAllBreakpoints();
     is(Object.keys(gBreakpoints), 0, "There are no breakpoints");
 
     gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,
       onEditorBreakpointAdd);
 
     let location = { url: gScripts.selectedValue, line: 4 };
     executeSoon(function () {
       gPane.addBreakpoint(location, onBreakpointAdd);
--- a/browser/devtools/debugger/test/browser_dbg_bug740825_conditional-breakpoints-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_bug740825_conditional-breakpoints-01.js
@@ -24,17 +24,17 @@ function test()
   let framesAdded = false;
   let resumed = false;
   let testStarted = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gBreakpoints = gDebugger.DebuggerController.Breakpoints;
     gBreakpointsPane = gDebugger.DebuggerView.Breakpoints;
 
     gDebugger.DebuggerView.togglePanes({ visible: true, animated: false });
     resumed = true;
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
@@ -74,17 +74,17 @@ function test()
 
     gEditor = gDebugger.editor;
 
     isnot(gEditor.getText().indexOf("ermahgerd"), -1,
           "The correct script was loaded initially.");
     is(gScripts.selectedValue, gScripts.values[0],
           "The correct script is selected");
 
-    gBreakpoints = gPane.breakpoints;
+    gBreakpoints = gPane.getAllBreakpoints();
     is(Object.keys(gBreakpoints).length, 13, "thirteen breakpoints");
     ok(!gPane.getBreakpoint("foo", 3), "getBreakpoint('foo', 3) returns falsey");
 
     is(gEditor.getBreakpoints().length, 13, "thirteen breakpoints in the editor");
 
     executeSoon(test1);
   }
 
--- a/browser/devtools/debugger/test/browser_dbg_bug740825_conditional-breakpoints-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_bug740825_conditional-breakpoints-02.js
@@ -28,17 +28,17 @@ function test()
   let framesAdded = false;
   let resumed = false;
   let testStarted = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gBreakpoints = gDebugger.DebuggerController.Breakpoints;
     gBreakpointsPane = gDebugger.DebuggerView.Breakpoints;
 
     gDebugger.DebuggerView.togglePanes({ visible: true, animated: false });
     resumed = true;
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
@@ -78,17 +78,17 @@ function test()
 
     gEditor = gDebugger.editor;
 
     isnot(gEditor.getText().indexOf("ermahgerd"), -1,
           "The correct script was loaded initially.");
     is(gScripts.selectedValue, gScripts.values[0],
           "The correct script is selected");
 
-    gBreakpoints = gPane.breakpoints;
+    gBreakpoints = gPane.getAllBreakpoints();
     is(Object.keys(gBreakpoints), 0, "no breakpoints");
     ok(!gPane.getBreakpoint("foo", 3), "getBreakpoint('foo', 3) returns falsey");
 
     is(gEditor.getBreakpoints().length, 0, "no breakpoints in the editor");
 
     executeSoon(addBreakpoint1);
   }
 
--- a/browser/devtools/debugger/test/browser_dbg_bug786070_hide_nonenums.js
+++ b/browser/devtools/debugger/test/browser_dbg_bug786070_hide_nonenums.js
@@ -8,17 +8,17 @@ var gTab = null;
 var gDebuggee = null;
 var gDebugger = null;
 
 function test() {
   debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     testNonEnumProperties();
   });
 }
 
 function testNonEnumProperties() {
   gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
     Services.tm.currentThread.dispatch({ run: function() {
--- a/browser/devtools/debugger/test/browser_dbg_clean-exit.js
+++ b/browser/devtools/debugger/test/browser_dbg_clean-exit.js
@@ -10,17 +10,17 @@ var gTab = null;
 var gDebugger = null;
 
 const DEBUGGER_TAB_URL = EXAMPLE_URL + "browser_dbg_debuggerstatement.html";
 
 function test() {
   debug_tab_pane(DEBUGGER_TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     testCleanExit();
   });
 }
 
 function testCleanExit() {
   gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
     Services.tm.currentThread.dispatch({ run: function() {
--- a/browser/devtools/debugger/test/browser_dbg_createRemote.js
+++ b/browser/devtools/debugger/test/browser_dbg_createRemote.js
@@ -13,17 +13,17 @@ var gRemoteTimeout = null;
 var gAutoConnect = null;
 
 const TEST_URL = EXAMPLE_URL + "browser_dbg_iframes.html";
 
 function test() {
   debug_remote(TEST_URL, function(aTab, aDebuggee, aWindow) {
     gTab = aTab;
     gWindow = aWindow;
-    let gDebugger = gWindow.contentWindow;
+    let gDebugger = gWindow.panelWin;
 
     info("Current remote window x: " +
       Services.prefs.getIntPref("devtools.debugger.ui.win-x"));
     info("Current remote window y: " +
       Services.prefs.getIntPref("devtools.debugger.ui.win-y"));
     info("Current remote window width: " +
       Services.prefs.getIntPref("devtools.debugger.ui.win-width"));
     info("Current remote window height: " +
--- a/browser/devtools/debugger/test/browser_dbg_displayName.js
+++ b/browser/devtools/debugger/test/browser_dbg_displayName.js
@@ -13,17 +13,17 @@ var gDebugger = null;
 
 const TAB_URL = EXAMPLE_URL + "browser_dbg_displayName.html";
 
 function test() {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     testAnonCall();
   });
 }
 
 function testAnonCall() {
   gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
     Services.tm.currentThread.dispatch({ run: function() {
--- a/browser/devtools/debugger/test/browser_dbg_iframes.js
+++ b/browser/devtools/debugger/test/browser_dbg_iframes.js
@@ -9,20 +9,17 @@ var gPane = null;
 var gTab = null;
 
 const TEST_URL = EXAMPLE_URL + "browser_dbg_iframes.html";
 
 function test() {
   debug_tab_pane(TEST_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
-    let gDebugger = gPane.contentWindow;
-
-    is(gDebugger.document.getElementById("close").getAttribute("hidden"), "false",
-      "The close button should be visible in a normal content debugger.");
+    let gDebugger = gPane.panelWin;
 
     is(gDebugger.DebuggerController.activeThread.paused, false,
       "Should be running after debug_tab_pane.");
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       Services.tm.currentThread.dispatch({ run: function() {
 
         let frames = gDebugger.DebuggerView.StackFrames._container._list;
--- a/browser/devtools/debugger/test/browser_dbg_leaktest.js
+++ b/browser/devtools/debugger/test/browser_dbg_leaktest.js
@@ -19,17 +19,17 @@ function test()
   let framesAdded = false;
   let resumed = false;
   let testStarted = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     resumed = true;
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
       executeSoon(startTest);
     });
 
     executeSoon(function() {
--- a/browser/devtools/debugger/test/browser_dbg_location-changes-blank.js
+++ b/browser/devtools/debugger/test/browser_dbg_location-changes-blank.js
@@ -15,17 +15,17 @@ function test()
 {
   let scriptShown = false;
   let framesAdded = false;
 
   debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
       runTest();
     });
 
     gDebuggee.simpleCall();
   });
--- a/browser/devtools/debugger/test/browser_dbg_location-changes-new.js
+++ b/browser/devtools/debugger/test/browser_dbg_location-changes-new.js
@@ -15,17 +15,17 @@ function test()
 {
   let scriptShown = false;
   let framesAdded = false;
 
   debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
       runTest();
     });
 
     gDebuggee.simpleCall();
   });
--- a/browser/devtools/debugger/test/browser_dbg_location-changes.js
+++ b/browser/devtools/debugger/test/browser_dbg_location-changes.js
@@ -12,17 +12,17 @@ var gDebuggee = null;
 var gDebugger = null;
 
 function test()
 {
   debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     testSimpleCall();
   });
 }
 
 function testSimpleCall() {
   gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
     Services.tm.currentThread.dispatch({
--- a/browser/devtools/debugger/test/browser_dbg_pane-collapse.js
+++ b/browser/devtools/debugger/test/browser_dbg_pane-collapse.js
@@ -11,17 +11,17 @@ var gDebuggee = null;
 var gDebugger = null;
 var gView = null;
 
 function test() {
   debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gView = gDebugger.DebuggerView;
 
     testPanesState();
 
     gView.togglePanes({ visible: true, animated: false });
     testPaneCollapse1();
     testPaneCollapse2();
     testPanesStartupPref(closeDebuggerAndFinish);
--- a/browser/devtools/debugger/test/browser_dbg_panesize-inner.js
+++ b/browser/devtools/debugger/test/browser_dbg_panesize-inner.js
@@ -2,70 +2,75 @@
 /*
  * 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;
+    let target1 = TargetFactory.forTab(tab1);
 
-    ok(!DebuggerUI.getDebugger(),
-      "Shouldn't have a debugger pane for this tab yet.");
+    ok(!gDevTools.getPanelForTarget("jsdebugger", target1),
+      "Shouldn't have a debugger panel for this tab yet.");
 
-    let pane = DebuggerUI.toggleDebugger();
-    ok(pane, "toggleDebugger() should return a pane.");
+    let toolbox = gDevTools.openToolboxForTab(target1, "jsdebugger");
+    toolbox.once("jsdebugger-ready", function dbgReady() {
+      let dbg = gDevTools.getPanelForTarget("jsdebugger", target1);
+      ok(dbg, "We should have a debugger panel.");
 
-    let preferredSfw = Services.prefs.getIntPref("devtools.debugger.ui.stackframes-width");
-    let preferredBpw = Services.prefs.getIntPref("devtools.debugger.ui.variables-width");
-    let someWidth1, someWidth2;
+      let preferredSfw = Services.prefs.getIntPref("devtools.debugger.ui.stackframes-width");
+      let preferredBpw = Services.prefs.getIntPref("devtools.debugger.ui.variables-width");
+      let someWidth1, someWidth2;
 
-    do {
-      someWidth1 = parseInt(Math.random() * 200) + 100;
-      someWidth2 = parseInt(Math.random() * 200) + 100;
-    } while (someWidth1 == preferredSfw ||
-             someWidth2 == preferredBpw)
+      do {
+        someWidth1 = parseInt(Math.random() * 200) + 100;
+        someWidth2 = parseInt(Math.random() * 200) + 100;
+      } while (someWidth1 == preferredSfw ||
+               someWidth2 == preferredBpw)
+
+      let someWidth1 = parseInt(Math.random() * 200) + 100;
+      let someWidth2 = parseInt(Math.random() * 200) + 100;
 
-    info("Preferred stackframes width: " + preferredSfw);
-    info("Preferred variables width: " + preferredBpw);
-    info("Generated stackframes width: " + someWidth1);
-    info("Generated variables width: " + someWidth2);
+      info("Preferred stackframes width: " + preferredSfw);
+      info("Preferred variables width: " + preferredBpw);
+      info("Generated stackframes width: " + someWidth1);
+      info("Generated variables width: " + someWidth2);
+
+      let content = dbg.panelWin;
+      let stackframes;
+      let variables;
 
-    is(DebuggerUI.getDebugger(), pane,
-      "getDebugger() should return the same pane as toggleDebugger().");
+      wait_for_connect_and_resume(function() {
+        ok(content.Prefs.stackframesWidth,
+          "The debugger preferences should have a saved stackframesWidth value.");
+        ok(content.Prefs.variablesWidth,
+          "The debugger preferences should have a saved variablesWidth value.");
 
-    let content = pane.contentWindow;
-    let stackframes;
-    let variables;
+        stackframes = content.document.getElementById("stackframes+breakpoints");
+        variables = content.document.getElementById("variables+expressions");
 
-    wait_for_connect_and_resume(function() {
-      ok(content.Prefs.stackframesWidth,
-        "The debugger preferences should have a saved stackframesWidth value.");
-      ok(content.Prefs.variablesWidth,
-        "The debugger preferences should have a saved variablesWidth value.");
+        is(content.Prefs.stackframesWidth, stackframes.getAttribute("width"),
+          "The stackframes pane width should be the same as the preferred value.");
+        is(content.Prefs.variablesWidth, variables.getAttribute("width"),
+          "The variables pane width should be the same as the preferred value.");
 
-      stackframes = content.document.getElementById("stackframes+breakpoints");
-      variables = content.document.getElementById("variables+expressions");
+        stackframes.setAttribute("width", someWidth1);
+        variables.setAttribute("width", someWidth2);
+
+        removeTab(tab1);
+      }, tab1);
+
+      window.addEventListener("Debugger:Shutdown", function dbgShutdown() {
+        window.removeEventListener("Debugger:Shutdown", dbgShutdown, true);
 
-      is(content.Prefs.stackframesWidth, stackframes.getAttribute("width"),
-        "The stackframes pane width should be the same as the preferred value.");
-      is(content.Prefs.variablesWidth, variables.getAttribute("width"),
-        "The variables pane width should be the same as the preferred value.");
+        is(content.Prefs.stackframesWidth, stackframes.getAttribute("width"),
+          "The stackframes pane width should have been saved by now.");
+        is(content.Prefs.variablesWidth, variables.getAttribute("width"),
+          "The variables pane width should have been saved by now.");
 
-      stackframes.setAttribute("width", someWidth1);
-      variables.setAttribute("width", someWidth2);
+        finish();
 
-      removeTab(tab1);
+      }, true);
     });
 
-    window.addEventListener("Debugger:Shutdown", function dbgShutdown() {
-      window.removeEventListener("Debugger:Shutdown", dbgShutdown, true);
-
-      is(content.Prefs.stackframesWidth, stackframes.getAttribute("width"),
-        "The stackframes pane width should have been saved by now.");
-      is(content.Prefs.variablesWidth, variables.getAttribute("width"),
-        "The variables pane width should have been saved by now.");
-
-      finish();
-
-    }, true);
   });
 }
deleted file mode 100644
--- a/browser/devtools/debugger/test/browser_dbg_panesize.js
+++ /dev/null
@@ -1,55 +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(),
-      "Shouldn't have a debugger pane for this tab yet.");
-
-    let pane = DebuggerUI.toggleDebugger();
-    ok(pane, "toggleDebugger() should return a pane.");
-
-    let preferredHeight = Services.prefs.getIntPref("devtools.debugger.ui.height");
-    let someHeight;
-
-    do {
-      someHeight = parseInt(Math.random() * 200) + 200;
-    } while (someHeight == preferredHeight)
-
-    info("Preferred pane height: " + preferredHeight);
-    info("Generated pane height: " + someHeight);
-
-    is(DebuggerUI.getDebugger(), pane,
-      "getDebugger() should return the same pane as toggleDebugger().");
-
-    ok(DebuggerUI.preferences.height,
-      "The debugger preferences should have a saved height value.");
-
-    is(DebuggerUI.preferences.height, pane._frame.height,
-      "The debugger pane height should be the same as the preferred value.");
-
-    pane._frame.height = someHeight;
-
-    ok(DebuggerUI.preferences.height !== someHeight,
-      "Height preferences shouldn't have been updated yet.");
-
-    wait_for_connect_and_resume(function() {
-      removeTab(tab1);
-    });
-
-    window.addEventListener("Debugger:Shutdown", function dbgShutdown() {
-      window.removeEventListener("Debugger:Shutdown", dbgShutdown, true);
-
-      is(DebuggerUI.preferences.height, someHeight,
-        "Height preferences should have been updated by now.");
-
-      finish();
-
-    }, true);
-  });
-}
--- a/browser/devtools/debugger/test/browser_dbg_pause-exceptions.js
+++ b/browser/devtools/debugger/test/browser_dbg_pause-exceptions.js
@@ -15,27 +15,27 @@ var gCount = 0;
 
 requestLongerTimeout(2);
 
 function test()
 {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     gDebugger.DebuggerController.StackFrames.autoScopeExpand = true;
     gDebugger.DebuggerView.Variables.nonEnumVisible = false;
     testWithFrame();
   });
 }
 
 function testWithFrame()
 {
-  gPane.contentWindow.gClient.addOneTimeListener("paused", function() {
+  gPane.panelWin.gClient.addOneTimeListener("paused", function() {
     gDebugger.addEventListener("Debugger:FetchedVariables", function testA() {
       // We expect 2 Debugger:FetchedVariables events, one from the global object
       // scope and the regular one.
       if (++gCount < 2) {
         is(gCount, 1, "A. First Debugger:FetchedVariables event received.");
         return;
       }
       is(gCount, 2, "A. Second Debugger:FetchedVariables event received.");
@@ -43,17 +43,17 @@ function testWithFrame()
 
       is(gDebugger.DebuggerController.activeThread.state, "paused",
         "Should be paused now.");
 
       gDebugger.DebuggerView.Options._pauseOnExceptionsItem.setAttribute("checked", "true");
       gDebugger.DebuggerView.Options._togglePauseOnExceptions();
 
       gCount = 0;
-      gPane.contentWindow.gClient.addOneTimeListener("resumed", function() {
+      gPane.panelWin.gClient.addOneTimeListener("resumed", function() {
         gDebugger.addEventListener("Debugger:FetchedVariables", function testB() {
           // We expect 2 Debugger:FetchedVariables events, one from the global object
           // scope and the regular one.
           if (++gCount < 2) {
             is(gCount, 1, "B. First Debugger:FetchedVariables event received.");
             return;
           }
           is(gCount, 2, "B. Second Debugger:FetchedVariables event received.");
@@ -91,17 +91,17 @@ function testWithFrame()
   });
 
   EventUtils.sendMouseEvent({ type: "click" },
     content.document.querySelector("button"),
     content.window);
 }
 
 function resumeAndFinish() {
-  gPane.contentWindow.gClient.addOneTimeListener("resumed", function() {
+  gPane.panelWin.gClient.addOneTimeListener("resumed", function() {
     Services.tm.currentThread.dispatch({ run: function() {
 
       closeDebuggerAndFinish(false);
     }}, 0);
   });
 
   // Resume to let the exception reach it's catch clause.
   gDebugger.DebuggerController.activeThread.resume();
--- a/browser/devtools/debugger/test/browser_dbg_pause-resume.js
+++ b/browser/devtools/debugger/test/browser_dbg_pause-resume.js
@@ -10,17 +10,17 @@ var gDebugger = null;
 var gView = null;
 var gLH = null;
 var gL10N = null;
 
 function test() {
   debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gView = gDebugger.DebuggerView;
     gLH = gDebugger.LayoutHelpers;
     gL10N = gDebugger.L10N;
 
     testPause();
   });
 }
 
--- a/browser/devtools/debugger/test/browser_dbg_progress-listener-bug.js
+++ b/browser/devtools/debugger/test/browser_dbg_progress-listener-bug.js
@@ -13,17 +13,17 @@ var gOldListener = null;
 const TEST_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
 
 function test() {
   installListener();
 
   debug_tab_pane(TEST_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
-    let gDebugger = gPane.contentWindow;
+    let gDebugger = gPane.panelWin;
 
     is(gDebugger.DebuggerController._isInitialized, true,
       "Controller should be initialized after debug_tab_pane.");
     is(gDebugger.DebuggerView._isInitialized, true,
       "View should be initialized after debug_tab_pane.");
 
     closeDebuggerAndFinish();
   });
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-01.js
@@ -8,17 +8,17 @@ var gTab = null;
 var gDebuggee = null;
 var gDebugger = null;
 
 function test() {
   debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     testSimpleCall();
   });
 }
 
 function testSimpleCall() {
   gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
     Services.tm.currentThread.dispatch({ run: function() {
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-02.js
@@ -8,17 +8,17 @@ var gTab = null;
 var gDebuggee = null;
 var gDebugger = null;
 
 function test() {
   debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     testSimpleCall();
   });
 }
 
 function testSimpleCall() {
   gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
     Services.tm.currentThread.dispatch({ run: function() {
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-03.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-03.js
@@ -8,17 +8,17 @@ var gTab = null;
 var gDebuggee = null;
 var gDebugger = null;
 
 function test() {
   debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     testSimpleCall();
   });
 }
 
 function testSimpleCall() {
   gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
     Services.tm.currentThread.dispatch({ run: function() {
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-04.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-04.js
@@ -8,17 +8,17 @@ var gTab = null;
 var gDebuggee = null;
 var gDebugger = null;
 
 function test() {
   debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     testSimpleCall();
   });
 }
 
 function testSimpleCall() {
   gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
     Services.tm.currentThread.dispatch({ run: function() {
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-05.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-05.js
@@ -8,17 +8,17 @@ var gTab = null;
 var gDebuggee = null;
 var gDebugger = null;
 
 function test() {
   debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     testSimpleCall();
   });
 }
 
 function testSimpleCall() {
   gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
     Services.tm.currentThread.dispatch({ run: function() {
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-06.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-06.js
@@ -8,17 +8,17 @@ var gTab = null;
 var gDebuggee = null;
 var gDebugger = null;
 
 function test() {
   debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     testSimpleCall();
   });
 }
 
 function testSimpleCall() {
   gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
     Services.tm.currentThread.dispatch({ run: function() {
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-07.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-07.js
@@ -12,17 +12,17 @@ var gPane = null;
 var gTab = null;
 var gDebugger = null;
 
 function test()
 {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     testFrameParameters();
   });
 }
 
 function testFrameParameters()
 {
   dump("Started testFrameParameters!\n");
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-08.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-08.js
@@ -12,17 +12,17 @@ var gPane = null;
 var gTab = null;
 var gDebugger = null;
 
 function test()
 {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     testFrameParameters();
   });
 }
 
 function testFrameParameters()
 {
   dump("Started testFrameParameters!\n");
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-09.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-09.js
@@ -14,17 +14,17 @@ var gDebugger = null;
 
 requestLongerTimeout(2);
 
 function test()
 {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     gDebugger.DebuggerController.StackFrames.autoScopeExpand = true;
     gDebugger.DebuggerView.Variables.nonEnumVisible = false;
     testFrameParameters();
   });
 }
 
 function testFrameParameters()
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-10.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-10.js
@@ -14,17 +14,17 @@ var gDebugger = null;
 
 requestLongerTimeout(2);
 
 function test()
 {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     gDebugger.DebuggerController.StackFrames.autoScopeExpand = true;
     gDebugger.DebuggerView.Variables.nonEnumVisible = false;
     testWithFrame();
   });
 }
 
 function testWithFrame()
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-data.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-data.js
@@ -13,17 +13,17 @@ var gVariablesView = null;
 var gScope = null;
 var gVariable = null;
 
 function test()
 {
   debug_tab_pane(TAB1_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gVariablesView = gDebugger.DebuggerView.Variables;
 
     testVariablesView();
   });
 }
 
 function testVariablesView()
 {
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-edit-watch.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-edit-watch.js
@@ -19,17 +19,17 @@ var gVars = null;
 
 requestLongerTimeout(2);
 
 function test() {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gWatch = gDebugger.DebuggerView.WatchExpressions;
     gVars = gDebugger.DebuggerView.Variables;
 
     gDebugger.DebuggerController.StackFrames.autoScopeExpand = true;
     gDebugger.DebuggerView.Variables.nonEnumVisible = false;
     testFrameEval();
   });
 }
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-edit.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-edit.js
@@ -17,17 +17,17 @@ var gDebugger = null;
 
 requestLongerTimeout(2);
 
 function test() {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     gDebugger.DebuggerController.StackFrames.autoScopeExpand = true;
     gDebugger.DebuggerView.Variables.nonEnumVisible = false;
     testFrameEval();
   });
 }
 
 function testFrameEval() {
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-filter-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-filter-01.js
@@ -16,17 +16,17 @@ var gSearchBox = null;
 
 requestLongerTimeout(2);
 
 function test()
 {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gDebuggee = aDebuggee;
 
     gDebugger.DebuggerController.StackFrames.autoScopeExpand = true;
     gDebugger.DebuggerView.Variables.delayedSearch = false;
     testSearchbox();
     prepareVariables(testVariablesFiltering);
   });
 }
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-filter-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-filter-02.js
@@ -16,17 +16,17 @@ var gSearchBox = null;
 
 requestLongerTimeout(2);
 
 function test()
 {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gDebuggee = aDebuggee;
 
     gDebugger.DebuggerController.StackFrames.autoScopeExpand = true;
     gDebugger.DebuggerView.Variables.delayedSearch = false;
     testSearchbox();
     prepareVariables(testVariablesFiltering);
   });
 }
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-filter-03.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-filter-03.js
@@ -19,17 +19,17 @@ function test()
   gPrevPref = Services.prefs.getBoolPref(
     "devtools.debugger.ui.variables-searchbox-visible");
   Services.prefs.setBoolPref(
     "devtools.debugger.ui.variables-searchbox-visible", false);
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gDebuggee = aDebuggee;
 
     testSearchbox();
     testPref();
   });
 }
 
 function testSearchbox()
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-filter-04.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-filter-04.js
@@ -19,17 +19,17 @@ function test()
   gPrevPref = Services.prefs.getBoolPref(
     "devtools.debugger.ui.variables-searchbox-visible");
   Services.prefs.setBoolPref(
     "devtools.debugger.ui.variables-searchbox-visible", true);
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gDebuggee = aDebuggee;
 
     testSearchbox();
     testPref();
   });
 }
 
 function testSearchbox()
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-filter-05.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-filter-05.js
@@ -16,17 +16,17 @@ var gSearchBox = null;
 
 requestLongerTimeout(2);
 
 function test()
 {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gDebuggee = aDebuggee;
 
     gDebugger.DebuggerController.StackFrames.autoScopeExpand = true;
     gDebugger.DebuggerView.Variables.delayedSearch = false;
     prepareVariables(testVariablesFiltering);
   });
 }
 
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-filter-06.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-filter-06.js
@@ -16,17 +16,17 @@ var gSearchBox = null;
 
 requestLongerTimeout(2);
 
 function test()
 {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gDebuggee = aDebuggee;
 
     gDebugger.DebuggerController.StackFrames.autoScopeExpand = false;
     gDebugger.DebuggerView.Variables.delayedSearch = false;
     prepareVariables(testVariablesFiltering);
   });
 }
 
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-filter-07.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-filter-07.js
@@ -16,17 +16,17 @@ var gSearchBox = null;
 
 requestLongerTimeout(2);
 
 function test()
 {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gDebuggee = aDebuggee;
 
     gDebugger.DebuggerController.StackFrames.autoScopeExpand = true;
     gDebugger.DebuggerView.Variables.delayedSearch = false;
     prepareVariables(testVariablesFiltering);
   });
 }
 
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-filter-08.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-filter-08.js
@@ -16,17 +16,17 @@ var gSearchBox = null;
 
 requestLongerTimeout(2);
 
 function test()
 {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gDebuggee = aDebuggee;
 
     gDebugger.DebuggerController.StackFrames.autoScopeExpand = true;
     gDebugger.DebuggerView.Variables.delayedSearch = false;
     prepareVariables(testVariablesFiltering);
   });
 }
 
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-reexpand.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-reexpand.js
@@ -15,17 +15,17 @@ var gDebuggee = null;
 
 requestLongerTimeout(2);
 
 function test()
 {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gDebuggee = aDebuggee;
 
     addBreakpoint();
   });
 }
 
 function addBreakpoint()
 {
--- a/browser/devtools/debugger/test/browser_dbg_reload-preferred-script.js
+++ b/browser/devtools/debugger/test/browser_dbg_reload-preferred-script.js
@@ -22,17 +22,17 @@ function test()
   let scriptShownUrl = null;
   let resumed = false;
   let testStarted = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gView = gDebugger.DebuggerView;
     resumed = true;
 
     gView.Sources.preferredSource = EXAMPLE_URL + expectedScript;
     startTest();
   });
 
   function onScriptShown(aEvent)
--- a/browser/devtools/debugger/test/browser_dbg_reload-same-script.js
+++ b/browser/devtools/debugger/test/browser_dbg_reload-same-script.js
@@ -23,17 +23,17 @@ function test()
   let scriptShownUrl = null;
   let resumed = false;
   let testStarted = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gView = gDebugger.DebuggerView;
     resumed = true;
 
     startTest();
   });
 
   function onScriptShown(aEvent)
   {
--- a/browser/devtools/debugger/test/browser_dbg_script-switching.js
+++ b/browser/devtools/debugger/test/browser_dbg_script-switching.js
@@ -20,17 +20,17 @@ function test()
   let framesAdded = false;
   let resumed = false;
   let testStarted = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     resumed = true;
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
       executeSoon(startTest);
     });
 
     executeSoon(function() {
--- a/browser/devtools/debugger/test/browser_dbg_scripts-searching-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_scripts-searching-01.js
@@ -19,17 +19,17 @@ function test()
 {
   let scriptShown = false;
   let framesAdded = false;
 
   debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gDebugger.SourceResults.prototype.alwaysExpand = false;
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
       runTest();
     });
 
     gDebuggee.simpleCall();
--- a/browser/devtools/debugger/test/browser_dbg_scripts-searching-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_scripts-searching-02.js
@@ -21,17 +21,17 @@ function test()
 {
   let scriptShown = false;
   let framesAdded = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gDebugger.SourceResults.prototype.alwaysExpand = false;
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
       runTest();
     });
 
     gDebuggee.firstCall();
--- a/browser/devtools/debugger/test/browser_dbg_scripts-searching-03.js
+++ b/browser/devtools/debugger/test/browser_dbg_scripts-searching-03.js
@@ -22,17 +22,17 @@ function test()
 {
   let scriptShown = false;
   let framesAdded = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gDebugger.SourceResults.prototype.alwaysExpand = false;
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
       runTest();
     });
 
     gDebuggee.firstCall();
--- a/browser/devtools/debugger/test/browser_dbg_scripts-searching-04.js
+++ b/browser/devtools/debugger/test/browser_dbg_scripts-searching-04.js
@@ -22,17 +22,17 @@ function test()
 {
   let scriptShown = false;
   let framesAdded = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gDebugger.SourceResults.prototype.alwaysExpand = false;
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
       runTest();
     });
 
     gDebuggee.firstCall();
--- a/browser/devtools/debugger/test/browser_dbg_scripts-searching-05.js
+++ b/browser/devtools/debugger/test/browser_dbg_scripts-searching-05.js
@@ -22,17 +22,17 @@ function test()
 {
   let scriptShown = false;
   let framesAdded = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gDebugger.SourceResults.prototype.alwaysExpand = false;
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
       runTest();
     });
 
     gDebuggee.firstCall();
--- a/browser/devtools/debugger/test/browser_dbg_scripts-searching-06.js
+++ b/browser/devtools/debugger/test/browser_dbg_scripts-searching-06.js
@@ -22,17 +22,17 @@ function test()
 {
   let scriptShown = false;
   let framesAdded = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gDebugger.SourceResults.prototype.alwaysExpand = false;
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
       runTest();
     });
 
     gDebuggee.firstCall();
--- a/browser/devtools/debugger/test/browser_dbg_scripts-searching-07.js
+++ b/browser/devtools/debugger/test/browser_dbg_scripts-searching-07.js
@@ -23,17 +23,17 @@ function test()
 {
   let scriptShown = false;
   let framesAdded = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gDebugger.SourceResults.prototype.alwaysExpand = false;
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
       runTest();
     });
 
     gDebuggee.firstCall();
--- a/browser/devtools/debugger/test/browser_dbg_scripts-searching-08.js
+++ b/browser/devtools/debugger/test/browser_dbg_scripts-searching-08.js
@@ -22,17 +22,17 @@ function test()
 {
   let scriptShown = false;
   let framesAdded = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gDebugger.SourceResults.prototype.alwaysExpand = false;
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
       runTest();
     });
 
     gDebuggee.firstCall();
--- a/browser/devtools/debugger/test/browser_dbg_scripts-searching-popup.js
+++ b/browser/devtools/debugger/test/browser_dbg_scripts-searching-popup.js
@@ -13,17 +13,17 @@ var gSearchBox = null;
 var gSearchBoxPanel = null;
 
 function test()
 {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       runTest();
     });
 
     gDebuggee.firstCall();
   });
 }
--- a/browser/devtools/debugger/test/browser_dbg_scripts-sorting.js
+++ b/browser/devtools/debugger/test/browser_dbg_scripts-sorting.js
@@ -8,17 +8,17 @@ var gTab = null;
 var gDebuggee = null;
 var gDebugger = null;
 
 function test() {
   debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     testSimpleCall();
   });
 }
 
 function testSimpleCall() {
   gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
     Services.tm.currentThread.dispatch({ run: function() {
--- a/browser/devtools/debugger/test/browser_dbg_select-line.js
+++ b/browser/devtools/debugger/test/browser_dbg_select-line.js
@@ -19,17 +19,17 @@ var gDebugger = null;
 var gScripts = null;
 
 function test()
 {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     testSelectLine();
   });
 }
 
 function testSelectLine() {
   gDebugger.DebuggerController.activeThread.addOneTimeListener("scriptsadded", function() {
     Services.tm.currentThread.dispatch({ run: function() {
--- a/browser/devtools/debugger/test/browser_dbg_stack-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_stack-01.js
@@ -9,17 +9,17 @@ var gTab = null;
 var gDebuggee = null;
 var gDebugger = null;
 
 function test() {
   debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     testSimpleCall();
   });
 }
 
 function testSimpleCall() {
   gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
     Services.tm.currentThread.dispatch({ run: function() {
--- a/browser/devtools/debugger/test/browser_dbg_stack-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_stack-02.js
@@ -9,17 +9,17 @@ var gTab = null;
 var gDebuggee = null;
 var gDebugger = null;
 
 function test() {
   debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     testEvalCall();
   });
 }
 
 function testEvalCall() {
   gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
     Services.tm.currentThread.dispatch({ run: function() {
--- a/browser/devtools/debugger/test/browser_dbg_stack-03.js
+++ b/browser/devtools/debugger/test/browser_dbg_stack-03.js
@@ -9,17 +9,17 @@ var gTab = null;
 var gDebuggee = null;
 var gDebugger = null;
 
 function test() {
   debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     testRecurse();
   });
 }
 
 function testRecurse() {
   gDebuggee.gRecurseLimit = (gDebugger.gCallStackPageSize * 2) + 1;
 
--- a/browser/devtools/debugger/test/browser_dbg_stack-04.js
+++ b/browser/devtools/debugger/test/browser_dbg_stack-04.js
@@ -9,17 +9,17 @@ var gTab = null;
 var gDebuggee = null;
 var gDebugger = null;
 
 function test() {
   debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     testEvalCallResume();
   });
 }
 
 function testEvalCallResume() {
   gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
     Services.tm.currentThread.dispatch({ run: function() {
--- a/browser/devtools/debugger/test/browser_dbg_stack-05.js
+++ b/browser/devtools/debugger/test/browser_dbg_stack-05.js
@@ -17,17 +17,17 @@ var gDebugger = null;
 function test() {
   let scriptShown = false;
   let framesAdded = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
       runTest();
     });
 
     gDebuggee.firstCall();
   });
--- a/browser/devtools/debugger/test/browser_dbg_update-editor-mode.js
+++ b/browser/devtools/debugger/test/browser_dbg_update-editor-mode.js
@@ -24,17 +24,17 @@ function test()
   let framesAdded = false;
   let testStarted = false;
   let resumed = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
-    gDebugger = gPane.contentWindow;
+    gDebugger = gPane.panelWin;
     gScripts = gDebugger.DebuggerView.Sources._container;
     resumed = true;
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
       executeSoon(startTest);
     });
 
--- a/browser/devtools/debugger/test/head.js
+++ b/browser/devtools/debugger/test/head.js
@@ -9,16 +9,20 @@ const Cu = Components.utils;
 let tempScope = {};
 Cu.import("resource://gre/modules/devtools/dbg-server.jsm", tempScope);
 Cu.import("resource://gre/modules/devtools/dbg-client.jsm", tempScope);
 Cu.import("resource://gre/modules/Services.jsm", tempScope);
 let DebuggerServer = tempScope.DebuggerServer;
 let DebuggerTransport = tempScope.DebuggerTransport;
 let DebuggerClient = tempScope.DebuggerClient;
 let Services = tempScope.Services;
+Cu.import("resource:///modules/devtools/gDevTools.jsm", tempScope);
+let gDevTools = tempScope.gDevTools;
+Cu.import("resource:///modules/devtools/Target.jsm", tempScope);
+let TargetFactory = tempScope.TargetFactory;
 
 const EXAMPLE_URL = "http://example.com/browser/browser/devtools/debugger/test/";
 const TAB1_URL = EXAMPLE_URL + "browser_dbg_tab1.html";
 const TAB2_URL = EXAMPLE_URL + "browser_dbg_tab2.html";
 const STACK_URL = EXAMPLE_URL + "browser_dbg_stack.html";
 
 // Enable logging and remote debugging for the relevant tests.
 let gEnableRemote = Services.prefs.getBoolPref("devtools.debugger.remote-enabled");
@@ -81,123 +85,131 @@ function addTab(aURL, aOnload, aWindow) 
 function removeTab(aTab, aWindow) {
   let targetWindow = aWindow || window;
   let targetBrowser = targetWindow.gBrowser;
 
   targetBrowser.removeTab(aTab);
 }
 
 function closeDebuggerAndFinish(aRemoteFlag, aCallback, aWindow) {
-  let targetWindow = aWindow || window;
-  let debuggerUI = targetWindow.DebuggerUI;
-
   let debuggerClosed = false;
   let debuggerDisconnected = false;
+  // let targetWindow = aWindow || window;
+  ok(gTab, "There is a gTab to use for getting a toolbox reference");
+  let target = TargetFactory.forTab(gTab);
+
+  // let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
+  window.addEventListener("Debugger:Shutdown", function cleanup() {
+    window.removeEventListener("Debugger:Shutdown", cleanup, false);
+    debuggerDisconnected = true;
+    _maybeFinish();
+  }, false);
+
+  let toolbox = gDevTools.getToolboxForTarget(target);
+  toolbox.once("destroyed", function() {
+    debuggerClosed = true;
+    _maybeFinish();
+  });
+  toolbox.destroy();
 
   function _maybeFinish() {
     if (debuggerClosed && debuggerDisconnected) {
       if (!aCallback)
         aCallback = finish;
       aCallback();
     }
   }
 
-  debuggerUI.chromeWindow.addEventListener("Debugger:Shutdown", function cleanup() {
-    debuggerUI.chromeWindow.removeEventListener("Debugger:Shutdown", cleanup, false);
-    debuggerDisconnected = true;
-    _maybeFinish();
-  }, false);
-  if (!aRemoteFlag) {
-    debuggerUI.getDebugger().close(function() {
-      debuggerClosed = true;
-      _maybeFinish();
-    });
-  } else {
-    debuggerClosed = true;
-    debuggerUI.getRemoteDebugger().close();
-  }
+  // if (!aRemoteFlag) {
+  //   dbg.getDebugger().close(function() {
+  //     debuggerClosed = true;
+  //     _maybeFinish();
+  //   });
+  // } else {
+  //   debuggerClosed = true;
+  //   dbg.getRemoteDebugger().close();
+  // }
 }
 
 function get_tab_actor_for_url(aClient, aURL, aCallback) {
   aClient.listTabs(function(aResponse) {
     for each (let tab in aResponse.tabs) {
       if (tab.url == aURL) {
         aCallback(tab);
         return;
       }
     }
   });
 }
 
 function attach_tab_actor_for_url(aClient, aURL, aCallback) {
   get_tab_actor_for_url(aClient, aURL, function(actor) {
-    aClient.request({ to: actor.actor, type: "attach" }, function(aResponse) {
+    aClient.attachTab(actor.actor, function(aResponse) {
       aCallback(actor, aResponse);
     });
   });
 }
 
 function attach_thread_actor_for_url(aClient, aURL, aCallback) {
   attach_tab_actor_for_url(aClient, aURL, function(aTabActor, aResponse) {
-    aClient.request({ "to": actor.threadActor, "type": "attach" }, function(aResponse) {
+    aClient.attachThread(actor.threadActor, function(aResponse, aThreadClient) {
       // We don't care about the pause right now (use
       // get_actor_for_url() if you do), so resume it.
-      aClient.request({ to: actor.threadActor, type: "resume" }, function(aResponse) {
+      aThreadClient.resume(function(aResponse) {
         aCallback(actor);
       });
     });
   });
 }
 
-function wait_for_connect_and_resume(aOnDebugging, aWindow) {
-  let targetWindow = aWindow || window;
-  let targetDocument = targetWindow.document;
-
-  targetDocument.addEventListener("Debugger:Connected", function dbgConnected(aEvent) {
-    targetDocument.removeEventListener("Debugger:Connected", dbgConnected, true);
-
+function wait_for_connect_and_resume(aOnDebugging, aTab) {
+  let target = TargetFactory.forTab(aTab);
+  let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
+  dbg.once("connected", function dbgConnected() {
     // Wait for the initial resume...
-    aEvent.target.ownerDocument.defaultView.gClient.addOneTimeListener("resumed", function() {
+    dbg.panelWin.gClient.addOneTimeListener("resumed", function() {
       aOnDebugging();
     });
-  }, true);
+  });
 }
 
 function debug_tab_pane(aURL, aOnDebugging) {
   let tab = addTab(aURL, function() {
     gBrowser.selectedTab = gTab;
-    let debuggee = tab.linkedBrowser.contentWindow.wrappedJSObject;
-
-    let pane = DebuggerUI.toggleDebugger();
-    pane._frame.addEventListener("Debugger:Connected", function dbgConnected() {
-      pane._frame.removeEventListener("Debugger:Connected", dbgConnected, true);
+    let debuggee = gBrowser.selectedTab.linkedBrowser.contentWindow.wrappedJSObject;
 
-      // Wait for the initial resume...
-      pane.contentWindow.gClient.addOneTimeListener("resumed", function() {
-        pane.contentWindow.DebuggerView.Variables.lazyEmpty = false;
-        aOnDebugging(tab, debuggee, pane);
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    let toolbox = gDevTools.openToolboxForTab(target, "jsdebugger");
+    toolbox.once("jsdebugger-ready", function dbgReady() {
+      let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
+      dbg.once("connected", function() {
+        // Wait for the initial resume...
+        dbg.panelWin.gClient.addOneTimeListener("resumed", function() {
+          dbg._view.Variables.lazyEmpty = false;
+          aOnDebugging(tab, debuggee, dbg);
+        });
       });
-    }, true);
+    });
   });
 }
 
 function debug_remote(aURL, aOnDebugging, aBeforeTabAdded) {
   // Make any necessary preparations (start the debugger server etc.)
   aBeforeTabAdded();
 
   let tab = addTab(aURL, function() {
     gBrowser.selectedTab = gTab;
     let debuggee = tab.linkedBrowser.contentWindow.wrappedJSObject;
 
     let win = DebuggerUI.toggleRemoteDebugger();
     win._dbgwin.addEventListener("Debugger:Connected", function dbgConnected() {
       win._dbgwin.removeEventListener("Debugger:Connected", dbgConnected, true);
 
       // Wait for the initial resume...
-      win.contentWindow.gClient.addOneTimeListener("resumed", function() {
+      win.panelWin.gClient.addOneTimeListener("resumed", function() {
         win._dbgwin.DebuggerView.Variables.lazyEmpty = false;
         aOnDebugging(tab, debuggee, win);
       });
     }, true);
   });
 }
 
 function debug_chrome(aURL, aOnClosing, aOnDebugging) {
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/Makefile.in
@@ -0,0 +1,18 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DEPTH		= @DEPTH@
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+TEST_DIRS += test
+
+include $(topsrcdir)/config/rules.mk
+
+libs::
+	$(NSINSTALL) $(srcdir)/*.jsm $(FINAL_TARGET)/modules/devtools
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/Sidebar.jsm
@@ -0,0 +1,191 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const Cc = Components.classes;
+const Cu = Components.utils;
+const Ci = Components.interfaces;
+
+this.EXPORTED_SYMBOLS = ["ToolSidebar"];
+
+Cu.import("resource:///modules/devtools/EventEmitter.jsm");
+
+const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+
+/**
+ * ToolSidebar provides methods to register tabs in the sidebar.
+ * It's assumed that the sidebar contains a xul:tabbox.
+ *
+ * @param {Node} tabbox
+ *  <tabbox> node;
+ * @param {ToolPanel} panel
+ *  Related ToolPanel instance;
+ * @param {Boolean} showTabstripe
+ *  Show the tabs.
+ */
+this.ToolSidebar = function ToolSidebar(tabbox, panel, showTabstripe=true)
+{
+  new EventEmitter(this);
+
+  this._tabbox = tabbox;
+  this._panelDoc = this._tabbox.ownerDocument;
+  this._toolPanel = panel;
+
+  this._tabbox.tabpanels.addEventListener("select", this, true);
+
+  this._tabs = new Map();
+
+  if (!showTabstripe) {
+    this._tabbox.setAttribute("hidetabs", "true");
+  }
+}
+
+ToolSidebar.prototype = {
+  /**
+   * Register a tab. A tab is a document.
+   * The document must have a title, which will be used as the name of the tab.
+   *
+   * @param {string} tab uniq id
+   * @param {string} url
+   */
+  addTab: function ToolSidebar_addTab(id, url, selected=false) {
+    let iframe = this._panelDoc.createElementNS(XULNS, "iframe");
+    iframe.className = "iframe-" + id;
+    iframe.setAttribute("flex", "1");
+    iframe.setAttribute("src", url);
+
+    let tab = this._tabbox.tabs.appendItem();
+
+    let onIFrameLoaded = function() {
+      tab.setAttribute("label", iframe.contentDocument.title);
+      iframe.removeEventListener("DOMContentLoaded", onIFrameLoaded, true);
+      if ("setPanel" in iframe.contentWindow) {
+        iframe.contentWindow.setPanel(this._toolPanel, iframe);
+      }
+      this.emit(id + "-ready");
+    }.bind(this);
+
+    iframe.addEventListener("DOMContentLoaded", onIFrameLoaded, true);
+
+    let tabpanel = this._panelDoc.createElementNS(XULNS, "tabpanel");
+    tabpanel.setAttribute("id", "sidebar-panel-" + id);
+    tabpanel.appendChild(iframe);
+    this._tabbox.tabpanels.appendChild(tabpanel);
+
+    tab.linkedPanel = "sidebar-panel-" + id;
+
+    // We store the index of this tab.
+    this._tabs.set(id, tab);
+
+    if (selected) {
+      // For some reason I don't understand, if we call this.select in this
+      // event loop (after inserting the tab), the tab will never get the
+      // the "selected" attribute set to true.
+      this._panelDoc.defaultView.setTimeout(function() {
+        this.select(id);
+      }.bind(this), 0);
+    }
+
+    this.emit("new-tab-registered", id);
+  },
+
+  /**
+   * Select a specific tab.
+   */
+  select: function ToolSidebar_select(id) {
+    let tab = this._tabs.get(id);
+    if (tab) {
+      this._tabbox.selectedTab = tab;
+    }
+  },
+
+  /**
+   * Return the id of the selected tab.
+   */
+  getCurrentTabID: function ToolSidebar_getCurrentTabID() {
+    let currentID = null;
+    for (let [id, tab] of this._tabs) {
+      if (this._tabbox.tabs.selectedItem == tab) {
+        currentID = id;
+        break;
+      }
+    }
+    return currentID;
+  },
+
+  /**
+   * Event handler.
+   */
+  handleEvent: function ToolSidebar_eventHandler(event) {
+    if (event.type == "select") {
+      let previousTool = this._currentTool;
+      this._currentTool = this.getCurrentTabID();
+      if (previousTool) {
+        this.emit(previousTool + "-unselected");
+      }
+
+      this.emit(this._currentTool + "-selected");
+      this.emit("select", this._currentTool);
+    }
+  },
+
+
+  /**
+   * Toggle sidebar's visibility state.
+   */
+  toggle: function ToolSidebar_toggle() {
+    if (this._tabbox.hasAttribute("hidden")) {
+      this.show();
+    } else {
+      this.hide();
+    }
+  },
+
+  /**
+   * Show the sidebar.
+   */
+  show: function ToolSidebar_show() {
+    this._tabbox.removeAttribute("hidden");
+  },
+
+  /**
+   * Show the sidebar.
+   */
+  hide: function ToolSidebar_hide() {
+    this._tabbox.setAttribute("hidden", "true");
+  },
+
+  /**
+   * Return the window containing the tab content.
+   */
+  getWindowForTab: function ToolSidebar_getWindowForTab(id) {
+    if (!this._tabs.has(id)) {
+      return null;
+    }
+
+    let panel = this._panelDoc.getElementById(this._tabs.get(id).linkedPanel);
+    return panel.firstChild.contentWindow;
+  },
+
+  /**
+   * Clean-up.
+   */
+  destroy: function ToolSidebar_destroy() {
+    this._tabbox.removeEventListener("select", this, true);
+
+    while (this._tabbox.tabpanels.hasChildNodes()) {
+      this._tabbox.tabpanels.removeChild(this._tabbox.tabpanels.firstChild);
+    }
+
+    while (this._tabbox.tabs.hasChildNodes()) {
+      this._tabbox.tabs.removeChild(this._tabbox.tabs.firstChild);
+    }
+
+    this._tabs = null;
+    this._tabbox = null;
+    this._panelDoc = null;
+    this._toolPanel = null;
+  },
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/Target.jsm
@@ -0,0 +1,385 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = [ "TargetFactory" ];
+
+const Cu = Components.utils;
+const Ci = Components.interfaces;
+Cu.import("resource:///modules/devtools/EventEmitter.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+
+const targets = new WeakMap();
+
+/**
+ * Functions for creating Targets
+ */
+this.TargetFactory = {
+  /**
+   * Construct a Target
+   * @param {XULTab} tab
+   *        The tab to use in creating a new target
+   * @return A target object
+   */
+  forTab: function TF_forTab(tab) {
+    let target = targets.get(tab);
+    if (target == null) {
+      target = new TabTarget(tab);
+      targets.set(tab, target);
+    }
+    return target;
+  },
+
+  /**
+   * Creating a target for a tab that is being closed is a problem because it
+   * allows a leak as a result of coming after the close event which normally
+   * clears things up. This function allows us to ask if there is a known
+   * target for a tab without creating a target
+   * @return true/false
+   */
+  isKnownTab: function TF_isKnownTab(tab) {
+    return targets.has(tab);
+  },
+
+  /**
+   * Construct a Target
+   * @param {nsIDOMWindow} window
+   *        The chromeWindow to use in creating a new target
+   * @return A target object
+   */
+  forWindow: function TF_forWindow(window) {
+    let target = targets.get(window);
+    if (target == null) {
+      target = new WindowTarget(window);
+      targets.set(window, target);
+    }
+    return target;
+  },
+
+  /**
+   * Construct a Target for a remote global
+   * @param {Object} form
+   *        The serialized form of a debugging protocol actor.
+   * @param {DebuggerClient} client
+   *        The debuger client instance to communicate with the server.
+   * @param {boolean} chrome
+   *        A flag denoting that the debugging target is the remote process as a
+   *        whole and not a single tab.
+   * @return A target object
+   */
+  forRemote: function TF_forRemote(form, client, chrome) {
+    let target = targets.get(form);
+    if (target == null) {
+      target = new RemoteTarget(form, client, chrome);
+      targets.set(form, target);
+    }
+    return target;
+  },
+
+  /**
+   * Get all of the targets known to some browser instance (local if null)
+   * @return An array of target objects
+   */
+  allTargets: function TF_allTargets() {
+    let windows = [];
+    let wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+                       .getService(Components.interfaces.nsIWindowMediator);
+    let en = wm.getXULWindowEnumerator(null);
+    while (en.hasMoreElements()) {
+      windows.push(en.getNext());
+    }
+
+    return windows.map(function(window) {
+      return TargetFactory.forWindow(window);
+    });
+  },
+};
+
+/**
+ * The 'version' property allows the developer tools equivalent of browser
+ * detection. Browser detection is evil, however while we don't know what we
+ * will need to detect in the future, it is an easy way to postpone work.
+ * We should be looking to use 'supports()' in place of version where
+ * possible.
+ */
+function getVersion() {
+  // FIXME: return something better
+  return 20;
+}
+
+/**
+ * A better way to support feature detection, but we're not yet at a place
+ * where we have the features well enough defined for this to make lots of
+ * sense.
+ */
+function supports(feature) {
+  // FIXME: return something better
+  return false;
+};
+
+/**
+ * A Target represents something that we can debug. Targets are generally
+ * read-only. Any changes that you wish to make to a target should be done via
+ * a Tool that attaches to the target. i.e. a Target is just a pointer saying
+ * "the thing to debug is over there".
+ *
+ * Providing a generalized abstraction of a web-page or web-browser (available
+ * either locally or remotely) is beyond the scope of this class (and maybe
+ * also beyond the scope of this universe) However Target does attempt to
+ * abstract some common events and read-only properties common to many Tools.
+ *
+ * Supported read-only properties:
+ * - name, isRemote, url
+ *
+ * Target extends EventEmitter and provides support for the following events:
+ * - close: The target window has been closed. All tools attached to this
+ *     target should close. This event is not currently cancelable.
+ * - navigate: The target window has navigated to a different URL
+ *
+ * Optional events:
+ * - will-navigate: The target window will navigate to a different URL
+ * - hidden: The target is not visible anymore (for TargetTab, another tab is selected)
+ * - visible: The target is visible (for TargetTab, tab is selected)
+ *
+ * Target also supports 2 functions to help allow 2 different versions of
+ * Firefox debug each other. The 'version' property is the equivalent of
+ * browser detection - simple and easy to implement but gets fragile when things
+ * are not quite what they seem. The 'supports' property is the equivalent of
+ * feature detection - harder to setup, but more robust long-term.
+ *
+ * Comparing Targets: 2 instances of a Target object can point at the same
+ * thing, so t1 !== t2 and t1 != t2 even when they represent the same object.
+ * To compare to targets use 't1.equals(t2)'.
+ */
+function Target() {
+  throw new Error("Use TargetFactory.newXXX or Target.getXXX to create a Target in place of 'new Target()'");
+}
+
+Object.defineProperty(Target.prototype, "version", {
+  get: getVersion,
+  enumerable: true
+});
+
+
+/**
+ * A TabTarget represents a page living in a browser tab. Generally these will
+ * be web pages served over http(s), but they don't have to be.
+ */
+function TabTarget(tab) {
+  new EventEmitter(this);
+  this._tab = tab;
+  this._setupListeners();
+}
+
+TabTarget.prototype = {
+  _webProgressListener: null,
+
+  supports: supports,
+  get version() { return getVersion(); },
+
+  get tab() {
+    return this._tab;
+  },
+
+  get name() {
+    return this._tab.linkedBrowser.contentDocument.title;
+  },
+
+  get url() {
+    return this._tab.linkedBrowser.contentDocument.location.href;
+  },
+
+  get isRemote() {
+    return false;
+  },
+
+  /**
+   * Listen to the different tabs events.
+   */
+  _setupListeners: function TabTarget__setupListeners() {
+    this._webProgressListener = new TabWebProgressListener(this);
+    this.tab.linkedBrowser.addProgressListener(this._webProgressListener);
+    this.tab.addEventListener("TabClose", this);
+    this.tab.parentNode.addEventListener("TabSelect", this);
+  },
+
+  /**
+   * Handle tabs events.
+   */
+  handleEvent: function (event) {
+    switch (event.type) {
+      case "TabClose":
+        this.destroy();
+        break;
+      case "TabSelect":
+        if (this.tab.selected) {
+          this.emit("visible", event);
+        } else {
+          this.emit("hidden", event);
+        }
+        break;
+    }
+  },
+
+
+  /**
+   * Target is not alive anymore.
+   */
+  destroy: function() {
+    if (this._destroyed) {
+      return;
+    }
+    this.tab.linkedBrowser.removeProgressListener(this._webProgressListener)
+    this._webProgressListener.target = null;
+    this._webProgressListener = null;
+    this.tab.removeEventListener("TabClose", this);
+    this.tab.parentNode.removeEventListener("TabSelect", this);
+    this._destroyed = true;
+    this.emit("close");
+
+    targets.delete(this._tab);
+    this._tab = null;
+  },
+
+  toString: function() {
+    return 'TabTarget:' + this.tab;
+  },
+};
+
+
+/**
+ * WebProgressListener for TabTarget.
+ *
+ * @param object aTarget
+ *        The TabTarget instance to work with.
+ */
+function TabWebProgressListener(aTarget) {
+  this.target = aTarget;
+}
+
+TabWebProgressListener.prototype = {
+  target: null,
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, Ci.nsISupportsWeakReference]),
+
+  onStateChange: function TWPL_onStateChange(progress, request, flag, status) {
+    let isStart = flag & Ci.nsIWebProgressListener.STATE_START;
+    let isDocument = flag & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT;
+    let isNetwork = flag & Ci.nsIWebProgressListener.STATE_IS_NETWORK;
+    let isRequest = flag & Ci.nsIWebProgressListener.STATE_IS_REQUEST;
+
+    // Skip non-interesting states.
+    if (!isStart || !isDocument || !isRequest || !isNetwork) {
+      return;
+    }
+
+    if (this.target) {
+      this.target.emit("will-navigate", request);
+    }
+  },
+
+  onProgressChange: function() {},
+  onSecurityChange: function() {},
+  onStatusChange: function() {},
+
+  onLocationChange: function TwPL_onLocationChange(webProgress) {
+    let window = webProgress.DOMWindow;
+    if (this.target) {
+      this.target.emit("navigate", window);
+    }
+  },
+};
+
+
+/**
+ * A WindowTarget represents a page living in a xul window or panel. Generally
+ * these will have a chrome: URL
+ */
+function WindowTarget(window) {
+  new EventEmitter(this);
+  this._window = window;
+}
+
+WindowTarget.prototype = {
+  supports: supports,
+  get version() { return getVersion(); },
+
+  get window() {
+    return this._window;
+  },
+
+  get name() {
+    return this._window.document.title;
+  },
+
+  get url() {
+    return this._window.document.location.href;
+  },
+
+  get isRemote() {
+    return false;
+  },
+
+  toString: function() {
+    return 'WindowTarget:' + this.window;
+  },
+};
+
+/**
+ * A RemoteTarget represents a page living in a remote Firefox instance.
+ */
+function RemoteTarget(form, client, chrome) {
+  new EventEmitter(this);
+  this._client = client;
+  this._form = form;
+  this._chrome = chrome;
+
+  this.destroy = this.destroy.bind(this);
+  this.client.addListener("tabDetached", this.destroy);
+
+  this._onTabNavigated = function onRemoteTabNavigated() {
+    this.emit("navigate");
+  }.bind(this);
+  this.client.addListener("tabNavigated", this._onTabNavigated);
+}
+
+RemoteTarget.prototype = {
+  supports: supports,
+  get version() getVersion(),
+
+  get isRemote() true,
+
+  get chrome() this._chrome,
+
+  get name() this._form._title,
+
+  get url() this._form._url,
+
+  get client() this._client,
+
+  get form() this._form,
+
+  /**
+   * Target is not alive anymore.
+   */
+  destroy: function RT_destroy() {
+    if (this._destroyed) {
+      return;
+    }
+    this.client.removeListener("tabNavigated", this._onTabNavigated);
+    this.client.removeListener("tabDetached", this.destroy);
+
+    this._client.close(function onClosed() {
+      this._client = null;
+      this._destroyed = true;
+      this.emit("close");
+    }.bind(this));
+  },
+
+  toString: function() {
+    return 'RemoteTarget:' + this.form.actor;
+  },
+};
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/ToolDefinitions.jsm
@@ -0,0 +1,154 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = [
+                          "defaultTools",
+                          "webConsoleDefinition",
+                          "debuggerDefinition",
+                          "inspectorDefinition",
+                          "styleEditorDefinition"
+                        ];
+
+const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+
+const inspectorProps = "chrome://browser/locale/devtools/inspector.properties";
+const debuggerProps = "chrome://browser/locale/devtools/debugger.properties";
+const styleEditorProps = "chrome://browser/locale/devtools/styleeditor.properties";
+const webConsoleProps = "chrome://browser/locale/devtools/webconsole.properties";
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource:///modules/devtools/EventEmitter.jsm");
+
+XPCOMUtils.defineLazyGetter(this, "osString",
+  function() Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS);
+
+// Panels
+XPCOMUtils.defineLazyModuleGetter(this, "WebConsolePanel",
+  "resource:///modules/WebConsolePanel.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "DebuggerPanel",
+  "resource:///modules/devtools/DebuggerPanel.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "StyleEditorPanel",
+  "resource:///modules/devtools/StyleEditorPanel.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "InspectorPanel",
+  "resource:///modules/devtools/InspectorPanel.jsm");
+
+// Strings
+XPCOMUtils.defineLazyGetter(this, "webConsoleStrings",
+  function() Services.strings.createBundle(webConsoleProps));
+
+XPCOMUtils.defineLazyGetter(this, "debuggerStrings",
+  function() Services.strings.createBundle(debuggerProps));
+
+XPCOMUtils.defineLazyGetter(this, "styleEditorStrings",
+  function() Services.strings.createBundle(styleEditorProps));
+
+XPCOMUtils.defineLazyGetter(this, "inspectorStrings",
+  function() Services.strings.createBundle(inspectorProps));
+
+// Definitions
+let webConsoleDefinition = {
+  id: "webconsole",
+  key: l10n("cmd.commandkey", webConsoleStrings),
+  accesskey: l10n("webConsoleCmd.accesskey", webConsoleStrings),
+  modifiers: Services.appinfo.OS == "Darwin" ? "accel,alt" : "accel,shift",
+  ordinal: 0,
+  icon: "chrome://browser/skin/devtools/webconsole-tool-icon.png",
+  url: "chrome://browser/content/devtools/webconsole.xul",
+  label: l10n("ToolboxWebconsole.label", webConsoleStrings),
+  isTargetSupported: function(target) {
+    return true;
+  },
+  build: function(iframeWindow, toolbox) {
+    return new WebConsolePanel(iframeWindow, toolbox);
+  }
+};
+
+let debuggerDefinition = {
+  id: "jsdebugger",
+  key: l10n("open.commandkey", debuggerStrings),
+  accesskey: l10n("debuggerMenu.accesskey", debuggerStrings),
+  modifiers: osString == "Darwin" ? "accel,alt" : "accel,shift",
+  ordinal: 1,
+  killswitch: "devtools.debugger.enabled",
+  icon: "chrome://browser/skin/devtools/tools-icons-small.png",
+  url: "chrome://browser/content/debugger.xul",
+  label: l10n("ToolboxDebugger.label", debuggerStrings),
+
+  isTargetSupported: function(target) {
+    return true;
+  },
+
+  build: function(iframeWindow, toolbox) {
+    return new DebuggerPanel(iframeWindow, toolbox);
+  }
+};
+
+let inspectorDefinition = {
+  id: "inspector",
+  accesskey: l10n("inspector.accesskey", inspectorStrings),
+  key: l10n("inspector.commandkey", inspectorStrings),
+  ordinal: 2,
+  modifiers: osString == "Darwin" ? "accel,alt" : "accel,shift",
+  icon: "chrome://browser/skin/devtools/tools-icons-small.png",
+  url: "chrome://browser/content/devtools/inspector/inspector.xul",
+  label: l10n("inspector.label", inspectorStrings),
+
+  isTargetSupported: function(target) {
+    return !target.isRemote;
+  },
+
+  build: function(iframeWindow, toolbox) {
+    return new InspectorPanel(iframeWindow, toolbox);
+  }
+};
+
+let styleEditorDefinition = {
+  id: "styleeditor",
+  key: l10n("open.commandkey", styleEditorStrings),
+  ordinal: 3,
+  accesskey: l10n("open.accesskey", styleEditorStrings),
+  modifiers: "shift",
+  label: l10n("ToolboxStyleEditor.label", styleEditorStrings),
+  url: "chrome://browser/content/styleeditor.xul",
+
+  isTargetSupported: function(target) {
+    return !target.isRemote && !target.isChrome;
+  },
+
+  build: function(iframeWindow, toolbox) {
+    return new StyleEditorPanel(iframeWindow, toolbox);
+  }
+};
+
+this.defaultTools = [
+  styleEditorDefinition,
+  webConsoleDefinition,
+  debuggerDefinition,
+  inspectorDefinition,
+];
+
+/**
+ * Lookup l10n string from a string bundle.
+ *
+ * @param {string} name
+ *        The key to lookup.
+ * @param {StringBundle} bundle
+ *        The key to lookup.
+ * @returns A localized version of the given key.
+ */
+function l10n(name, bundle)
+{
+  try {
+    return bundle.GetStringFromName(name);
+  } catch (ex) {
+    Services.console.logStringMessage("Error reading '" + name + "'");
+    throw new Error("l10n error with " + name);
+  }
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/Toolbox.jsm
@@ -0,0 +1,525 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+
+Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource:///modules/devtools/EventEmitter.jsm");
+Cu.import("resource:///modules/devtools/gDevTools.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "Hosts",
+                                  "resource:///modules/devtools/ToolboxHosts.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "CommandUtils",
+                                  "resource:///modules/devtools/DeveloperToolbar.jsm");
+
+// DO NOT put Require.jsm or gcli.jsm into lazy getters as this breaks the
+// requisition import a few lines down.
+Cu.import("resource://gre/modules/devtools/gcli.jsm");
+Cu.import("resource://gre/modules/devtools/Require.jsm");
+
+let Requisition = require('gcli/cli').Requisition;
+let CommandOutputManager = require('gcli/canon').CommandOutputManager;
+
+this.EXPORTED_SYMBOLS = [ "Toolbox" ];
+
+/**
+ * A "Toolbox" is the component that holds all the tools for one specific
+ * target. Visually, it's a document that includes the tools tabs and all
+ * the iframes where the tool panels will be living in.
+ *
+ * @param {object} target
+ *        The object the toolbox is debugging.
+ * @param {Toolbox.HostType} hostType
+ *        Type of host that will host the toolbox (e.g. sidebar, window)
+ * @param {string} selectedTool
+ *        Tool to select initially
+ */
+this.Toolbox = function Toolbox(target, hostType, selectedTool) {
+  this._target = target;
+  this._toolPanels = new Map();
+
+  this._onLoad = this._onLoad.bind(this);
+  this._toolRegistered = this._toolRegistered.bind(this);
+  this._toolUnregistered = this._toolUnregistered.bind(this);
+  this.destroy = this.destroy.bind(this);
+
+  this._target.once("close", this.destroy);
+
+  if (!hostType) {
+    hostType = Services.prefs.getCharPref(this._prefs.LAST_HOST);
+  }
+  if (!selectedTool) {
+    selectedTool = Services.prefs.getCharPref(this._prefs.LAST_TOOL);
+  }
+  let definitions = gDevTools.getToolDefinitions();
+  if (!definitions.get(selectedTool)) {
+    selectedTool = "webconsole";
+  }
+  this._defaultToolId = selectedTool;
+
+  this._host = this._createHost(hostType);
+
+  new EventEmitter(this);
+
+  gDevTools.on("tool-registered", this._toolRegistered);
+  gDevTools.on("tool-unregistered", this._toolUnregistered);
+}
+
+/**
+ * The toolbox can be 'hosted' either embedded in a browser window
+ * or in a separate window.
+ */
+Toolbox.HostType = {
+  BOTTOM: "bottom",
+  SIDE: "side",
+  WINDOW: "window"
+}
+
+Toolbox.prototype = {
+  _URL: "chrome://browser/content/devtools/framework/toolbox.xul",
+
+  _prefs: {
+    LAST_HOST: "devtools.toolbox.host",
+    LAST_TOOL: "devtools.toolbox.selectedTool",
+    SIDE_ENABLED: "devtools.toolbox.sideEnabled"
+  },
+
+  HostType: Toolbox.HostType,
+
+  /**
+   * Returns a *copy* of the _toolPanels collection.
+   *
+   * @return {Map} panels
+   *         All the running panels in the toolbox
+   */
+  getToolPanels: function TB_getToolPanels() {
+    let panels = new Map();
+
+    for (let [key, value] of this._toolPanels) {
+      panels.set(key, value);
+    }
+    return panels;
+  },
+
+  /**
+   * Get/alter the target of a Toolbox so we're debugging something different.
+   * See Target.jsm for more details.
+   * TODO: Do we allow |toolbox.target = null;| ?
+   */
+  get target() {
+    return this._target;
+  },
+
+  set target(value) {
+    this._target = value;
+  },
+
+  /**
+   * Get/alter the host of a Toolbox, i.e. is it in browser or in a separate
+   * tab. See HostType for more details.
+   */
+  get hostType() {
+    return this._host.type;
+  },
+
+  set hostType(value) {
+    this._switchToHost(value);
+  },
+
+  /**
+   * Get/alter the currently displayed tool.
+   */
+  get currentToolId() {
+    return this._currentToolId;
+  },
+
+  set currentToolId(value) {
+    this._currentToolId = value;
+  },
+
+  /**
+   * Get the iframe containing the toolbox UI.
+   */
+  get frame() {
+    return this._host.frame;
+  },
+
+  /**
+   * Shortcut to the document containing the toolbox UI
+   */
+  get doc() {
+    return this.frame.contentDocument;
+  },
+
+  /**
+   * Open the toolbox
+   */
+  open: function TBOX_open() {
+    this._host.once("ready", function(event, iframe) {
+      iframe.addEventListener("DOMContentLoaded", this._onLoad, true);
+      iframe.setAttribute("src", this._URL);
+    }.bind(this));
+
+    this._host.open();
+  },
+
+  /**
+   * Build the buttons for changing hosts. Called every time
+   * the host changes.
+   */
+  _buildDockButtons: function TBOX_createDockButtons() {
+    let dockBox = this.doc.getElementById("toolbox-dock-buttons");
+
+    while (dockBox.firstChild) {
+      dockBox.removeChild(dockBox.firstChild);
+    }
+
+    let sideEnabled = Services.prefs.getBoolPref(this._prefs.SIDE_ENABLED);
+
+    for each (let position in this.HostType) {
+      if (position == this.hostType ||
+         (!sideEnabled && position == this.HostType.SIDE)) {
+        continue;
+      }
+
+      let button = this.doc.createElement("toolbarbutton");
+      button.id = "toolbox-dock-" + position;
+      button.className = "toolbox-dock-button";
+      button.addEventListener("command", function(position) {
+        this.hostType = position;
+      }.bind(this, position));
+
+      dockBox.appendChild(button);
+    }
+  },
+
+  /**
+   * Onload handler for the toolbox's iframe
+   */
+  _onLoad: function TBOX_onLoad() {
+    this.frame.removeEventListener("DOMContentLoaded", this._onLoad, true);
+    this.isReady = true;
+
+    let closeButton = this.doc.getElementById("toolbox-close");
+    closeButton.addEventListener("command", this.destroy, true);
+
+    this._buildDockButtons();
+
+    this._buildTabs();
+    this._buildButtons(this.frame);
+
+    this.selectTool(this._defaultToolId);
+
+    this.emit("ready");
+  },
+
+  /**
+   * Add tabs to the toolbox UI for registered tools
+   */
+  _buildTabs: function TBOX_buildTabs() {
+    for (let [id, definition] of gDevTools.getToolDefinitions()) {
+      this._buildTabForTool(definition);
+    }
+  },
+
+  /**
+   * Add buttons to the UI as specified in the devtools.window.toolbarSpec pref
+   *
+   * @param {iframe} frame
+   *        The iframe to contain the buttons
+   */
+  _buildButtons: function TBOX_buildButtons(frame) {
+    let toolbarSpec = CommandUtils.getCommandbarSpec("devtools.toolbox.toolbarSpec");
+    let environment = { chromeDocument: frame.ownerDocument };
+    let requisition = new Requisition(environment);
+    requisition.commandOutputManager = new CommandOutputManager();
+
+    let buttons = CommandUtils.createButtons(toolbarSpec, this.doc, requisition);
+
+    let container = this.doc.getElementById("toolbox-buttons");
+    buttons.forEach(function(button) {
+      container.appendChild(button);
+    }.bind(this));
+  },
+
+  /**
+   * Build a tab for one tool definition and add to the toolbox
+   *
+   * @param {string} toolDefinition
+   *        Tool definition of the tool to build a tab for.
+   */
+  _buildTabForTool: function TBOX_buildTabForTool(toolDefinition) {
+    const MAX_ORDINAL = 99;
+    if (!toolDefinition.isTargetSupported(this._target)) {
+      return;
+    }
+
+    let tabs = this.doc.getElementById("toolbox-tabs");
+    let deck = this.doc.getElementById("toolbox-deck");
+
+    let id = toolDefinition.id;
+
+    let radio = this.doc.createElement("radio");
+    radio.setAttribute("label", toolDefinition.label);
+    radio.className = "toolbox-tab devtools-tab";
+    radio.id = "toolbox-tab-" + id;
+    radio.setAttribute("toolid", id);
+
+    let ordinal = (typeof toolDefinition.ordinal == "number") ?
+                  toolDefinition.ordinal : MAX_ORDINAL;
+    radio.setAttribute("ordinal", ordinal);
+
+    radio.addEventListener("command", function(id) {
+      this.selectTool(id);
+    }.bind(this, id));
+
+    let vbox = this.doc.createElement("vbox");
+    vbox.className = "toolbox-panel";
+    vbox.id = "toolbox-panel-" + id;
+
+    tabs.appendChild(radio);
+    deck.appendChild(vbox);
+  },
+
+  /**
+   * Switch to the tool with the given id
+   *
+   * @param {string} id
+   *        The id of the tool to switch to
+   */
+  selectTool: function TBOX_selectTool(id) {
+    if (!this.isReady) {
+      throw new Error("Can't select tool, wait for toolbox 'ready' event");
+    }
+    let tab = this.doc.getElementById("toolbox-tab-" + id);
+
+    if (!tab) {
+      throw new Error("No tool found");
+    }
+
+    let tabstrip = this.doc.getElementById("toolbox-tabs");
+
+    // select the right tab
+    let index = -1;
+    let tabs = tabstrip.childNodes;
+    for (let i = 0; i < tabs.length; i++) {
+      if (tabs[i] === tab) {
+        index = i;
+        break;
+      }
+    }
+    tabstrip.selectedIndex = index;
+
+    // and select the right iframe
+    let deck = this.doc.getElementById("toolbox-deck");
+    deck.selectedIndex = index;
+
+    let definition = gDevTools.getToolDefinitions().get(id);
+
+    let iframe = this.doc.getElementById("toolbox-panel-iframe-" + id);
+    if (!iframe) {
+      iframe = this.doc.createElement("iframe");
+      iframe.className = "toolbox-panel-iframe";
+      iframe.id = "toolbox-panel-iframe-" + id;
+      iframe.setAttribute("flex", 1);
+
+      let vbox = this.doc.getElementById("toolbox-panel-" + id);
+      vbox.appendChild(iframe);
+
+      let boundLoad = function() {
+        iframe.removeEventListener("DOMContentLoaded", boundLoad, true);
+        let panel = definition.build(iframe.contentWindow, this);
+        this._toolPanels.set(id, panel);
+
+        let panelReady = function() {
+          this.emit(id + "-ready", panel);
+          this.emit("select", id);
+          this.emit(id + "-selected", panel);
+          gDevTools.emit(id + "-ready", this, panel);
+        }.bind(this);
+
+        if (panel.isReady) {
+          panelReady();
+        } else {
+          panel.once("ready", panelReady);
+        }
+      }.bind(this);
+
+      iframe.addEventListener("DOMContentLoaded", boundLoad, true);
+      iframe.setAttribute("src", definition.url);
+    } else {
+      let panel = this._toolPanels.get(id);
+      // only emit 'select' event if the iframe has been loaded
+      if (panel) {
+        this.emit("select", id);
+        this.emit(id + "-selected", panel);
+      }
+    }
+
+    Services.prefs.setCharPref(this._prefs.LAST_TOOL, id);
+
+    this._currentToolId = id;
+  },
+
+  /**
+   * Create a host object based on the given host type.
+   *
+   * @param {string} hostType
+   *        The host type of the new host object
+   *
+   * @return {Host} host
+   *        The created host object
+   */
+  _createHost: function TBOX_createHost(hostType) {
+    let hostTab = this._getHostTab();
+    if (!Hosts[hostType]) {
+      throw new Error('Unknown hostType: '+ hostType);
+    }
+    let newHost = new Hosts[hostType](hostTab);
+
+    // clean up the toolbox if its window is closed
+    newHost.on("window-closed", this.destroy);
+
+    return newHost;
+  },
+
+  /**
+   * Switch to a new host for the toolbox UI. E.g.
+   * bottom, sidebar, separate window.
+   *
+   * @param {string} hostType
+   *        The host type of the new host object
+   */
+  _switchToHost: function TBOX_switchToHost(hostType) {
+    if (hostType == this._host.type) {
+      return;
+    }
+
+    let newHost = this._createHost(hostType);
+
+    newHost.once("ready", function(event, iframe) {
+      // change toolbox document's parent to the new host
+      iframe.QueryInterface(Components.interfaces.nsIFrameLoaderOwner);
+      iframe.swapFrameLoaders(this.frame);
+
+      this._host.off("window-closed", this.destroy);
+      this._host.destroy();
+
+      this._host = newHost;
+
+      Services.prefs.setCharPref(this._prefs.LAST_HOST, this._host.type);
+
+      this._buildDockButtons();
+
+      this.emit("host-changed");
+    }.bind(this));
+
+    newHost.open();
+  },
+
+  /**
+   * Get the most appropriate host tab, either the target or the current tab
+   */
+  _getHostTab: function TBOX_getHostTab() {
+    if (!this._target.isRemote && !this._target.isChrome) {
+      return this._target.tab;
+    } else {
+      let win = Services.wm.getMostRecentWindow("navigator:browser");
+      return win.gBrowser.selectedTab;
+    }
+  },
+
+  /**
+   * Handler for the tool-registered event.
+   * @param  {string} event
+   *         Name of the event ("tool-registered")
+   * @param  {string} toolId
+   *         Id of the tool that was registered
+   */
+  _toolRegistered: function TBOX_toolRegistered(event, toolId) {
+    let defs = gDevTools.getToolDefinitions();
+    let tool = defs.get(toolId);
+
+    this._buildTabForTool(tool);
+  },
+
+  /**
+   * Handler for the tool-unregistered event.
+   * @param  {string} event
+   *         Name of the event ("tool-unregistered")
+   * @param  {string} toolId
+   *         Id of the tool that was unregistered
+   */
+  _toolUnregistered: function TBOX_toolUnregistered(event, toolId) {
+    let radio = this.doc.getElementById("toolbox-tab-" + toolId);
+    let panel = this.doc.getElementById("toolbox-panel-" + toolId);
+
+    if (this._currentToolId == toolId) {
+      let nextToolName = null;
+      if (radio.nextSibling) {
+        nextToolName = radio.nextSibling.getAttribute("toolid");
+      }
+      if (radio.previousSibling) {
+        nextToolName = radio.previousSibling.getAttribute("toolid");
+      }
+      if (nextToolName) {
+        this.selectTool(nextToolName);
+      }
+    }
+
+    if (radio) {
+      radio.parentNode.removeChild(radio);
+    }
+
+    if (panel) {
+      panel.parentNode.removeChild(panel);
+    }
+
+    if (this._toolPanels.has(toolId)) {
+      let instance = this._toolPanels.get(toolId);
+      instance.destroy();
+      this._toolPanels.delete(toolId);
+    }
+  },
+
+
+  /**
+   * Get the toolbox's notification box
+   *
+   * @return The notification box element.
+   */
+  getNotificationBox: function TBOX_getNotificationBox() {
+    return this.doc.getElementById("toolbox-notificationbox");
+  },
+
+  /**
+   * Remove all UI elements, detach from target and clear up
+   */
+  destroy: function TBOX_destroy() {
+    if (this._destroyed) {
+      return;
+    }
+
+    // Remote targets need to be notified that the toolbox is being torn down.
+    if (this._target && this._target.isRemote) {
+      this._target.destroy();
+    }
+    this._target = null;
+
+    for (let [id, panel] of this._toolPanels) {
+      panel.destroy();
+    }
+
+    this._host.destroy();
+
+    gDevTools.off("tool-registered", this._toolRegistered);
+    gDevTools.off("tool-unregistered", this._toolUnregistered);
+
+    this._destroyed = true;
+    this.emit("destroyed");
+  }
+};
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/ToolboxHosts.jsm
@@ -0,0 +1,208 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource:///modules/devtools/EventEmitter.jsm");
+
+this.EXPORTED_SYMBOLS = [ "Hosts" ];
+
+/**
+ * A toolbox host represents an object that contains a toolbox (e.g. the
+ * sidebar or a separate window). Any host object should implement the
+ * following functions:
+ *
+ * open() - create the UI and emit a 'ready' event when the UI is ready to use
+ * destroy() - destroy the host's UI
+ */
+
+this.Hosts = {
+  "bottom": BottomHost,
+  "side": SidebarHost,
+  "window": WindowHost
+}
+
+/**
+ * Host object for the dock on the bottom of the browser
+ */
+function BottomHost(hostTab) {
+  this.hostTab = hostTab;
+
+  new EventEmitter(this);
+}
+
+BottomHost.prototype = {
+  type: "bottom",
+
+  heightPref: "devtools.toolbox.footer.height",
+
+  /**
+   * Create a box at the bottom of the host tab.
+   */
+  open: function BH_open() {
+    let gBrowser = this.hostTab.ownerDocument.defaultView.gBrowser;
+    let ownerDocument = gBrowser.ownerDocument;
+
+    this._splitter = ownerDocument.createElement("splitter");
+    this._splitter.setAttribute("class", "devtools-horizontal-splitter");
+
+    this.frame = ownerDocument.createElement("iframe");
+    this.frame.id = "devtools-toolbox-bottom-iframe";
+    this.frame.height = Services.prefs.getIntPref(this.heightPref);
+
+    this._nbox = gBrowser.getNotificationBox(this.hostTab.linkedBrowser);
+    this._nbox.appendChild(this._splitter);
+    this._nbox.appendChild(this.frame);
+
+    let frameLoad = function() {
+      this.frame.removeEventListener("DOMContentLoaded", frameLoad, true);
+      this.emit("ready", this.frame);
+    }.bind(this);
+
+    this.frame.addEventListener("DOMContentLoaded", frameLoad, true);
+
+    // we have to load something so we can switch documents if we have to
+    this.frame.setAttribute("src", "about:blank");
+
+    focusTab(this.hostTab);
+  },
+
+  /**
+   * Destroy the bottom dock.
+   */
+  destroy: function BH_destroy() {
+    if (this._destroyed) {
+      return;
+    }
+    this._destroyed = true;
+    Services.prefs.setIntPref(this.heightPref, this.frame.height);
+
+    this._nbox.removeChild(this._splitter);
+    this._nbox.removeChild(this.frame);
+  }
+}
+
+
+/**
+ * Host object for the in-browser sidebar
+ */
+function SidebarHost(hostTab) {
+  this.hostTab = hostTab;
+
+  new EventEmitter(this);
+}
+
+SidebarHost.prototype = {
+  type: "side",
+
+  widthPref: "devtools.toolbox.sidebar.width",
+
+  /**
+   * Create a box in the sidebar of the host tab.
+   */
+  open: function RH_open() {
+    let gBrowser = this.hostTab.ownerDocument.defaultView.gBrowser;
+    let ownerDocument = gBrowser.ownerDocument;
+
+    this._splitter = ownerDocument.createElement("splitter");
+    this._splitter.setAttribute("class", "devtools-side-splitter");
+
+    this.frame = ownerDocument.createElement("iframe");
+    this.frame.id = "devtools-toolbox-side-iframe";
+    this.frame.width = Services.prefs.getIntPref(this.widthPref);
+
+    this._sidebar = gBrowser.getSidebarContainer(this.hostTab.linkedBrowser);
+    this._sidebar.appendChild(this._splitter);
+    this._sidebar.appendChild(this.frame);
+
+    let frameLoad = function() {
+      this.frame.removeEventListener("DOMContentLoaded", frameLoad, true);
+      this.emit("ready", this.frame);
+    }.bind(this);
+
+    this.frame.addEventListener("DOMContentLoaded", frameLoad, true);
+    this.frame.setAttribute("src", "about:blank");
+
+    focusTab(this.hostTab);
+  },
+
+  /**
+   * Destroy the sidebar.
+   */
+  destroy: function RH_destroy() {
+    Services.prefs.setIntPref(this.widthPref, this.frame.width);
+
+    this._sidebar.removeChild(this._splitter);
+    this._sidebar.removeChild(this.frame);
+  }
+}
+
+/**
+ * Host object for the toolbox in a separate window
+ */
+function WindowHost() {
+  this._boundUnload = this._boundUnload.bind(this);
+
+  new EventEmitter(this);
+}
+
+WindowHost.prototype = {
+  type: "window",
+
+  WINDOW_URL: "chrome://browser/content/devtools/framework/toolbox-window.xul",
+
+  /**
+   * Create a new xul window to contain the toolbox.
+   */
+  open: function WH_open() {
+    let flags = "chrome,centerscreen,resizable,dialog=no";
+    let win = Services.ww.openWindow(null, this.WINDOW_URL, "_blank",
+                                     flags, null);
+
+    let frameLoad = function(event) {
+      win.removeEventListener("load", frameLoad, true);
+      this.frame = win.document.getElementById("toolbox-iframe");
+      this.emit("ready", this.frame);
+    }.bind(this);
+
+    win.addEventListener("load", frameLoad, true);
+    win.addEventListener("unload", this._boundUnload);
+
+    win.focus();
+
+    this._window = win;
+  },
+
+  /**
+   * Catch the user closing the window.
+   */
+  _boundUnload: function(event) {
+    if (event.target.location != this.WINDOW_URL) {
+      return;
+    }
+    this._window.removeEventListener("unload", this._boundUnload);
+
+    this.emit("window-closed");
+  },
+
+  /**
+   * Destroy the window.
+   */
+  destroy: function WH_destroy() {
+    this._window.removeEventListener("unload", this._boundUnload);
+    this._window.close();
+  }
+}
+
+/**
+ *  Switch to the given tab in a browser and focus the browser window
+ */
+function focusTab(tab) {
+  let browserWindow = tab.ownerDocument.defaultView;
+  browserWindow.focus();
+  browserWindow.gBrowser.selectedTab = tab;
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/connect/connect.css
@@ -0,0 +1,87 @@
+html {
+  background: url("chrome://browser/skin/newtab/noise.png");
+}
+
+body {
+  font-family: Arial;
+  padding: 20px;
+  border-radius: 3px;
+  max-width: 600px;
+  min-height: 400px;
+  margin: 10px auto 0;
+}
+
+label {
+  display: block;
+  margin: 10px;
+  font-size: 0;
+}
+
+label > span {
+  display: inline-block;
+  min-width: 150px;
+  font-size: 0.8rem;
+  text-align: right;
+  margin-right: 10px;
+}
+
+#submit {
+  margin-left: 160px;
+}
+
+
+#actors, #connection-form {
+  margin: 20px;
+}
+
+input {
+  border: 1px solid grey;
+}
+
+#connection-form,
+#connecting,
+#actors-list {
+  display: none;
+}
+
+body:not(.actors-mode):not(.connecting) > #connection-form {
+  display: block;
+}
+
+body.actors-mode > #actors-list {
+  display: block;
+}
+
+body.connecting > #connecting {
+  display: block;
+}
+
+#connecting {
+  text-align: center;
+}
+
+#throbber {
+  height: 7px; width: 7px;
+  border-radius: 50%;
+  background: black;
+  display: inline-block;
+  animation-duration: 0.6s;
+  animation-name: anim;
+  animation-direction: alternate;
+  animation-iteration-count: infinite;
+  animation-timing-function: linear;
+}
+@keyframes anim {to {
+    transform: scale(0.5) rotate(0.1deg);
+}}
+
+#actors {
+  padding-left: 0;
+  font-size: 0.9rem;
+}
+
+#actors > a {
+  display: block;
+  margin: 5px;
+  padding: 5px;
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/connect/connect.js
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const Cu = Components.utils;
+Cu.import("resource:///modules/devtools/Target.jsm");
+Cu.import("resource:///modules/devtools/Toolbox.jsm");
+Cu.import("resource:///modules/devtools/gDevTools.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
+
+let gClient;
+
+function submit() {
+  document.body.classList.add("connecting");
+
+  let host = document.getElementById("host").value;
+  let port = document.getElementById("port").value;
+  if (!host) {
+    host = Services.prefs.getCharPref("devtools.debugger.remote-host");
+  } else {
+    Services.prefs.setCharPref("devtools.debugger.remote-host", host);
+  }
+  if (!port) {
+    port = Services.prefs.getIntPref("devtools.debugger.remote-port");
+  } else {
+    Services.prefs.setIntPref("devtools.debugger.remote-port", port);
+  }
+
+  let transport = debuggerSocketConnect(host, port);
+  let client = gClient = new DebuggerClient(transport);
+
+  client.connect(function(aType, aTraits) {
+    client.listTabs(function(aResponse) {
+      document.body.classList.remove("connecting");
+      document.body.classList.add("actors-mode");
+
+      let parent = document.getElementById("actors");
+      let focusSet = false;
+
+      // Add Global Process debugging...
+      let globals = JSON.parse(JSON.stringify(aResponse));
+      delete globals.tabs;
+      delete globals.selected;
+      // ...only if there are appropriate actors (a 'from' property will always
+      // be there).
+      if (Object.keys(globals).length > 1) {
+        let a = document.createElement("a");
+        a.onclick = function() {
+          connect(globals, true);
+        }
+
+        a.title = a.textContent = "Remote process";
+        a.href = "#";
+
+        parent.appendChild(a);
+      }
+
+      // Add one entry for each open tab.
+      if (aResponse.tabs.length > 0) {
+        let header = document.createElement("div");
+        header.innerHTML = "Tabs:";
+        parent.appendChild(header);
+      }
+      for (let i = 0; i < aResponse.tabs.length; i++) {
+        let tab = aResponse.tabs[i];
+
+        let a = document.createElement("a");
+        a.onclick = function() {
+          connect(tab);
+        }
+
+        a.title = a.textContent = tab.title;
+        a.href = "#";
+
+        if (i == aResponse.selected) {
+          a.title += " [*]";
+          a.textContent = a.title;
+        }
+
+        parent.appendChild(a);
+
+        if (!focusSet) {
+          a.focus();
+          focusSet = true;
+        }
+      }
+    });
+  });
+}
+
+function connect(form, chrome=false) {
+  let target = TargetFactory.forRemote(form, gClient, chrome);
+  gDevTools.openToolbox(target, Toolbox.HostType.WINDOW, "webconsole");
+  window.close();
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/connect/connect.xhtml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<!DOCTYPE html [
+<!ENTITY % connectionDTD SYSTEM "chrome://browser/locale/devtools/connection-screen.dtd" >
+ %connectionDTD;
+]>
+
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <head>
+    <title>&title;</title>
+    <link rel="stylesheet" href="chrome://browser/content/devtools/connect.css" type="text/css"/>
+    <script type="application/javascript;version=1.8" src="connect.js"></script>
+  </head>
+  <body>
+    <p>
+    </p>
+    <section id="connection-form">
+      <form onsubmit="window.submit()" action="#">
+        <label>
+          <span>&host;</span>
+          <input id="host" type="text" placeholder="localhost"></input>
+        </label>
+        <label>
+          <span>&port;</span>
+          <input id="port" type="number" placeholder="6000"></input>
+        </label>
+        <label>
+          <input id="submit" type="submit" value="&connect;"></input>
+        </label>
+      </form>
+    </section>
+    <section id="actors-list">
+      <p>&availability;</p>
+      <ul id="actors"></ul>
+    </section>
+    <section id="connecting">
+      <p>&connecting;</p>
+      <div id="throbber"></div>
+    </section>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/gDevTools.jsm
@@ -0,0 +1,546 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = [ "gDevTools", "DevTools", "DevToolsXULCommands" ];
+
+const Cu = Components.utils;
+const Ci = Components.interfaces;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource:///modules/devtools/EventEmitter.jsm");
+Cu.import("resource:///modules/devtools/ToolDefinitions.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Toolbox",
+  "resource:///modules/devtools/Toolbox.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
+  "resource:///modules/devtools/Target.jsm");
+
+const FORBIDDEN_IDS = new Set("toolbox", "");
+
+/**
+ * DevTools is a class that represents a set of developer tools, it holds a
+ * set of tools and keeps track of open toolboxes in the browser.
+ */
+this.DevTools = function DevTools() {
+  this._tools = new Map();
+  this._toolboxes = new Map();
+
+  // destroy() is an observer's handler so we need to preserve context.
+  this.destroy = this.destroy.bind(this);
+
+  this._trackedBrowserWindows = new Set();
+
+  // Bind _updateMenuCheckbox() to preserve context.
+  this._updateMenuCheckbox = this._updateMenuCheckbox.bind(this);
+
+  new EventEmitter(this);
+
+  Services.obs.addObserver(this.destroy, "quit-application", false);
+
+  /**
+   * Register the set of default tools
+   */
+  for (let definition of defaultTools) {
+    this.registerTool(definition);
+  }
+}
+
+DevTools.prototype = {
+  /**
+   * Register a new developer tool.
+   *
+   * A definition is a light object that holds different information about a
+   * developer tool. This object is not supposed to have any operational code.
+   * See it as a "manifest".
+   * The only actual code lives in the build() function, which will be used to
+   * start an instance of this tool.
+   *
+   * Each toolDefinition has the following properties:
+   * - id: Unique identifier for this tool (string|required)
+   * - killswitch: Property name to allow us to turn this tool on/off globally
+   *               (string|required) (TODO: default to devtools.{id}.enabled?)
+   * - icon: URL pointing to a graphic which will be used as the src for an
+   *         16x16 img tag (string|required)
+   * - url: URL pointing to a XUL/XHTML document containing the user interface
+   *        (string|required)
+   * - label: Localized name for the tool to be displayed to the user
+   *          (string|required)
+   * - build: Function that takes an iframe, which has been populated with the
+   *          markup from |url|, and also the toolbox containing the panel.
+   *          And returns an instance of ToolPanel (function|required)
+   */
+  registerTool: function DT_registerTool(toolDefinition) {
+    let toolId = toolDefinition.id;
+
+    if (!toolId || FORBIDDEN_IDS.has(toolId)) {
+      throw new Error("Invalid definition.id");
+    }
+
+    toolDefinition.killswitch = toolDefinition.killswitch ||
+      "devtools." + toolId + ".enabled";
+    this._tools.set(toolId, toolDefinition);
+
+    this._addToolToWindows(toolDefinition);
+
+    this.emit("tool-registered", toolId);
+  },
+
+  /**
+   * Removes all tools that match the given |toolId|
+   * Needed so that add-ons can remove themselves when they are deactivated
+   *
+   * @param {string} toolId
+   *        id of the tool to unregister
+   */
+  unregisterTool: function DT_unregisterTool(toolId) {
+    this._tools.delete(toolId);
+
+    this._removeToolFromWindows(toolId);
+
+    this.emit("tool-unregistered", toolId);
+  },
+
+  /**
+   * Allow ToolBoxes to get at the list of tools that they should populate
+   * themselves with.
+   *
+   * @return {Map} tools
+   *         A map of the the tool definitions registered in this instance
+   */
+  getToolDefinitions: function DT_getToolDefinitions() {
+    let tools = new Map();
+
+    for (let [key, value] of this._tools) {
+      let enabled;
+
+      try {
+        enabled = Services.prefs.getBoolPref(value.killswitch);
+      } catch(e) {
+        enabled = true;
+      }
+
+      if (enabled) {
+        tools.set(key, value);
+      }
+    }
+    return tools;
+  },
+
+  /**
+   * Create a toolbox to debug |target| using a window displayed in |hostType|
+   * (optionally with |defaultToolId| opened)
+   *
+   * @param {Target} target
+   *         The target the toolbox will debug
+   * @param {Toolbox.HostType} hostType
+   *        The type of host (bottom, top, side)
+   * @param {string} defaultToolId
+   *        The id of the initial tool to show
+   *
+   * @return {Toolbox} toolbox
+   *        The toolbox that was opened
+   */
+  openToolbox: function DT_openToolbox(target, hostType, defaultToolId) {
+    if (this._toolboxes.has(target)) {
+      // only allow one toolbox per target
+      return this._toolboxes.get(target);
+    }
+
+    let tb = new Toolbox(target, hostType, defaultToolId);
+
+    this._toolboxes.set(target, tb);
+    tb.once("destroyed", function() {
+      this._toolboxes.delete(target);
+      this._updateMenuCheckbox();
+      this.emit("toolbox-destroyed", target);
+    }.bind(this));
+
+    tb.once("ready", function() {
+      this.emit("toolbox-ready", tb);
+      this._updateMenuCheckbox();
+    }.bind(this));
+
+    tb.open();
+
+    return tb;
+  },
+
+  /**
+   * Close the toolbox for a given target
+   */
+  closeToolbox: function DT_closeToolbox(target) {
+    let toolbox = this._toolboxes.get(target);
+    if (toolbox == null) {
+      return;
+    }
+    toolbox.destroy();
+  },
+
+  /**
+   * Open the toolbox for a specific target (not tab).
+   * FIXME: We should probably merge this function and openToolbox
+   *
+   * @param  {Target} target
+   *         The target that the toolbox should be debugging
+   * @param  {String} toolId
+   *         The id of the tool to open
+   *
+   * @return {Toolbox} toolbox
+   *         The toolbox that has been opened
+   */
+  openToolboxForTab: function DT_openToolboxForTab(target, toolId) {
+    let tb = this.getToolboxForTarget(target);
+
+    if (tb) {
+      tb.selectTool(toolId);
+    } else {
+      tb = this.openToolbox(target, null, toolId);
+    }
+    return tb;
+  },
+
+  /**
+   * This function is for the benefit of command#Tools:DevToolbox in
+   * browser/base/content/browser-sets.inc and should not be used outside
+   * of there
+   */
+  toggleToolboxCommand: function(gBrowser, toolId=null) {
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    this.toggleToolboxForTarget(target, toolId);
+  },
+
+  /**
+   * Toggle a toolbox for the given target.
+   *
+   * @param  {Target} target
+   *         The target the toolbox is debugging
+   * @param  {string} toolId
+   *         The id of the tool to show in the toolbox, if it's to be opened.
+   */
+  toggleToolboxForTarget: function DT_toggleToolboxForTarget(target, toolId) {
+    let tb = this.getToolboxForTarget(target);
+
+    if (tb /* FIXME: && tool is showing */ ) {
+      tb.destroy();
+    } else {
+      this.openToolboxForTab(target, toolId);
+    }
+  },
+
+  /**
+   * Return the toolbox for a given target.
+   *
+   * @param  {object} target
+   *         Target value e.g. the target that owns this toolbox
+   *
+   * @return {Toolbox} toolbox
+   *         The toobox that is debugging the given target
+   */
+  getToolboxForTarget: function DT_getToolboxForTarget(target) {
+    return this._toolboxes.get(target);
+  },
+
+  /**
+   * Return a tool panel for a given tool and target.
+   *
+   * @param  {String} toolId
+   *         The id of the tool to open.
+   * @param  {object} target
+   *         The toolbox's target.
+   *
+   * @return {ToolPanel} panel
+   *         Panel for the tool with the toolid
+   */
+  getPanelForTarget: function DT_getPanelForTarget(toolId, target) {
+    let toolbox = this.getToolboxForTarget(target);
+    if (!toolbox) {
+      return undefined;
+    }
+    return toolbox.getToolPanels().get(toolId);
+  },
+
+  /**
+   * Add this DevTools's presence to a browser window's document
+   *
+   * @param  {XULDocument} doc
+   *         The document to which menuitems and handlers are to be added
+   */
+  registerBrowserWindow: function DT_registerBrowserWindow(win) {
+    this._trackedBrowserWindows.add(win);
+    this._addAllToolsToMenu(win.document);
+
+    let tabContainer = win.document.getElementById("tabbrowser-tabs")
+    tabContainer.addEventListener("TabSelect", this._updateMenuCheckbox, false);
+  },
+
+  /**
+   * Add the menuitem for a tool to all open browser windows.
+   *
+   * @param {object} toolDefinition
+   *        properties of the tool to add
+   */
+  _addToolToWindows: function DT_addToolToWindows(toolDefinition) {
+    for (let win of this._trackedBrowserWindows) {
+      this._addToolToMenu(toolDefinition, win.document);
+    }
+  },
+
+  /**
+   * Add all tools to the developer tools menu of a window.
+   *
+   * @param {XULDocument} doc
+   *        The document to which the tool items are to be added.
+   */
+  _addAllToolsToMenu: function DT_addAllToolsToMenu(doc) {
+    let fragCommands = doc.createDocumentFragment();
+    let fragKeys = doc.createDocumentFragment();
+    let fragBroadcasters = doc.createDocumentFragment();
+    let fragAppMenuItems = doc.createDocumentFragment();
+    let fragMenuItems = doc.createDocumentFragment();
+
+    for (let [key, toolDefinition] of this._tools) {
+      let frags = this._addToolToMenu(toolDefinition, doc, true);
+
+      if (!frags) {
+        return;
+      }
+
+      let [cmd, key, bc, appmenuitem, menuitem] = frags;
+
+      fragCommands.appendChild(cmd);
+      if (key) {
+        fragKeys.appendChild(key);
+      }
+      fragBroadcasters.appendChild(bc);
+      fragAppMenuItems.appendChild(appmenuitem);
+      fragMenuItems.appendChild(menuitem);
+    }
+
+    let mcs = doc.getElementById("mainCommandSet");
+    mcs.appendChild(fragCommands);
+
+    let mks = doc.getElementById("mainKeyset");
+    mks.appendChild(fragKeys);
+
+    let mbs = doc.getElementById("mainBroadcasterSet");
+    mbs.appendChild(fragBroadcasters);
+
+    let amp = doc.getElementById("appmenu_webDeveloper_popup");
+    if (amp) {
+      let amps = doc.getElementById("appmenu_devtools_separator");
+      amp.insertBefore(fragAppMenuItems, amps);
+    }
+
+    let mp = doc.getElementById("menuWebDeveloperPopup");
+    let mps = doc.getElementById("menu_devtools_separator");
+    mp.insertBefore(fragMenuItems, mps);
+  },
+
+  /**
+   * Add a menu entry for a tool definition
+   *
+   * @param {string} toolDefinition
+   *        Tool definition of the tool to add a menu entry.
+   * @param {XULDocument} doc
+   *        The document to which the tool menu item is to be added.
+   * @param {Boolean} [noAppend]
+   *        Return an array of elements instead of appending them to the
+   *        document. Default is false.
+   */
+  _addToolToMenu: function DT_addToolToMenu(toolDefinition, doc, noAppend) {
+    let id = toolDefinition.id;
+
+    // Prevent multiple entries for the same tool.
+    if (doc.getElementById("Tools:" + id)) {
+      return;
+    }
+
+    let cmd = doc.createElement("command");
+    cmd.id = "Tools:" + id;
+    cmd.setAttribute("oncommand",
+        'gDevTools.toggleToolboxCommand(gBrowser, "' + id + '");');
+
+    let key = null;
+    if (toolDefinition.key) {
+      key = doc.createElement("key");
+      key.id = "key_" + id;
+
+      if (toolDefinition.key.startsWith("VK_")) {
+        key.setAttribute("keycode", toolDefinition.key);
+      } else {
+        key.setAttribute("key", toolDefinition.key);
+      }
+
+      key.setAttribute("oncommand",
+          'gDevTools.toggleToolboxCommand(gBrowser, "' + id + '");');
+      key.setAttribute("modifiers", toolDefinition.modifiers);
+    }
+
+    let bc = doc.createElement("broadcaster");
+    bc.id = "devtoolsMenuBroadcaster_" + id;
+    bc.setAttribute("label", toolDefinition.label);
+    bc.setAttribute("command", "Tools:" + id);
+
+    if (key) {
+      bc.setAttribute("key", "key_" + id);
+    }
+
+    let appmenuitem = doc.createElement("menuitem");
+    appmenuitem.id = "appmenuitem_" + id;
+    appmenuitem.setAttribute("observes", "devtoolsMenuBroadcaster_" + id);
+
+    let menuitem = doc.createElement("menuitem");
+    menuitem.id = "menuitem_" + id;
+    menuitem.setAttribute("observes", "devtoolsMenuBroadcaster_" + id);
+
+    if (toolDefinition.accesskey) {
+      menuitem.setAttribute("accesskey", toolDefinition.accesskey);
+    }
+
+    if (noAppend) {
+      return [cmd, key, bc, appmenuitem, menuitem];
+    } else {
+      let mcs = doc.getElementById("mainCommandSet");
+      mcs.appendChild(cmd);
+
+      if (key) {
+        let mks = doc.getElementById("mainKeyset");
+        mks.appendChild(key);
+      }
+
+      let mbs = doc.getElementById("mainBroadcasterSet");
+      mbs.appendChild(bc);
+
+      let amp = doc.getElementById("appmenu_webDeveloper_popup");
+      if (amp) {
+        let amps = doc.getElementById("appmenu_devtools_separator");
+        amp.insertBefore(appmenuitem, amps);
+      }
+
+      let mp = doc.getElementById("menuWebDeveloperPopup");
+      let mps = doc.getElementById("menu_devtools_separator");
+      mp.insertBefore(menuitem, mps);
+    }
+  },
+
+  /**
+   * Update the "Toggle Toolbox" checkbox in the developer tools menu. This is
+   * called when a toolbox is created or destroyed.
+   */
+  _updateMenuCheckbox: function DT_updateMenuCheckbox() {
+    for (let win of this._trackedBrowserWindows) {
+
+      let hasToolbox = false;
+      if (TargetFactory.isKnownTab(win.gBrowser.selectedTab)) {
+        let target = TargetFactory.forTab(win.gBrowser.selectedTab);
+        if (this._toolboxes.has(target)) {
+          hasToolbox = true;
+        }
+      }
+
+      let broadcaster = win.document.getElementById("devtoolsMenuBroadcaster_DevToolbox");
+      if (hasToolbox) {
+        broadcaster.setAttribute("checked", "true");
+      } else {
+        broadcaster.removeAttribute("checked");
+      }
+    }
+  },
+
+  /**
+   * Remove the menuitem for a tool to all open browser windows.
+   *
+   * @param {object} toolId
+   *        id of the tool to remove
+   */
+  _removeToolFromWindows: function DT_removeToolFromWindows(toolId) {
+    for (let win of this._trackedBrowserWindows) {
+      this._removeToolFromMenu(toolId, win.document);
+    }
+  },
+
+  /**
+   * Remove a tool's menuitem from a window
+   *
+   * @param {string} toolId
+   *        Id of the tool to add a menu entry for
+   * @param {XULDocument} doc
+   *        The document to which the tool menu item is to be removed from
+   */
+  _removeToolFromMenu: function DT_removeToolFromMenu(toolId, doc) {
+    let command = doc.getElementById("Tools:" + toolId);
+    command.parentNode.removeChild(command);
+
+    let key = doc.getElementById("key_" + toolId);
+    if (key) {
+      key.parentNode.removeChild(key);
+    }
+
+    let bc = doc.getElementById("devtoolsMenuBroadcaster_" + toolId);
+    bc.parentNode.removeChild(bc);
+
+    /*
+    // FIXME: item is null in testing. This is the only place to use
+    // "appmenu_devToolbar" + toolId, so it seems clear that this is wrong
+    let item = doc.getElementById("appmenu_devToolbar" + toolId);
+    item.parentNode.removeChild(item);
+    */
+  },
+
+  /**
+   * Called on browser unload to remove menu entries, toolboxes and event
+   * listeners from the closed browser window.
+   *
+   * @param  {XULWindow} win
+   *         The window containing the menu entry
+   */
+  forgetBrowserWindow: function DT_forgetBrowserWindow(win) {
+    if (!this._tools) {
+      return;
+    }
+
+    this._trackedBrowserWindows.delete(win);
+
+    // Destroy toolboxes for closed window
+    for (let [target, toolbox] of this._toolboxes) {
+      if (toolbox.frame.ownerDocument.defaultView == win) {
+        toolbox.destroy();
+      }
+    }
+
+    let tabContainer = win.document.getElementById("tabbrowser-tabs")
+    tabContainer.removeEventListener("TabSelect",
+                                     this._updateMenuCheckbox, false);
+  },
+
+  /**
+   * All browser windows have been closed, tidy up remaining objects.
+   */
+  destroy: function() {
+    Services.obs.removeObserver(this.destroy, "quit-application");
+
+    delete this._trackedBrowserWindows;
+    delete this._tools;
+    delete this._toolboxes;
+  },
+};
+
+/**
+ * gDevTools is a singleton that controls the Firefox Developer Tools.
+ *
+ * It is an instance of a DevTools class that holds a set of tools. It has the
+ * same lifetime as the browser.
+ */
+this.gDevTools = new DevTools();
+
+/**
+ * DevToolsXULCommands exposes methods used by browser's <command>s.
+ */
+this.DevToolsXULCommands = {
+  openConnectScreen: function(gBrowser) {
+    gBrowser.selectedTab = gBrowser.addTab("chrome://browser/content/devtools/connect.xhtml");
+  },
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/test/Makefile.in
@@ -0,0 +1,26 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DEPTH			= @DEPTH@
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH			= @srcdir@
+relativesrcdir  = @relativesrcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MOCHITEST_BROWSER_FILES = \
+		head.js \
+		browser_devtools_api.js \
+		browser_new_activation_workflow.js \
+		browser_toolbox_dynamic_registration.js \
+		browser_toolbox_hosts.js \
+		browser_toolbox_ready.js \
+		browser_toolbox_select_event.js \
+		browser_target_events.js \
+		browser_toolbox_tool_ready.js \
+		browser_toolbox_sidebar.js \
+		$(NULL)
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/test/browser_devtools_api.js
@@ -0,0 +1,137 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Tests devtools API
+
+const Cu = Components.utils;
+const toolId = "test-tool";
+
+let tempScope = {};
+Cu.import("resource:///modules/devtools/EventEmitter.jsm", tempScope);
+let EventEmitter = tempScope.EventEmitter;
+Cu.import("resource:///modules/devtools/Target.jsm", tempScope);
+let TargetFactory = tempScope.TargetFactory;
+
+function test() {
+  addTab("about:blank", function(aBrowser, aTab) {
+    runTests(aTab);
+  });
+}
+
+function runTests(aTab) {
+  let toolDefinition = {
+    id: toolId,
+    isTargetSupported: function() true,
+    killswitch: "devtools.test-tool.enabled",
+    url: "about:blank",
+    label: "someLabel",
+    build: function(iframeWindow, toolbox) {
+      let panel = new DevToolPanel(iframeWindow, toolbox);
+      return panel;
+    },
+  };
+
+  ok(gDevTools, "gDevTools exists");
+  is(gDevTools.getToolDefinitions().has(toolId), false,
+    "The tool is not registered");
+
+  gDevTools.registerTool(toolDefinition);
+  is(gDevTools.getToolDefinitions().has(toolId), true,
+    "The tool is registered");
+
+  let target = TargetFactory.forTab(gBrowser.selectedTab);
+
+  function onNewToolbox(event, toolboxFromEvent) {
+    let toolBoxes = gDevTools._toolboxes;
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    let tb = toolBoxes.get(target);
+    is(toolboxFromEvent, tb, "'toolbox-ready' event fired. Correct toolbox value.");
+    is(tb.target, target, "toolbox target is correct");
+    is(tb._host.hostTab, gBrowser.selectedTab, "toolbox host is correct");
+    gDevTools.once(toolId + "-ready", continueTests);
+  }
+
+  function onToolboxClosed(event, targetFromEvent) {
+    is(targetFromEvent, target, "'toolbox-destroyed' event fired. Correct tab value.");
+    finishUp();
+  }
+
+
+  gDevTools.once("toolbox-ready", onNewToolbox);
+  gDevTools.once("toolbox-destroyed", onToolboxClosed);
+
+  executeSoon(function() {
+    gDevTools.openToolbox(target, "bottom", toolId);
+  });
+}
+
+function continueTests(event, toolbox, panel) {
+  let target = TargetFactory.forTab(gBrowser.selectedTab);
+  is(toolbox, gDevTools._toolboxes.get(target), "{toolId}-ready event received, with correct toolbox value");
+  is(panel, toolbox.getToolPanels().get(toolId), "panel value is correct");
+
+  is(toolbox.currentToolId, toolId, "toolbox _currentToolId is correct");
+
+  let toolDefinitions = gDevTools.getToolDefinitions();
+  is(toolDefinitions.has(toolId), true, "The tool is in gDevTools");
+
+  let toolDefinition = toolDefinitions.get(toolId);
+  is(toolDefinition.id, toolId, "toolDefinition id is correct");
+
+  gDevTools.unregisterTool(toolId);
+  is(gDevTools.getToolDefinitions().has(toolId), false,
+    "The tool is no longer registered");
+
+  toolbox.destroy();
+}
+
+function finishUp() {
+  tempScope = null;
+  gBrowser.removeCurrentTab();
+  finish();
+}
+
+/**
+* When a Toolbox is started it creates a DevToolPanel for each of the tools
+* by calling toolDefinition.build(). The returned object should
+* at least implement these functions. They will be used by the ToolBox.
+*
+* There may be no benefit in doing this as an abstract type, but if nothing
+* else gives us a place to write documentation.
+*/
+function DevToolPanel(iframeWindow, toolbox) {
+  new EventEmitter(this);
+
+  this._toolbox = toolbox;
+
+  /*let doc = iframeWindow.document
+  let label = doc.createElement("label");
+  let textNode = doc.createTextNode("Some Tool");
+
+  label.appendChild(textNode);
+  doc.body.appendChild(label);*/
+
+  executeSoon(function() {
+    this.setReady();
+  }.bind(this));
+}
+
+DevToolPanel.prototype = {
+  get target() this._toolbox.target,
+
+  get toolbox() this._toolbox,
+
+  get isReady() this._isReady,
+
+  _isReady: false,
+
+  setReady: function() {
+    this._isReady = true;
+    this.emit("ready");
+  },
+
+  destroy: function DTI_destroy()
+  {
+
+  },
+};
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/test/browser_new_activation_workflow.js
@@ -0,0 +1,64 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Tests devtools API
+
+const Cu = Components.utils;
+
+let toolbox;
+
+let tempScope = {};
+Cu.import("resource:///modules/devtools/Target.jsm", tempScope);
+let TargetFactory = tempScope.TargetFactory;
+
+function test() {
+  addTab("about:blank", function(aBrowser, aTab) {
+    loadWebConsole(aTab);
+  });
+}
+
+function loadWebConsole(aTab) {
+  ok(gDevTools, "gDevTools exists");
+
+  let target = TargetFactory.forTab(gBrowser.selectedTab);
+  toolbox = gDevTools.openToolbox(target, "bottom", "webconsole");
+  toolbox.once("webconsole-ready", checkToolLoading);
+}
+
+function checkToolLoading() {
+  is(toolbox.currentToolId, "webconsole", "The web console is selected");
+  selectAndCheckById("jsdebugger");
+  selectAndCheckById("styleeditor");
+  testToggle();
+}
+
+function selectAndCheckById(id) {
+  let doc = toolbox.frame.contentDocument;
+
+  toolbox.selectTool(id);
+  let tab = doc.getElementById("toolbox-tab-" + id);
+  is(tab.selected, true, "The " + id + " tab is selected");
+}
+
+function testToggle() {
+  toolbox.once("destroyed", function() {
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    toolbox = gDevTools.openToolbox(target, "bottom", "styleeditor");
+    toolbox.once("styleeditor-ready", checkStyleEditorLoaded);
+  }.bind(this));
+
+  let target = TargetFactory.forTab(gBrowser.selectedTab);
+  gDevTools.toggleToolboxForTarget(target);
+}
+
+function checkStyleEditorLoaded() {
+  is(toolbox.currentToolId, "styleeditor", "The style editor is selected");
+  finishUp();
+}
+
+function finishUp() {
+  toolbox.destroy();
+  toolbox = null;
+  gBrowser.removeCurrentTab();
+  finish();
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/test/browser_target_events.js
@@ -0,0 +1,58 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+var tempScope = {};
+Cu.import("resource:///modules/devtools/Target.jsm", tempScope);
+var TargetFactory = tempScope.TargetFactory;
+
+var target;
+
+function test()
+{
+  waitForExplicitFinish();
+
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", onLoad, true);
+}
+
+function onLoad(evt) {
+  gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
+
+  target = TargetFactory.forTab(gBrowser.selectedTab);
+
+  is(target.tab, gBrowser.selectedTab, "Target linked to the right tab.");
+
+  target.once("hidden", onHidden);
+  gBrowser.selectedTab = gBrowser.addTab();
+}
+
+function onHidden() {
+  ok(true, "Hidden event received");
+  target.once("visible", onVisible);
+  gBrowser.removeCurrentTab();
+}
+
+function onVisible() {
+  ok(true, "Visible event received");
+  target.once("will-navigate", onWillNavigate);
+  gBrowser.contentWindow.location = "data:text/html,test navigation";
+}
+
+function onWillNavigate(event, request) {
+  ok(true, "will-navigate event received");
+  target.once("navigate", onNavigate);
+}
+
+function onNavigate() {
+  ok(true, "navigate event received");
+  target.once("close", onClose);
+  gBrowser.removeCurrentTab();
+}
+
+function onClose() {
+  ok(true, "close event received");
+
+  target = null;
+  finish();
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/test/browser_toolbox_dynamic_registration.js
@@ -0,0 +1,112 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let toolbox;
+
+let temp = {};
+Cu.import("resource:///modules/devtools/Target.jsm", temp);
+let TargetFactory = temp.TargetFactory;
+
+function test()
+{
+  waitForExplicitFinish();
+
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
+    gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
+    openToolbox();
+  }, true);
+
+  content.location = "data:text/html,test for dynamically registering and unregistering tools";
+}
+
+function openToolbox()
+{
+  let target = TargetFactory.forTab(gBrowser.selectedTab);
+  toolbox = gDevTools.openToolbox(target);
+
+  toolbox.once("ready", testRegister);
+}
+
+
+function testRegister()
+{
+  gDevTools.once("tool-registered", toolRegistered);
+
+  gDevTools.registerTool({
+    id: "test-tool",
+    label: "Test Tool",
+    isTargetSupported: function() true,
+    build: function() {}
+  });
+}
+
+function toolRegistered(event, toolId)
+{
+  is(toolId, "test-tool", "tool-registered event handler sent tool id");
+
+  ok(gDevTools.getToolDefinitions().has(toolId), "tool added to map");
+
+  // test that it appeared in the UI
+  let doc = toolbox.frame.contentDocument;
+  let tab = doc.getElementById("toolbox-tab-" + toolId);
+  ok(tab, "new tool's tab exists in toolbox UI");
+
+  let panel = doc.getElementById("toolbox-panel-" + toolId);
+  ok(panel, "new tool's panel exists in toolbox UI");
+
+  for (let win of getAllBrowserWindows()) {
+    let command = win.document.getElementById("Tools:" + toolId);
+    ok(command, "command for new tool added to every browser window");
+  }
+
+  // then unregister it
+  testUnregister();
+}
+
+function getAllBrowserWindows() {
+  let wins = [];
+  let enumerator = Services.wm.getEnumerator("navigator:browser");
+  while (enumerator.hasMoreElements()) {
+    wins.push(enumerator.getNext());
+  }
+  return wins;
+}
+
+function testUnregister()
+{
+  gDevTools.once("tool-unregistered", toolUnregistered);
+
+  gDevTools.unregisterTool("test-tool");
+}
+
+function toolUnregistered(event, toolId)
+{
+  is(toolId, "test-tool", "tool-unregistered event handler sent tool id");
+
+  ok(!gDevTools.getToolDefinitions().has(toolId), "tool removed from map");
+
+  // test that it disappeared from the UI
+  let doc = toolbox.frame.contentDocument;
+  let tab = doc.getElementById("toolbox-tab-" + toolId);
+  ok(!tab, "tool's tab was removed from the toolbox UI");
+
+  let panel = doc.getElementById("toolbox-panel-" + toolId);
+  ok(!panel, "tool's panel was removed from toolbox UI");
+
+  for (let win of getAllBrowserWindows()) {
+    let command = win.document.getElementById("Tools:" + toolId);
+    ok(!command, "command removed from every browser window");
+  }
+
+  cleanup();
+}
+
+function cleanup()
+{
+  toolbox.destroy();
+  toolbox = null;
+  gBrowser.removeCurrentTab();
+  finish();
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/test/browser_toolbox_hosts.js
@@ -0,0 +1,135 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let temp = {}
+Cu.import("resource:///modules/devtools/gDevTools.jsm", temp);
+let DevTools = temp.DevTools;
+
+Cu.import("resource:///modules/devtools/Toolbox.jsm", temp);
+let Toolbox = temp.Toolbox;
+
+Cu.import("resource:///modules/devtools/Target.jsm", temp);
+let TargetFactory = temp.TargetFactory;
+
+let toolbox;
+
+function test()
+{
+  waitForExplicitFinish();
+
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
+    gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
+    openToolbox(testBottomHost);
+  }, true);
+
+  content.location = "data:text/html,test for opening toolbox in different hosts";
+}
+
+function openToolbox(callback)
+{
+  let target = TargetFactory.forTab(gBrowser.selectedTab);
+  gDevTools.toggleToolboxForTarget(target);
+
+  toolbox = gDevTools.getToolboxForTarget(target);
+  toolbox.once("ready", callback);
+}
+
+function testBottomHost()
+{
+  checkHostType(Toolbox.HostType.BOTTOM);
+
+  // test UI presence
+  let iframe = document.getElementById("devtools-toolbox-bottom-iframe");
+  ok(iframe, "toolbox bottom iframe exists");
+
+  checkToolboxLoaded(iframe);
+
+  toolbox.once("host-changed", testSidebarHost);
+  toolbox.hostType = Toolbox.HostType.SIDE;
+}
+
+function testSidebarHost()
+{
+  checkHostType(Toolbox.HostType.SIDE);
+
+  // test UI presence
+  let bottom = document.getElementById("devtools-toolbox-bottom-iframe");
+  ok(!bottom, "toolbox bottom iframe doesn't exist");
+
+  let iframe = document.getElementById("devtools-toolbox-side-iframe");
+  ok(iframe, "toolbox side iframe exists");
+
+  checkToolboxLoaded(iframe);
+
+  toolbox.once("host-changed", testWindowHost);
+  toolbox.hostType = Toolbox.HostType.WINDOW;
+}
+
+function testWindowHost()
+{
+  checkHostType(Toolbox.HostType.WINDOW);
+
+  let sidebar = document.getElementById("devtools-toolbox-side-iframe");
+  ok(!sidebar, "toolbox sidebar iframe doesn't exist");
+
+  let win = Services.wm.getMostRecentWindow("devtools:toolbox");
+  ok(win, "toolbox separate window exists");
+
+  let iframe = win.document.getElementById("toolbox-iframe");
+  checkToolboxLoaded(iframe);
+
+  testToolSelect();
+}
+
+function testToolSelect()
+{
+  // make sure we can load a tool after switching hosts
+  toolbox.once("inspector-ready", testDestroy);
+  toolbox.selectTool("inspector");
+}
+
+function testDestroy()
+{
+  toolbox.once("destroyed", function() {
+    openToolbox(testRememberHost);
+  });
+
+  toolbox.destroy();
+}
+
+function testRememberHost()
+{
+  // last host was the window - make sure it's the same when re-opening
+  is(toolbox.hostType, Toolbox.HostType.WINDOW, "host remembered");
+
+  let win = Services.wm.getMostRecentWindow("devtools:toolbox");
+  ok(win, "toolbox separate window exists");
+
+  cleanup();
+}
+
+function checkHostType(hostType)
+{
+  is(toolbox.hostType, hostType, "host type is " + hostType);
+
+  let pref = Services.prefs.getCharPref("devtools.toolbox.host");
+  is(pref, hostType, "host pref is " + hostType);
+}
+
+function checkToolboxLoaded(iframe)
+{
+  let tabs = iframe.contentDocument.getElementById("toolbox-tabs");
+  ok(tabs, "toolbox UI has been loaded into iframe");
+}
+
+function cleanup()
+{
+  Services.prefs.setCharPref("devtools.toolbox.host", Toolbox.HostType.BOTTOM);
+
+  toolbox.destroy();
+  DevTools = Toolbox = toolbox = null;
+  gBrowser.removeCurrentTab();
+  finish();
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/test/browser_toolbox_ready.js
@@ -0,0 +1,56 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let tempScope = {};
+Cu.import("resource:///modules/devtools/Target.jsm", tempScope);
+let TargetFactory = tempScope.TargetFactory;
+
+let toolbox;
+
+function test()
+{
+  waitForExplicitFinish();
+
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
+    gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
+    openToolbox();
+  }, true);
+
+  content.location = "data:text/html,test for dynamically registering and unregistering tools";
+}
+
+function openToolbox()
+{
+  let target = TargetFactory.forTab(gBrowser.selectedTab);
+  gDevTools.toggleToolboxForTarget(target);
+
+  toolbox = gDevTools.getToolboxForTarget(target);
+
+  ok(!toolbox.isReady, "toolbox isReady isn't set yet");
+
+  try {
+    toolbox.selectTool("webconsole");
+    ok(false, "Should throw when selectTool() called before toolbox is ready");
+  }
+  catch(error) {
+    is(error.message, "Can't select tool, wait for toolbox 'ready' event")
+  }
+
+  toolbox.once("ready", testReady);
+}
+
+function testReady()
+{
+  ok(toolbox.isReady, "toolbox isReady is set");
+  cleanup();
+}
+
+function cleanup()
+{
+  toolbox.destroy();
+  toolbox = null;
+  gBrowser.removeCurrentTab();
+  finish();
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/test/browser_toolbox_select_event.js
@@ -0,0 +1,97 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let toolbox;
+
+function test() {
+  addTab("about:blank", function() {
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    toolbox = gDevTools.openToolbox(target, "bottom", "webconsole");
+    toolbox.once("ready", testSelect);
+  });
+}
+
+let called = {
+  inspector: false,
+  webconsole: false,
+  styleeditor: false,
+  //jsdebugger: false,
+}
+
+function testSelect() {
+  info("Toolbox fired a `ready` event");
+
+  toolbox.on("select", selectCB);
+
+  toolbox.selectTool("inspector");
+  toolbox.selectTool("webconsole");
+  toolbox.selectTool("styleeditor");
+  //toolbox.selectTool("jsdebugger");
+}
+
+function selectCB(event, id) {
+  called[id] = true;
+  info("toolbox-select event from " + id);
+
+  for (let tool in called) {
+    if (!called[tool]) {
+      return;
+    }
+  }
+
+  ok(true, "All the tools fired a 'select event'");
+  toolbox.off("select", selectCB);
+
+  reselect();
+}
+
+function reselect() {
+  for (let tool in called) {
+    called[tool] = false;
+  }
+
+  toolbox.once("inspector-selected", function() {
+    tidyUpIfAllCalled("inspector");
+  });
+
+  toolbox.once("webconsole-selected", function() {
+    tidyUpIfAllCalled("webconsole");
+  });
+
+  /*
+  toolbox.once("jsdebugger-selected", function() {
+    tidyUpIfAllCalled("jsdebugger");
+  });
+  */
+
+  toolbox.once("styleeditor-selected", function() {
+    tidyUpIfAllCalled("styleeditor");
+  });
+
+  toolbox.selectTool("inspector");
+  toolbox.selectTool("webconsole");
+  toolbox.selectTool("styleeditor");
+  //toolbox.selectTool("jsdebugger");
+}
+
+function tidyUpIfAllCalled(id) {
+  called[id] = true;
+  info("select event from " + id);
+
+  for (let tool in called) {
+    if (!called[tool]) {
+      return;
+    }
+  }
+
+  ok(true, "All the tools fired a {id}-selected event");
+  tidyUp();
+}
+
+function tidyUp() {
+  toolbox.destroy();
+  gBrowser.removeCurrentTab();
+
+  toolbox = null;
+  finish();
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/test/browser_toolbox_sidebar.js
@@ -0,0 +1,132 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+  const Cu = Components.utils;
+  let tempScope = {};
+  Cu.import("resource:///modules/devtools/gDevTools.jsm", tempScope);
+  Cu.import("resource:///modules/devtools/Target.jsm", tempScope);
+  Cu.import("resource:///modules/devtools/Sidebar.jsm", tempScope);
+  let {TargetFactory: TargetFactory, gDevTools: gDevTools, ToolSidebar: ToolSidebar} = tempScope;
+
+  const toolURL = "data:text/xml;charset=utf8,<?xml version='1.0'?>" +
+                  "<?xml-stylesheet href='chrome://browser/skin/devtools/common.css' type='text/css'?>" +
+                  "<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'>" +
+                  "<hbox flex='1'><description flex='1'>foo</description><splitter class='devtools-side-splitter'/>" +
+                  "<tabbox flex='1' id='sidebar' class='devtools-sidebar-tabs'><tabs/><tabpanels flex='1'/></tabbox>" +
+                  "</hbox>" +
+                  "</window>";
+
+  const tab1URL = "data:text/html;charset=utf8,<title>1</title><p>1</p>";
+  const tab2URL = "data:text/html;charset=utf8,<title>2</title><p>2</p>";
+  const tab3URL = "data:text/html;charset=utf8,<title>3</title><p>3</p>";
+
+  let panelDoc;
+
+  let registeredTabs = {};
+  let readyTabs = {};
+
+  let toolDefinition = {
+    id: "fakeTool4242",
+    killswitch: "devtools.fakeTool4242.enabled",
+    url: toolURL,
+    label: "FAKE TOOL!!!",
+    isTargetSupported: function() true,
+    build: function(iframeWindow, toolbox) {
+      let panel = {
+        target: toolbox.target,
+        toolbox: toolbox,
+        isReady: true,
+        destroy: function(){},
+        panelDoc: iframeWindow.document,
+      }
+      return panel;
+    },
+  };
+
+  gDevTools.registerTool(toolDefinition);
+
+  addTab("about:blank", function(aBrowser, aTab) {
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    let toolbox = gDevTools.openToolbox(target, "bottom", "fakeTool4242");
+    toolbox.once("fakeTool4242-ready", function(event, panel) {
+      ok(true, "Tool open");
+
+      let tabbox = panel.panelDoc.getElementById("sidebar");
+      panel.sidebar = new ToolSidebar(tabbox, panel, true);
+
+      panel.sidebar.on("new-tab-registered", function(event, id) {
+        registeredTabs[id] = true;
+      });
+
+      panel.sidebar.once("tab1-ready", function(event) {
+        readyTabs.tab1 = true;
+        if (readyTabs.tab1 && readyTabs.tab2 && readyTabs.tab3) {
+          allTabsReady(panel);
+        }
+      });
+
+      panel.sidebar.once("tab2-ready", function(event) {
+        readyTabs.tab2 = true;
+        if (readyTabs.tab1 && readyTabs.tab2 && readyTabs.tab3) {
+          allTabsReady(panel);
+        }
+      });
+
+      panel.sidebar.once("tab3-ready", function(event) {
+        readyTabs.tab3 = true;
+        if (readyTabs.tab1 && readyTabs.tab2 && readyTabs.tab3) {
+          allTabsReady(panel);
+        }
+      });
+
+      panel.sidebar.addTab("tab1", tab1URL, true);
+      panel.sidebar.addTab("tab2", tab2URL);
+      panel.sidebar.addTab("tab3", tab3URL);
+
+      panel.sidebar.show();
+    });
+  });
+
+  function allTabsReady(panel) {
+    ok(registeredTabs.tab1, "tab1 registered");
+    ok(registeredTabs.tab2, "tab2 registered");
+    ok(registeredTabs.tab3, "tab3 registered");
+    ok(readyTabs.tab1, "tab1 ready");
+    ok(readyTabs.tab2, "tab2 ready");
+    ok(readyTabs.tab3, "tab3 ready");
+
+    let tabs = panel.sidebar._tabbox.querySelectorAll("tab");
+    let panels = panel.sidebar._tabbox.querySelectorAll("tabpanel");
+    let label = 1;
+    for (let tab of tabs) {
+      is(tab.getAttribute("label"), label++, "Tab has the right title");
+    }
+    is(label, 4, "Found the right amount of tabs.");
+    is(panel.sidebar._tabbox.selectedPanel, panels[0], "First tab is selected");
+    ok(panel.sidebar.getCurrentTabID(), "tab1", "getCurrentTabID() is correct");
+
+    panel.sidebar.once("tab1-unselected", function() {
+      ok(true, "received 'unselected' event");
+      panel.sidebar.once("tab2-selected", function() {
+        ok(true, "received 'selected' event");
+        panel.sidebar.hide();
+        is(panel.sidebar._tabbox.getAttribute("hidden"), "true", "Sidebar hidden");
+        is(panel.sidebar.getWindowForTab("tab1").location.href, tab1URL, "Window is accessible");
+        finishUp(panel);
+      });
+    });
+
+    panel.sidebar.select("tab2");
+  }
+
+  function finishUp(panel) {
+    panel.sidebar.destroy();
+    gDevTools.unregisterTool(toolDefinition.id);
+
+    executeSoon(function() {
+      gBrowser.removeCurrentTab();
+      finish();
+    });
+  }
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/test/browser_toolbox_tool_ready.js
@@ -0,0 +1,72 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let temp = [];
+Cu.import("resource:///modules/devtools/Target.jsm", temp);
+let TargetFactory = temp.TargetFactory;
+
+function test() {
+  waitForExplicitFinish();
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
+    gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
+    openAllTools();
+  }, true);
+
+  function openAllTools() {
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+
+    let tools = gDevTools.getToolDefinitions();
+    let expectedCallbacksCount = tools.size;
+
+    let firstTool = null;
+    // we transform the map to a [id, eventHasBeenFiredYet] map
+    for (let [id] of tools) {
+      if (!firstTool)
+        firstTool = id;
+      tools.set(id, false);
+    }
+
+    let toolbox = gDevTools.openToolbox(target, undefined, firstTool);
+
+    // We add the event listeners
+    for (let [toolId] of tools) {
+      let id = toolId;
+      info("Registering listener for " + id);
+      tools.set(id, false);
+      toolbox.on(id + "-ready", function(event, panel) {
+        expectedCallbacksCount--;
+        info("Got event "  + event);
+        is(toolbox.getToolPanels().get(id), panel, "Got the right tool panel for " + id);
+        tools.set(id, true);
+        if (expectedCallbacksCount == 0) {
+          // "executeSoon" because we want to let a chance
+          // to falsy code to fire unexpected ready events.
+          executeSoon(theEnd);
+        }
+        if (expectedCallbacksCount < 0) {
+          ok(false, "we are receiving too many events");
+        }
+      });
+    }
+
+    toolbox.once("ready", function() {
+      // We open all the 
+      for (let [id] of tools) {
+        if (id != firstTool) {
+          toolbox.selectTool(id);
+        }
+      }
+    });
+
+    function theEnd() {
+      for (let [id, called] of tools) {
+        ok(called, "Tool " + id + " has fired its ready event");
+      }
+      toolbox.destroy();
+      gBrowser.removeCurrentTab();
+      finish();
+    }
+  }
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/test/head.js
@@ -0,0 +1,36 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+let tempScope = {};
+Components.utils.import("resource:///modules/devtools/Target.jsm", tempScope);
+let TargetFactory = tempScope.TargetFactory;
+Components.utils.import("resource:///modules/devtools/Console.jsm", tempScope);
+let console = tempScope.console;
+
+/**
+ * Open a new tab at a URL and call a callback on load
+ */
+function addTab(aURL, aCallback)
+{
+  waitForExplicitFinish();
+
+  gBrowser.selectedTab = gBrowser.addTab();
+  content.location = aURL;
+
+  let tab = gBrowser.selectedTab;
+  let browser = gBrowser.getBrowserForTab(tab);
+
+  function onTabLoad() {
+    browser.removeEventListener("load", onTabLoad, true);
+    aCallback(browser, tab, browser.contentDocument);
+  }
+
+  browser.addEventListener("load", onTabLoad, true);
+}
+
+registerCleanupFunction(function tearDown() {
+  while (gBrowser.tabs.length > 1) {
+    gBrowser.removeCurrentTab();
+  }
+});
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/toolbox-window.xul
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<!DOCTYPE window [
+<!ENTITY % toolboxDTD SYSTEM "chrome://browser/locale/devtools/toolbox.dtd" >
+ %toolboxDTD;
+]>
+
+<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        id="devtools-toolbox-window"
+        title="&window.title;"
+        macanimationtype="document"
+        fullscreenbutton="true"
+        windowtype="devtools:toolbox"
+        width="700" height="320"
+        persist="screenX screenY width height sizemode">
+
+  <commandset id="toolbox-commandset">
+    <command id="toolbox-cmd-close" oncommand="window.close();"/>
+  </commandset>
+
+  <keyset id="toolbox-keyset">
+    <key id="toolbox-key-close"
+         key="&closeCmd.key;"
+         command="toolbox-cmd-close"
+         modifiers="accel"/>
+  </keyset>
+
+  <iframe id="toolbox-iframe" flex="1"></iframe>
+</window>
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/toolbox.css
@@ -0,0 +1,10 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+.devtools-tab > .radio-check,
+.devtools-tab > .radio-check-box1,
+.devtools-tab > .radio-spacer-box {
+  display: none;
+}
+
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/toolbox.xul
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/content/devtools/shared/common.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/content/devtools/framework/toolbox.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/skin/devtools/common.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/skin/devtools/toolbox.css" type="text/css"?>
+<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
+<?xul-overlay href="chrome://browser/content/source-editor-overlay.xul"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <notificationbox id="toolbox-notificationbox" flex="1">
+    <toolbar class="devtools-tabbar">
+      <hbox id="toolbox-controls">
+        <toolbarbutton id="toolbox-close" class="devtools-closebutton"></toolbarbutton>
+        <hbox id="toolbox-dock-buttons"/>
+      </hbox>
+      <radiogroup id="toolbox-tabs" orient="horizontal">
+      </radiogroup>
+      <hbox id="toolbox-buttons" flex="1" pack="end"/>
+    </toolbar>
+    <deck id="toolbox-deck" flex="1">
+    </deck>
+  </notificationbox>
+</window>
deleted file mode 100644
--- a/browser/devtools/highlighter/CmdInspect.jsm
+++ /dev/null
@@ -1,29 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-this.EXPORTED_SYMBOLS = [ ];
-
-Cu.import("resource:///modules/devtools/gcli.jsm");
-
-/**
- * 'inspect' command
- */
-gcli.addCommand({
-  name: "inspect",
-  description: gcli.lookup("inspectDesc"),
-  manual: gcli.lookup("inspectManual"),
-  params: [
-    {
-      name: "selector",
-      type: "node",
-      description: gcli.lookup("inspectNodeDesc"),
-      manual: gcli.lookup("inspectNodeManual")
-    }
-  ],
-  exec: function Command_inspect(args, context) {
-    let document = context.environment.chromeDocument;
-    document.defaultView.InspectorUI.openInspectorUI(args.selector);
-  }
-});
deleted file mode 100644
--- a/browser/devtools/highlighter/Makefile.in
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DEPTH		= @DEPTH@
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-EXTRA_JS_MODULES = \
-	highlighter.jsm \
-	$(NULL)
-
-EXTRA_PP_JS_MODULES = \
-	inspector.jsm \
-	$(NULL)
-
-TEST_DIRS += test
-
-include $(topsrcdir)/config/rules.mk
-
-libs::
-	$(NSINSTALL) $(srcdir)/CmdInspect.jsm $(FINAL_TARGET)/modules/devtools
deleted file mode 100644
--- a/browser/devtools/highlighter/highlighter.jsm
+++ /dev/null
@@ -1,905 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const Cu = Components.utils;
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource:///modules/devtools/LayoutHelpers.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-this.EXPORTED_SYMBOLS = ["Highlighter"];
-
-const INSPECTOR_INVISIBLE_ELEMENTS = {
-  "head": true,
-  "base": true,
-  "basefont": true,
-  "isindex": true,
-  "link": true,
-  "meta": true,
-  "script": true,
-  "style": true,
-  "title": true,
-};
-
-const PSEUDO_CLASSES = [":hover", ":active", ":focus"];
-  // add ":visited" and ":link" after bug 713106 is fixed
-
-/**
- * A highlighter mechanism.
- *
- * The highlighter is built dynamically into the browser element.
- * The caller is in charge of destroying the highlighter (ie, the highlighter
- * won't be destroyed if a new tab is selected for example).
- *
- * API:
- *
- *   // Constructor and destructor.
- *   // @param aWindow - browser.xul window.
- *   Highlighter(aWindow);
- *   void destroy();
- *
- *   // Highlight a node.
- *   // @param aNode - node to highlight
- *   // @param aScroll - scroll to ensure the node is visible
- *   void highlight(aNode, aScroll);
- *
- *   // Get the selected node.
- *   DOMNode getNode();
- *
- *   // Lock and unlock the select node.
- *   void lock();
- *   void unlock();
- *
- *   // Show and hide the highlighter
- *   void show();
- *   void hide();
- *   boolean isHidden();
- *
- *   // Redraw the highlighter if the visible portion of the node has changed.
- *   void invalidateSize(aScroll);
- *
- *   // Is a node highlightable.
- *   boolean isNodeHighlightable(aNode);
- *
- *   // Show/hide the outline and the infobar
- *   void showInfobar();
- *   void hideInfobar();
- *   void showOutline();
- *   void hideOutline();
- *
- *   // Add/Remove listeners
- *   // @param aEvent - event name
- *   // @param aListener - function callback
- *   void addListener(aEvent, aListener);
- *   void removeListener(aEvent, aListener);
- *
- * Events:
- *
- *   "closed" - Highlighter is closing
- *   "nodeselected" - A new node has been selected
- *   "highlighting" - Highlighter is highlighting
- *   "locked" - The selected node has been locked
- *   "unlocked" - The selected ndoe has been unlocked
- *   "pseudoclasstoggled" - A pseudo-class lock has changed on the selected node
- *
- * Structure:
- *  <stack id="highlighter-container">
- *    <box id="highlighter-outline-container">
- *      <box id="highlighter-outline" locked="true/false"/>
- *    </box>
- *    <box id="highlighter-controls">
- *      <box id="highlighter-nodeinfobar-container" position="top/bottom" locked="true/false">
- *        <box class="highlighter-nodeinfobar-arrow" id="highlighter-nodeinfobar-arrow-top"/>
- *        <hbox id="highlighter-nodeinfobar">
- *          <toolbarbutton id="highlighter-nodeinfobar-inspectbutton" class="highlighter-nodeinfobar-button"/>
- *          <hbox id="highlighter-nodeinfobar-text">tagname#id.class1.class2</hbox>
- *          <toolbarbutton id="highlighter-nodeinfobar-menu" class="highlighter-nodeinfobar-button">…</toolbarbutton>
- *        </hbox>
- *        <box class="highlighter-nodeinfobar-arrow" id="highlighter-nodeinfobar-arrow-bottom"/>
- *      </box>
- *    </box>
- *  </stack>
- *
- */
-
-
-/**
- * Constructor.
- *
- * @param object aWindow
- */
-this.Highlighter = function Highlighter(aWindow)
-{
-  this.chromeWin = aWindow;
-  this.tabbrowser = aWindow.gBrowser;
-  this.chromeDoc = aWindow.document;
-  this.browser = aWindow.gBrowser.selectedBrowser;
-  this.events = {};
-
-  this._init();
-}
-
-Highlighter.prototype = {
-  _init: function Highlighter__init()
-  {
-    let stack = this.browser.parentNode;
-    this.win = this.browser.contentWindow;
-    this._highlighting = false;
-
-    this.highlighterContainer = this.chromeDoc.createElement("stack");
-    this.highlighterContainer.id = "highlighter-container";
-
-    this.outline = this.chromeDoc.createElement("box");
-    this.outline.id = "highlighter-outline";
-
-    let outlineContainer = this.chromeDoc.createElement("box");
-    outlineContainer.appendChild(this.outline);
-    outlineContainer.id = "highlighter-outline-container";
-
-    // The controlsBox will host the different interactive
-    // elements of the highlighter (buttons, toolbars, ...).
-    let controlsBox = this.chromeDoc.createElement("box");
-    controlsBox.id = "highlighter-controls";
-    this.highlighterContainer.appendChild(outlineContainer);
-    this.highlighterContainer.appendChild(controlsBox);
-
-    // Insert the highlighter right after the browser
-    stack.insertBefore(this.highlighterContainer, stack.childNodes[1]);
-
-    this.buildInfobar(controlsBox);
-
-    this.transitionDisabler = null;
-    this.pageEventsMuter = null;
-
-    this.unlock();
-
-    this.hidden = true;
-    this.show();
-  },
-
-  /**
-   * Destroy the nodes. Remove listeners.
-   */
-  destroy: function Highlighter_destroy()
-  {
-    this.detachMouseListeners();
-    this.detachPageListeners();
-
-    this.chromeWin.clearTimeout(this.transitionDisabler);
-    this.chromeWin.clearTimeout(this.pageEventsMuter);
-    this.boundCloseEventHandler = null;
-    this._contentRect = null;
-    this._highlightRect = null;
-    this._highlighting = false;
-    this.outline = null;
-    this.node = null;
-    this.nodeInfo = null;
-    this.highlighterContainer.parentNode.removeChild(this.highlighterContainer);
-    this.highlighterContainer = null;
-    this.win = null
-    this.browser = null;
-    this.chromeDoc = null;
-    this.chromeWin = null;
-    this.tabbrowser = null;
-
-    this.emitEvent("closed");
-    this.removeAllListeners();
-  },
-
-  /**
-   * Show the outline, and select a node.
-   * If no node is specified, the previous selected node is highlighted if any.
-   * If no node was selected, the root element is selected.
-   *
-   * @param aNode [optional] - The node to be selected.
-   * @param aScroll [optional] boolean
-   *        Should we scroll to ensure that the selected node is visible.
-   */
-  highlight: function Highlighter_highlight(aNode, aScroll)
-  {
-    if (this.hidden)
-      this.show();
-
-    let oldNode = this.node;
-
-    if (!aNode) {
-      if (!this.node)
-        this.node = this.win.document.documentElement;
-    } else {
-      this.node = aNode;
-    }
-
-    if (oldNode !== this.node) {
-      this.updateInfobar();
-    }
-
-    this.invalidateSize(!!aScroll);
-
-    if (oldNode !== this.node) {
-      this.emitEvent("nodeselected");
-    }
-  },
-
-  /**
-   * Notify that a pseudo-class lock was toggled on the highlighted element
-   *
-   * @param aPseudo - The pseudo-class to toggle, e.g. ":hover".
-   */
-  pseudoClassLockToggled: function Highlighter_pseudoClassLockToggled(aPseudo)
-  {
-    this.emitEvent("pseudoclasstoggled", [aPseudo]);
-    this.updateInfobar();
-    this.moveInfobar();
-  },
-
-  /**
-   * Update the highlighter size and position.
-   */
-  invalidateSize: function Highlighter_invalidateSize(aScroll)
-  {
-    let rect = null;
-
-    if (this.node && this.isNodeHighlightable(this.node)) {
-
-      if (aScroll &&
-          this.node.scrollIntoView) { // XUL elements don't have such method
-        this.node.scrollIntoView();
-      }
-      let clientRect = this.node.getBoundingClientRect();
-      rect = LayoutHelpers.getDirtyRect(this.node);
-    }
-
-    this.highlightRectangle(rect);
-
-    this.moveInfobar();
-
-    if (this._highlighting) {
-      this.showOutline();
-      this.emitEvent("highlighting");
-    }
-  },
-
-  /**
-   * Returns the selected node.
-   *
-   * @returns node
-   */
-  getNode: function() {
-    return this.node;
-  },
-
-  /**
-   * Show the highlighter if it has been hidden.
-   */
-  show: function() {
-    if (!this.hidden) return;
-    this.showOutline();
-    this.showInfobar();
-    this.computeZoomFactor();
-    this.attachPageListeners();
-    this.invalidateSize();
-    this.hidden = false;
-  },
-
-  /**
-   * Hide the highlighter, the outline and the infobar.
-   */
-  hide: function() {
-    if (this.hidden) return;
-    this.hideOutline();
-    this.hideInfobar();
-    this.detachPageListeners();
-    this.hidden = true;
-  },
-
-  /**
-   * Is the highlighter visible?
-   *
-   * @return boolean
-   */
-  isHidden: function() {
-    return this.hidden;
-  },
-
-  /**
-   * Lock a node. Stops the inspection.
-   */
-  lock: function() {
-    if (this.locked === true) return;
-    this.outline.setAttribute("locked", "true");
-    this.nodeInfo.container.setAttribute("locked", "true");
-    this.detachMouseListeners();
-    this.locked = true;
-    this.emitEvent("locked");
-  },
-
-  /**
-   * Start inspecting.
-   * Unlock the current node (if any), and select any node being hovered.
-   */
-  unlock: function() {
-    if (this.locked === false) return;
-    this.outline.removeAttribute("locked");
-    this.nodeInfo.container.removeAttribute("locked");
-    this.attachMouseListeners();
-    this.locked = false;
-    this.showOutline();
-    this.emitEvent("unlocked");
-  },
-
-  /**
-   * Is the specified node highlightable?
-   *
-   * @param nsIDOMNode aNode
-   *        the DOM element in question
-   * @returns boolean
-   *          True if the node is highlightable or false otherwise.
-   */
-  isNodeHighlightable: function Highlighter_isNodeHighlightable(aNode)
-  {
-    if (!LayoutHelpers.isNodeConnected(aNode)) {
-      return false;
-    }
-    if (aNode.nodeType != aNode.ELEMENT_NODE) {
-      return false;
-    }
-    let nodeName = aNode.nodeName.toLowerCase();
-    return !INSPECTOR_INVISIBLE_ELEMENTS[nodeName];
-  },
-
-  /**
-   * Hide the infobar
-   */
-   hideInfobar: function Highlighter_hideInfobar() {
-     this.nodeInfo.container.setAttribute("force-transitions", "true");
-     this.nodeInfo.container.setAttribute("hidden", "true");
-   },
-
-  /**
-   * Show the infobar
-   */
-   showInfobar: function Highlighter_showInfobar() {
-     this.nodeInfo.container.removeAttribute("hidden");
-     this.moveInfobar();
-     this.nodeInfo.container.removeAttribute("force-transitions");
-   },
-
-  /**
-   * Hide the outline
-   */
-   hideOutline: function Highlighter_hideOutline() {
-     this.outline.setAttribute("hidden", "true");
-   },
-
-  /**
-   * Show the outline
-   */
-   showOutline: function Highlighter_showOutline() {
-     if (this._highlighting)
-       this.outline.removeAttribute("hidden");
-   },
-
-  /**
-   * Build the node Infobar.
-   *
-   * <box id="highlighter-nodeinfobar-container">
-   *   <box id="Highlighter-nodeinfobar-arrow-top"/>
-   *   <hbox id="highlighter-nodeinfobar">
-   *     <toolbarbutton class="highlighter-nodeinfobar-button" id="highlighter-nodeinfobar-inspectbutton"/>
-   *     <hbox id="highlighter-nodeinfobar-text">
-   *       <xhtml:span id="highlighter-nodeinfobar-tagname"/>
-   *       <xhtml:span id="highlighter-nodeinfobar-id"/>
-   *       <xhtml:span id="highlighter-nodeinfobar-classes"/>
-   *       <xhtml:span id="highlighter-nodeinfobar-pseudo-classes"/>
-   *     </hbox>
-   *     <toolbarbutton class="highlighter-nodeinfobar-button" id="highlighter-nodeinfobar-menu"/>
-   *   </hbox>
-   *   <box id="Highlighter-nodeinfobar-arrow-bottom"/>
-   * </box>
-   *
-   * @param nsIDOMElement aParent
-   *        The container of the infobar.
-   */
-  buildInfobar: function Highlighter_buildInfobar(aParent)
-  {
-    let container = this.chromeDoc.createElement("box");
-    container.id = "highlighter-nodeinfobar-container";
-    container.setAttribute("position", "top");
-    container.setAttribute("disabled", "true");
-
-    let nodeInfobar = this.chromeDoc.createElement("hbox");
-    nodeInfobar.id = "highlighter-nodeinfobar";
-
-    nodeInfobar.addEventListener("mousedown", function(aEvent) {
-      this.emitEvent("nodeselected");
-    }.bind(this), true);
-
-    let arrowBoxTop = this.chromeDoc.createElement("box");
-    arrowBoxTop.className = "highlighter-nodeinfobar-arrow";
-    arrowBoxTop.id = "highlighter-nodeinfobar-arrow-top";
-
-    let arrowBoxBottom = this.chromeDoc.createElement("box");
-    arrowBoxBottom.className = "highlighter-nodeinfobar-arrow";
-    arrowBoxBottom.id = "highlighter-nodeinfobar-arrow-bottom";
-
-    let tagNameLabel = this.chromeDoc.createElementNS("http://www.w3.org/1999/xhtml", "span");
-    tagNameLabel.id = "highlighter-nodeinfobar-tagname";
-
-    let idLabel = this.chromeDoc.createElementNS("http://www.w3.org/1999/xhtml", "span");
-    idLabel.id = "highlighter-nodeinfobar-id";
-
-    let classesBox = this.chromeDoc.createElementNS("http://www.w3.org/1999/xhtml", "span");
-    classesBox.id = "highlighter-nodeinfobar-classes";
-
-    let pseudoClassesBox = this.chromeDoc.createElementNS("http://www.w3.org/1999/xhtml", "span");
-    pseudoClassesBox.id = "highlighter-nodeinfobar-pseudo-classes";
-
-    // Add some content to force a better boundingClientRect down below.
-    pseudoClassesBox.textContent = "&nbsp;";
-
-    // Create buttons
-
-    let inspect = this.chromeDoc.createElement("toolbarbutton");
-    inspect.id = "highlighter-nodeinfobar-inspectbutton";
-    inspect.className = "highlighter-nodeinfobar-button"
-    let toolbarInspectButton =
-      this.chromeDoc.getElementById("inspector-inspect-toolbutton");
-    inspect.setAttribute("tooltiptext",
-                         toolbarInspectButton.getAttribute("tooltiptext"));
-    inspect.setAttribute("command", "Inspector:Inspect");
-
-    let nodemenu = this.chromeDoc.createElement("toolbarbutton");
-    nodemenu.setAttribute("type", "menu");
-    nodemenu.id = "highlighter-nodeinfobar-menu";
-    nodemenu.className = "highlighter-nodeinfobar-button"
-    nodemenu.setAttribute("tooltiptext",
-                          this.strings.GetStringFromName("nodeMenu.tooltiptext"));
-
-    let menu = this.chromeDoc.getElementById("inspector-node-popup");
-    menu = menu.cloneNode(true);
-    menu.id = "highlighter-node-menu";
-
-    let separator = this.chromeDoc.createElement("menuseparator");
-    menu.appendChild(separator);
-
-    menu.addEventListener("popupshowing", function() {
-      let items = menu.getElementsByClassName("highlighter-pseudo-class-menuitem");
-      let i = items.length;
-      while (i--) {
-        menu.removeChild(items[i]);
-      }
-
-      let fragment = this.buildPseudoClassMenu();
-      menu.appendChild(fragment);
-    }.bind(this), true);
-
-    nodemenu.appendChild(menu);
-
-    // <hbox id="highlighter-nodeinfobar-text"/>
-    let texthbox = this.chromeDoc.createElement("hbox");
-    texthbox.id = "highlighter-nodeinfobar-text";
-    texthbox.setAttribute("align", "center");
-    texthbox.setAttribute("flex", "1");
-
-    texthbox.appendChild(tagNameLabel);
-    texthbox.appendChild(idLabel);
-    texthbox.appendChild(classesBox);
-    texthbox.appendChild(pseudoClassesBox);
-
-    nodeInfobar.appendChild(inspect);
-    nodeInfobar.appendChild(texthbox);
-    nodeInfobar.appendChild(nodemenu);
-
-    container.appendChild(arrowBoxTop);
-    container.appendChild(nodeInfobar);
-    container.appendChild(arrowBoxBottom);
-
-    aParent.appendChild(container);
-
-    let barHeight = container.getBoundingClientRect().height;
-
-    this.nodeInfo = {
-      tagNameLabel: tagNameLabel,
-      idLabel: idLabel,
-      classesBox: classesBox,
-      pseudoClassesBox: pseudoClassesBox,
-      container: container,
-      barHeight: barHeight,
-    };
-  },
-
-  /**
-   * Create the menuitems for toggling the selection's pseudo-class state
-   *
-   * @returns DocumentFragment. The menuitems for toggling pseudo-classes.
-   */
-  buildPseudoClassMenu: function IUI_buildPseudoClassesMenu()
-  {
-    let fragment = this.chromeDoc.createDocumentFragment();
-    for (let i = 0; i < PSEUDO_CLASSES.length; i++) {
-      let pseudo = PSEUDO_CLASSES[i];
-      let item = this.chromeDoc.createElement("menuitem");
-      item.id = "highlighter-pseudo-class-menuitem-" + pseudo;
-      item.setAttribute("type", "checkbox");
-      item.setAttribute("label", pseudo);
-      item.className = "highlighter-pseudo-class-menuitem";
-      item.setAttribute("checked", DOMUtils.hasPseudoClassLock(this.node,
-                        pseudo));
-      item.addEventListener("command",
-                            this.pseudoClassLockToggled.bind(this, pseudo), false);
-      fragment.appendChild(item);
-    }
-    return fragment;
-  },
-
-  /**
-   * Highlight a rectangular region.
-   *
-   * @param object aRect
-   *        The rectangle region to highlight.
-   * @returns boolean
-   *          True if the rectangle was highlighted, false otherwise.
-   */
-  highlightRectangle: function Highlighter_highlightRectangle(aRect)
-  {
-    if (!aRect) {
-      this.unhighlight();
-      return;
-    }
-
-    let oldRect = this._contentRect;
-
-    if (oldRect && aRect.top == oldRect.top && aRect.left == oldRect.left &&
-        aRect.width == oldRect.width && aRect.height == oldRect.height) {
-      return; // same rectangle
-    }
-
-    let aRectScaled = LayoutHelpers.getZoomedRect(this.win, aRect);
-
-    if (aRectScaled.left >= 0 && aRectScaled.top >= 0 &&
-        aRectScaled.width > 0 && aRectScaled.height > 0) {
-
-      this.showOutline();
-
-      // The bottom div and the right div are flexibles (flex=1).
-      // We don't need to resize them.
-      let top = "top:" + aRectScaled.top + "px;";
-      let left = "left:" + aRectScaled.left + "px;";
-      let width = "width:" + aRectScaled.width + "px;";
-      let height = "height:" + aRectScaled.height + "px;";
-      this.outline.setAttribute("style", top + left + width + height);
-
-      this._highlighting = true;
-    } else {
-      this.unhighlight();
-    }
-
-    this._contentRect = aRect; // save orig (non-scaled) rect
-    this._highlightRect = aRectScaled; // and save the scaled rect.
-
-    return;
-  },
-
-  /**
-   * Clear the highlighter surface.
-   */
-  unhighlight: function Highlighter_unhighlight()
-  {
-    this._highlighting = false;
-    this.hideOutline();
-  },
-
-  /**
-   * Update node information (tagName#id.class)
-   */
-  updateInfobar: function Highlighter_updateInfobar()
-  {
-    // Tag name
-    this.nodeInfo.tagNameLabel.textContent = this.node.tagName;
-
-    // ID
-    this.nodeInfo.idLabel.textContent = this.node.id ? "#" + this.node.id : "";
-
-    // Classes
-    let classes = this.nodeInfo.classesBox;
-
-    classes.textContent = this.node.classList.length ?
-                            "." + Array.join(this.node.classList, ".") : "";
-
-    // Pseudo-classes
-    let pseudos = PSEUDO_CLASSES.filter(function(pseudo) {
-      return DOMUtils.hasPseudoClassLock(this.node, pseudo);
-    }, this);
-
-    let pseudoBox = this.nodeInfo.pseudoClassesBox;
-    pseudoBox.textContent = pseudos.join("");
-  },
-
-  /**
-   * Move the Infobar to the right place in the highlighter.
-   */
-  moveInfobar: function Highlighter_moveInfobar()
-  {
-    if (this._highlightRect) {
-      let winHeight = this.win.innerHeight * this.zoom;
-      let winWidth = this.win.innerWidth * this.zoom;
-
-      let rect = {top: this._highlightRect.top,
-                  left: this._highlightRect.left,
-                  width: this._highlightRect.width,
-                  height: this._highlightRect.height};
-
-      rect.top = Math.max(rect.top, 0);
-      rect.left = Math.max(rect.left, 0);
-      rect.width = Math.max(rect.width, 0);
-      rect.height = Math.max(rect.height, 0);
-
-      rect.top = Math.min(rect.top, winHeight);
-      rect.left = Math.min(rect.left, winWidth);
-
-      this.nodeInfo.container.removeAttribute("disabled");
-      // Can the bar be above the node?
-      if (rect.top < this.nodeInfo.barHeight) {
-        // No. Can we move the toolbar under the node?
-        if (rect.top + rect.height +
-            this.nodeInfo.barHeight > winHeight) {
-          // No. Let's move it inside.
-          this.nodeInfo.container.style.top = rect.top + "px";
-          this.nodeInfo.container.setAttribute("position", "overlap");
-        } else {
-          // Yes. Let's move it under the node.
-          this.nodeInfo.container.style.top = rect.top + rect.height + "px";
-          this.nodeInfo.container.setAttribute("position", "bottom");
-        }
-      } else {
-        // Yes. Let's move it on top of the node.
-        this.nodeInfo.container.style.top =
-          rect.top - this.nodeInfo.barHeight + "px";
-        this.nodeInfo.container.setAttribute("position", "top");
-      }
-
-      let barWidth = this.nodeInfo.container.getBoundingClientRect().width;
-      let left = rect.left + rect.width / 2 - barWidth / 2;
-
-      // Make sure the whole infobar is visible
-      if (left < 0) {
-        left = 0;
-        this.nodeInfo.container.setAttribute("hide-arrow", "true");
-      } else {
-        if (left + barWidth > winWidth) {
-          left = winWidth - barWidth;
-          this.nodeInfo.container.setAttribute("hide-arrow", "true");
-        } else {
-          this.nodeInfo.container.removeAttribute("hide-arrow");
-        }
-      }
-      this.nodeInfo.container.style.left = left + "px";
-    } else {
-      this.nodeInfo.container.style.left = "0";
-      this.nodeInfo.container.style.top = "0";
-      this.nodeInfo.container.setAttribute("position", "top");
-      this.nodeInfo.container.setAttribute("hide-arrow", "true");
-    }
-  },
-
-  /**
-   * Store page zoom factor.
-   */
-  computeZoomFactor: function Highlighter_computeZoomFactor() {
-    this.zoom =
-      this.win.QueryInterface(Ci.nsIInterfaceRequestor)
-      .getInterface(Ci.nsIDOMWindowUtils)
-      .fullZoom;
-  },
-
-  /////////////////////////////////////////////////////////////////////////
-  //// Event Emitter Mechanism
-
-  addListener: function Highlighter_addListener(aEvent, aListener)
-  {
-    if (!(aEvent in this.events))
-      this.events[aEvent] = [];
-    this.events[aEvent].push(aListener);
-  },
-
-  removeListener: function Highlighter_removeListener(aEvent, aListener)
-  {
-    if (!(aEvent in this.events))
-      return;
-    let idx = this.events[aEvent].indexOf(aListener);
-    if (idx > -1)
-      this.events[aEvent].splice(idx, 1);
-  },
-
-  emitEvent: function Highlighter_emitEvent(aEvent, aArgv)
-  {
-    if (!(aEvent in this.events))
-      return;
-
-    let listeners = this.events[aEvent];
-    let highlighter = this;
-    listeners.forEach(function(aListener) {
-      try {
-        aListener.apply(highlighter, aArgv);
-      } catch(e) {}
-    });
-  },
-
-  removeAllListeners: function Highlighter_removeAllIsteners()
-  {
-    for (let event in this.events) {
-      delete this.events[event];
-    }
-  },
-
-  /////////////////////////////////////////////////////////////////////////
-  //// Event Handling
-
-  attachMouseListeners: function Highlighter_attachMouseListeners()
-  {
-    this.browser.addEventListener("mousemove", this, true);
-    this.browser.addEventListener("click", this, true);
-    this.browser.addEventListener("dblclick", this, true);
-    this.browser.addEventListener("mousedown", this, true);
-    this.browser.addEventListener("mouseup", this, true);
-  },
-
-  detachMouseListeners: function Highlighter_detachMouseListeners()
-  {
-    this.browser.removeEventListener("mousemove", this, true);
-    this.browser.removeEventListener("click", this, true);
-    this.browser.removeEventListener("dblclick", this, true);
-    this.browser.removeEventListener("mousedown", this, true);
-    this.browser.removeEventListener("mouseup", this, true);
-  },
-
-  attachPageListeners: function Highlighter_attachPageListeners()
-  {
-    this.browser.addEventListener("resize", this, true);
-    this.browser.addEventListener("scroll", this, true);
-    this.browser.addEventListener("MozAfterPaint", this, true);
-  },
-
-  detachPageListeners: function Highlighter_detachPageListeners()
-  {
-    this.browser.removeEventListener("resize", this, true);
-    this.browser.removeEventListener("scroll", this, true);
-    this.browser.removeEventListener("MozAfterPaint", this, true);
-  },
-
-  /**
-   * Generic event handler.
-   *
-   * @param nsIDOMEvent aEvent
-   *        The DOM event object.
-   */
-  handleEvent: function Highlighter_handleEvent(aEvent)
-  {
-    switch (aEvent.type) {
-      case "click":
-        this.handleClick(aEvent);
-        break;
-      case "mousemove":
-        this.brieflyIgnorePageEvents();
-        this.handleMouseMove(aEvent);
-        break;
-      case "resize":
-        this.computeZoomFactor();
-        break;
-      case "MozAfterPaint":
-      case "scroll":
-        this.brieflyDisableTransitions();
-        this.invalidateSize();
-        break;
-      case "dblclick":
-      case "mousedown":
-      case "mouseup":
-        aEvent.stopPropagation();
-        aEvent.preventDefault();
-        break;
-    }
-  },
-
-  /**
-   * Disable the CSS transitions for a short time to avoid laggy animations
-   * during scrolling or resizing.
-   */
-  brieflyDisableTransitions: function Highlighter_brieflyDisableTransitions()
-  {
-    if (this.transitionDisabler) {
-      this.chromeWin.clearTimeout(this.transitionDisabler);
-    } else {
-      this.outline.setAttribute("disable-transitions", "true");
-      this.nodeInfo.container.setAttribute("disable-transitions", "true");
-    }
-    this.transitionDisabler =
-      this.chromeWin.setTimeout(function() {
-        this.outline.removeAttribute("disable-transitions");
-        this.nodeInfo.container.removeAttribute("disable-transitions");
-        this.transitionDisabler = null;
-      }.bind(this), 500);
-  },
-
-  /**
-   * Don't listen to page events while inspecting with the mouse.
-   */
-  brieflyIgnorePageEvents: function Highlighter_brieflyIgnorePageEvents()
-  {
-    // The goal is to keep smooth animations while inspecting.
-    // CSS Transitions might be interrupted because of a MozAfterPaint
-    // event that would triger an invalidateSize() call.
-    // So we don't listen to events that would trigger an invalidateSize()
-    // call.
-    //
-    // Side effect, zoom levels are not updated during this short period.
-    // It's very unlikely this would happen, but just in case, we call
-    // computeZoomFactor() when reattaching the events.
-    if (this.pageEventsMuter) {
-      this.chromeWin.clearTimeout(this.pageEventsMuter);
-    } else {
-      this.detachPageListeners();
-    }
-    this.pageEventsMuter =
-      this.chromeWin.setTimeout(function() {
-        this.attachPageListeners();
-        // Just in case the zoom level changed while ignoring the paint events
-        this.computeZoomFactor();
-        this.pageEventsMuter = null;
-      }.bind(this), 500);
-  },
-
-  /**
-   * Handle clicks.
-   *
-   * @param nsIDOMEvent aEvent
-   *        The DOM event.
-   */
-  handleClick: function Highlighter_handleClick(aEvent)
-  {
-    // Stop inspection when the user clicks on a node.
-    if (aEvent.button == 0) {
-      let win = aEvent.target.ownerDocument.defaultView;
-      this.lock();
-      win.focus();
-      aEvent.preventDefault();
-      aEvent.stopPropagation();
-    }
-  },
-
-  /**
-   * Handle mousemoves in panel.
-   *
-   * @param nsiDOMEvent aEvent
-   *        The MouseEvent triggering the method.
-   */
-  handleMouseMove: function Highlighter_handleMouseMove(aEvent)
-  {
-    let doc = aEvent.target.ownerDocument;
-
-    // This should never happen, but just in case, we don't let the
-    // highlighter highlight browser nodes.
-    if (doc && doc != this.chromeDoc) {
-      let element = LayoutHelpers.getElementFromPoint(aEvent.target.ownerDocument,
-        aEvent.clientX, aEvent.clientY);
-      if (element && element != this.node) {
-        this.highlight(element);
-      }
-    }
-  },
-};
-
-///////////////////////////////////////////////////////////////////////////
-
-XPCOMUtils.defineLazyGetter(this, "DOMUtils", function () {
-  return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils)
-});
-
-XPCOMUtils.defineLazyGetter(Highlighter.prototype, "strings", function () {
-    return Services.strings.createBundle(
-            "chrome://browser/locale/devtools/inspector.properties");
-});
deleted file mode 100644
--- a/browser/devtools/highlighter/inspector.jsm
+++ /dev/null
@@ -1,2414 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const Cc = Components.classes;
-const Cu = Components.utils;
-const Ci = Components.interfaces;
-const Cr = Components.results;
-
-this.EXPORTED_SYMBOLS = ["InspectorUI"];
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource:///modules/devtools/MarkupView.jsm");
-Cu.import("resource:///modules/highlighter.jsm");
-Cu.import("resource:///modules/devtools/LayoutView.jsm");
-Cu.import("resource:///modules/devtools/LayoutHelpers.jsm");
-Cu.import("resource:///modules/devtools/EventEmitter.jsm");
-Cu.import("resource:///modules/devtools/DOMHelpers.jsm");
-
-// Inspector notifications dispatched through the nsIObserverService.
-const INSPECTOR_NOTIFICATIONS = {
-  // Fires once the Inspector completes the initialization and opens up on
-  // screen.
-  OPENED: "inspector-opened",
-
-  // Fires once the Inspector is closed.
-  CLOSED: "inspector-closed",
-
-  // Fires once the Inspector is destroyed. Not fired on tab switch.
-  DESTROYED: "inspector-destroyed",
-
-  // Fires when the Inspector is reopened after tab-switch.
-  STATE_RESTORED: "inspector-state-restored",
-
-  // Fires when the Tree Panel is opened and initialized.
-  TREEPANELREADY: "inspector-treepanel-ready",
-
-  // Event notifications for the attribute-value editor
-  EDITOR_OPENED: "inspector-editor-opened",
-  EDITOR_CLOSED: "inspector-editor-closed",
-  EDITOR_SAVED: "inspector-editor-saved",
-};
-
-const PSEUDO_CLASSES = [":hover", ":active", ":focus"];
-
-// Timer, in milliseconds, between change events fired by
-// things like resize events.
-const LAYOUT_CHANGE_TIMER = 250;
-
-/**
- * Represents an open instance of the Inspector for a tab.
- * This is the object handed out to sidebars and other API consumers.
- *
- * Right now it's a thin layer over InspectorUI, but we will
- * start moving per-tab state into this object soon, eventually
- * replacing the per-winID InspectorStore objects.
- *
- * The lifetime of this object is also not yet correct.  This object
- * is currently destroyed when the inspector is torn down, either by user
- * closing the inspector or by user switching the tab.  This should
- * only be destroyed when user closes the inspector.
- */
-function Inspector(aIUI)
-{
-  this._IUI = aIUI;
-  this._winID = aIUI.winID;
-  this._browser = aIUI.browser;
-  this._eventEmitter = new EventEmitter();
-
-  this._browser.addEventListener("resize", this, true);
-
-  this._markupButton = this._IUI.chromeDoc.getElementById("inspector-treepanel-toolbutton");
-
-  if (Services.prefs.getBoolPref("devtools.inspector.htmlPanelOpen")) {
-    this.openMarkup();
-  } else {
-    this.closeMarkup();
-  }
-
-}
-
-Inspector.prototype = {
-  /**
-   * True if the highlighter is locked on a node.
-   */
-  get locked() {
-    return !this._IUI.inspecting;
-  },
-
-  /**
-   * The currently selected node in the highlighter.
-   */
-  get selection() {
-    return this._IUI.selection;
-  },
-
-  /**
-   * Indicate that a tool has modified the state of the page.  Used to
-   * decide whether to show the "are you sure you want to navigate"
-   * notification.
-   */
-  markDirty: function Inspector_markDirty()
-  {
-    this._IUI.isDirty = true;
-  },
-
-  /**
-   * The chrome window the inspector lives in.
-   */
-  get chromeWindow() {
-    return this._IUI.chromeWin;
-  },
-
-  /**
-   * Notify the inspector that the current selection has changed.
-   *
-   * @param string aContext
-   *        An string that will be passed to the change event.  Allows
-   *        a tool to recognize when it sent a change notification itself
-   *        to avoid unnecessary refresh.
-   */
-  change: function Inspector_change(aContext)
-  {
-    this._cancelLayoutChange();
-    this._IUI.nodeChanged(aContext);
-  },
-
-  /**
-   * Returns true if a given sidebar panel is currently visible.
-   * @param string aPanelName
-   *        The panel name as registered with registerSidebar
-   */
-  isPanelVisible: function Inspector_isPanelVisible(aPanelName)
-  {
-    return this._IUI.sidebar.visible &&
-           this._IUI.sidebar.activePanel === aPanelName;
-  },
-
-  /**
-   * Called by the InspectorUI when the inspector is being destroyed.
-   */
-  _destroy: function Inspector__destroy()
-  {
-    this._cancelLayoutChange();
-    this._destroyMarkup();
-    this._browser.removeEventListener("resize", this, true);
-    delete this._IUI;
-    delete this._eventEmitter;
-  },
-
-  /**
-   * Event handler for DOM events.
-   *
-   * @param DOMEvent aEvent
-   */
-  handleEvent: function Inspector_handleEvent(aEvent)
-  {
-    switch(aEvent.type) {
-      case "resize":
-        this._scheduleLayoutChange();
-    }
-  },
-
-  /**
-   * Schedule a low-priority change event for things like paint
-   * and resize.
-   */
-  _scheduleLayoutChange: function Inspector_scheduleLayoutChange()
-  {
-    if (this._timer) {
-      return null;
-    }
-    this._timer = this._IUI.win.setTimeout(function() {
-      this.change("layout");
-    }.bind(this), LAYOUT_CHANGE_TIMER);
-  },
-
-  /**
-   * Cancel a pending low-priority change event if any is
-   * scheduled.
-   */
-  _cancelLayoutChange: function Inspector_cancelLayoutChange()
-  {
-    if (this._timer) {
-      this._IUI.win.clearTimeout(this._timer);
-      delete this._timer;
-    }
-  },
-
-  toggleMarkup: function Inspector_toggleMarkup()
-  {
-    if (this._markupFrame) {
-      this.closeMarkup();
-      Services.prefs.setBoolPref("devtools.inspector.htmlPanelOpen", false);
-    } else {
-      this.openMarkup(true);
-      Services.prefs.setBoolPref("devtools.inspector.htmlPanelOpen", true);
-    }
-  },
-
-  /**
-   * XXX: The sidebar has an object that exists and is manipulated
-   * separately from its actual loading.  So the public api for
-   * the sidebar looks like:
-   *
-   * if (inspector.sidebar.visible) { inspector.sidebar.close() }
-   *
-   * whereas the markup API looks more like
-   *
-   * if (inspector.markupOpen) { inspector.closeMarkup() }
-   *
-   * Maybe we should add an InspectorMarkup object that presents
-   * the public api for the markup panel?
-   */
-  get markupOpen() {
-    return this._markupOpen;
-  },
-
-  openMarkup: function Inspector_openMarkup(aFocus)
-  {
-    this._markupButton.setAttribute("checked", "true");
-    this._markupOpen = true;
-    if (!this._markupFrame) {
-      this._initMarkup(aFocus);
-    }
-  },
-
-  closeMarkup: function Inspector_closeMarkup()
-  {
-    this._markupButton.removeAttribute("checked");
-    this._markupOpen = false;
-    this._destroyMarkup();
-  },
-
-  _initMarkup: function Inspector_initMarkupPane(aFocus)
-  {
-    let doc = this._IUI.chromeDoc;
-
-    this._markupBox = doc.createElement("vbox");
-    try {
-      this._markupBox.height =
-        Services.prefs.getIntPref("devtools.inspector.htmlHeight");
-    } catch(e) {
-      this._markupBox.height = 112;
-    }
-    this._markupBox.minHeight = 64;
-
-    this._markupSplitter = doc.createElement("splitter");
-    this._markupSplitter.className = "devtools-horizontal-splitter";
-
-    let container = doc.getElementById("appcontent");
-    container.appendChild(this._markupSplitter);
-    container.appendChild(this._markupBox);
-
-    // create tool iframe
-    this._markupFrame = doc.createElement("iframe");
-    this._markupFrame.setAttribute("flex", "1");
-    this._markupFrame.setAttribute("tooltip", "aHTMLTooltip");
-    this._markupFrame.setAttribute("context", "inspector-node-popup");
-
-    // This is needed to enable tooltips inside the iframe document.
-    this._boundMarkupFrameLoad = function Inspector_initMarkupPanel_onload() {
-      if (aFocus) {
-        this._markupFrame.contentWindow.focus();
-      }
-      this._onMarkupFrameLoad();
-    }.bind(this);
-    this._markupFrame.addEventListener("load", this._boundMarkupFrameLoad, true);
-
-    this._markupSplitter.setAttribute("hidden", true);
-    this._markupBox.setAttribute("hidden", true);
-    this._markupBox.appendChild(this._markupFrame);
-    this._markupFrame.setAttribute("src", "chrome://browser/content/devtools/markup-view.xhtml");
-  },
-
-  _onMarkupFrameLoad: function Inspector__onMarkupFrameLoad()
-  {
-    this._markupFrame.removeEventListener("load", this._boundMarkupFrameLoad, true);
-    delete this._boundMarkupFrameLoad;
-
-    this._markupSplitter.removeAttribute("hidden");
-    this._markupBox.removeAttribute("hidden");
-
-    this.markup = new MarkupView(this, this._markupFrame);
-    this.emit("markuploaded");
-  },
-
-  _destroyMarkup: function Inspector__destroyMarkup()
-  {
-    if (this._boundMarkupFrameLoad) {
-      this._markupFrame.removeEventListener("load", this._boundMarkupFrameLoad, true);
-      delete this._boundMarkupFrameLoad;
-    }
-
-    if (this.markup) {
-      this.markup.destroy();
-      delete this.markup;
-    }
-
-    if (this._markupFrame) {
-      delete this._markupFrame;
-    }
-
-    if (this._markupBox) {
-      Services.prefs.setIntPref("devtools.inspector.htmlHeight", this._markupBox.height);
-      this._markupBox.parentNode.removeChild(this._markupBox);
-      delete this._markupBox;
-    }
-
-    if (this._markupSplitter) {
-      this._markupSplitter.parentNode.removeChild(this._markupSplitter);
-      delete this._markupSplitter;
-    }
-  },
-
-  /**
-   * Called by InspectorUI after a tab switch, when the
-   * inspector is no longer the active tab.
-   */
-  _freeze: function Inspector__freeze()
-  {
-    if (this._markupBox) {
-      this._markupSplitter.setAttribute("hidden", true);
-      this._markupBox.setAttribute("hidden", true);
-    }
-    this._cancelLayoutChange();
-    this._browser.removeEventListener("resize", this, true);
-    this._frozen = true;
-  },
-
-  /**
-   * Called by InspectorUI after a tab switch when the
-   * inspector is back to being the active tab.
-   */
-  _thaw: function Inspector__thaw()
-  {
-    if (!this._frozen) {
-      return;
-    }
-
-    if (this._markupOpen && !this._boundMarkupFrameLoad) {
-      this._markupSplitter.removeAttribute("hidden");
-      this._markupBox.removeAttribute("hidden");
-    }
-    this._browser.addEventListener("resize", this, true);
-    delete this._frozen;
-  },
-
-  /// Forward the events related calls to the event emitter.
-
-  /**
-   * Connect a listener to this object.
-   *
-   * @param string aEvent
-   *        The event name to which we're connecting.
-   * @param function aListener
-   *        Called when the event is fired.
-   */
-  on: function Inspector_on(aEvent, aListener)
-  {
-    this._eventEmitter.on(aEvent, aListener);
-  },
-
-  /**
-   * Listen for the next time an event is fired.
-   *
-   * @param string aEvent
-   *        The event name to which we're connecting.
-   * @param function aListener
-   *        Called when the event is fired.  Will be called at most one time.
-   */
-  once: function Inspector_once(aEvent, aListener)
-  {
-    this._eventEmitter.once(aEvent, aListener);
-  },
-
-  /**
-   * Remove a previously-registered event listener.  Works for events
-   * registered with either on or once.
-   *
-   * @param string aEvent
-   *        The event name whose listener we're disconnecting.
-   * @param function aListener
-   *        The listener to remove.
-   */
-  off: function Inspector_removeListener(aEvent, aListener)
-  {
-    this._eventEmitter.off(aEvent, aListener);
-  },
-
-  /**
-   * Emit an event on the inspector.  All arguments to this method will
-   * be sent to listner functions.
-   */
-  emit: function Inspector_emit()
-  {
-    this._eventEmitter.emit.apply(this._eventEmitter, arguments);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////
-//// InspectorUI
-
-/**
- * Main controller class for the Inspector.
- *
- * @constructor
- * @param nsIDOMWindow aWindow
- *        The chrome window for which the Inspector instance is created.
- */
-this.InspectorUI = function InspectorUI(aWindow)
-{
-  // Let style inspector tools register themselves.
-  let tmp = {};
-  Cu.import("resource:///modules/devtools/StyleInspector.jsm", tmp);
-
-  this.chromeWin = aWindow;
-  this.chromeDoc = aWindow.document;
-  this.tabbrowser = aWindow.gBrowser;
-  this.tools = {};
-  this.toolEvents = {};
-  this.store = new InspectorStore();
-  this.INSPECTOR_NOTIFICATIONS = INSPECTOR_NOTIFICATIONS;
-  this.buildButtonsTooltip();
-}
-
-InspectorUI.prototype = {
-  browser: null,
-  tools: null,
-  toolEvents: null,
-  inspecting: false,
-  ruleViewEnabled: true,
-  isDirty: false,
-  store: null,
-
-  _currentInspector: null,
-  _sidebar: null,
-
-  /**
-   * The Inspector object for the current tab.
-   */
-  get currentInspector() this._currentInspector,
-
-  /**
-   * The InspectorStyleSidebar for the current tab.
-   */
-  get sidebar() this._sidebar,
-
-  /**
-   * Toggle the inspector interface elements on or off.
-   *
-   * @param aEvent
-   *        The event that requested the UI change. Toolbar button or menu.
-   */
-  toggleInspectorUI: function IUI_toggleInspectorUI(aEvent)
-  {
-    if (this.isInspectorOpen) {
-      this.closeInspectorUI();
-    } else {
-      this.openInspectorUI();
-    }
-  },
-
-  /**
-   * Add a tooltip to the Inspect and Markup buttons.
-   * The tooltips include the related keyboard shortcut.
-   */
-  buildButtonsTooltip: function IUI_buildButtonsTooltip()
-  {
-    let keysbundle = Services.strings.createBundle("chrome://global-platform/locale/platformKeys.properties");
-    let separator = keysbundle.GetStringFromName("MODIFIER_SEPARATOR");
-
-    let button, tooltip;
-
-    // Inspect Button - the shortcut string is built from the <key> element
-
-    let key = this.chromeDoc.getElementById("key_inspect");
-
-    if (key) {
-      let modifiersAttr = key.getAttribute("modifiers");
-
-      let combo = [];
-
-      if (modifiersAttr.match("accel"))
-#ifdef XP_MACOSX
-        combo.push(keysbundle.GetStringFromName("VK_META"));
-#else
-        combo.push(keysbundle.GetStringFromName("VK_CONTROL"));
-#endif
-      if (modifiersAttr.match("shift"))
-        combo.push(keysbundle.GetStringFromName("VK_SHIFT"));
-      if (modifiersAttr.match("alt"))
-        combo.push(keysbundle.GetStringFromName("VK_ALT"));
-      if (modifiersAttr.match("ctrl"))
-        combo.push(keysbundle.GetStringFromName("VK_CONTROL"));
-      if (modifiersAttr.match("meta"))
-        combo.push(keysbundle.GetStringFromName("VK_META"));
-
-      combo.push(key.getAttribute("key"));
-
-      tooltip = this.strings.formatStringFromName("inspectButtonWithShortcutKey.tooltip",
-        [combo.join(separator)], 1);
-    } else {
-      tooltip = this.strings.GetStringFromName("inspectButton.tooltip");
-    }
-
-    button = this.chromeDoc.getElementById("inspector-inspect-toolbutton");
-    button.setAttribute("tooltiptext", tooltip);
-
-    // Markup Button - the shortcut string is built from the accesskey attribute
-
-    button = this.chromeDoc.getElementById("inspector-treepanel-toolbutton");
-#ifdef XP_MACOSX
-    // On Mac, no accesskey
-    tooltip = this.strings.GetStringFromName("markupButton.tooltip");
-#else
-    let altString = keysbundle.GetStringFromName("VK_ALT");
-    let accesskey = button.getAttribute("accesskey");
-    let shortcut = altString + separator + accesskey;
-    tooltip = this.strings.formatStringFromName("markupButton.tooltipWithAccesskey",
-      [shortcut], 1);
-#endif
-    button.setAttribute("tooltiptext", tooltip);
-
-  },
-
-  /**
-   * Toggle the status of the inspector, starting or stopping it. Invoked
-   * from the toolbar's Inspect button.
-   */
-  toggleInspection: function IUI_toggleInspection()
-  {
-    if (!this.isInspectorOpen) {
-      this.openInspectorUI();
-      return;
-    }
-
-    if (this.inspecting) {
-      this.stopInspecting();
-    } else {
-      this.startInspecting();
-    }
-  },
-
-  /**
-   * Show or hide the sidebar. Called from the Styling button on the
-   * highlighter toolbar.
-   */
-  toggleSidebar: function IUI_toggleSidebar()
-  {
-    if (!this.sidebar.visible) {
-      this.sidebar.show();
-    } else {
-      this.sidebar.hide();
-    }
-  },
-
-  /**
-   * Toggle the TreePanel.
-   */
-  toggleHTMLPanel: function IUI_toggleHTMLPanel()
-  {
-    this.currentInspector.toggleMarkup();
-  },
-
-  /**
-   * Is the inspector UI open? Simply check if the toolbar is visible or not.
-   *
-   * @returns boolean
-   */
-  get isInspectorOpen()
-  {
-    return !!(this.toolbar && !this.toolbar.hidden && this.highlighter);
-  },
-
-  /**
-   * Return the default selection element for the inspected document.
-   */
-  get defaultSelection()
-  {
-    let doc = this.win.document;
-    return doc.documentElement ? doc.documentElement.lastElementChild : null;
-  },
-
-  /**
-   * Open inspector UI and HTML tree. Add listeners for document scrolling,
-   * resize, tabContainer.TabSelect and others. If a node is provided, then
-   * start inspecting it.
-   *
-   * @param [optional] aNode
-   *        The node to inspect.
-   */
-  openInspectorUI: function IUI_openInspectorUI(aNode)
-  {
-    // InspectorUI is already up and running. Lock a node if asked (via context).
-    if (this.isInspectorOpen) {
-      if (aNode) {
-        this.inspectNode(aNode);
-        this.stopInspecting();
-      }
-      return;
-    }
-
-    // Observer used to inspect the specified element from content after the
-    // inspector UI has been opened (via the content context menu).
-    function inspectObserver(aElement) {
-      Services.obs.removeObserver(boundInspectObserver,
-                                  INSPECTOR_NOTIFICATIONS.OPENED,
-                                  false);
-      this.inspectNode(aElement);
-      this.stopInspecting();
-    };
-
-    var boundInspectObserver = inspectObserver.bind(this, aNode);
-
-    if (aNode) {
-      // Add the observer to inspect the node after initialization finishes.
-      Services.obs.addObserver(boundInspectObserver,
-                               INSPECTOR_NOTIFICATIONS.OPENED,
-                               false);
-    }
-    // Start initialization.
-    this.browser = this.tabbrowser.selectedBrowser;
-    this.win = this.browser.contentWindow;
-    this.winID = this.getWindowID(this.win);
-    this.toolbar = this.chromeDoc.getElementById("inspector-toolbar");
-    this.inspectCommand = this.chromeDoc.getElementById("Inspector:Inspect");
-
-    // Update menus:
-    this.inspectorUICommand = this.chromeDoc.getElementById("Tools:Inspect");
-    this.inspectorUICommand.setAttribute("checked", "true");
-
-    this.chromeWin.Tilt.setup();
-
-    this.toolbar.hidden = false;
-
-    // initialize the HTML Breadcrumbs
-    this.breadcrumbs = new HTMLBreadcrumbs(this);
-
-    this.isDirty = false;
-
-    this.progressListener = new InspectorProgressListener(this);
-
-    this.chromeWin.addEventListener("keypress", this, false);
-
-    // initialize the highlighter
-    this.highlighter = new Highlighter(this.chromeWin);
-
-    this.initializeStore();
-
-    this._sidebar = new InspectorStyleSidebar({
-      document: this.chromeDoc,
-      inspector: this._currentInspector,
-    });
-
-    // Fade out the highlighter when needed
-    let deck = this.chromeDoc.getElementById("devtools-sidebar-deck");
-    deck.addEventListener("mouseenter", this, true);
-    deck.addEventListener("mouseleave", this, true);
-
-    // Create UI for any sidebars registered with
-    // InspectorUI.registerSidebar()
-    for each (let tool in InspectorUI._registeredSidebars) {
-      this._sidebar.addTool(tool);
-    }
-
-    this.setupNavigationKeys();
-    this.highlighterReady();
-
-    // Focus the first focusable element in the toolbar
-    this.chromeDoc.commandDispatcher.advanceFocusIntoSubtree(this.toolbar);
-
-    // If nothing is focused in the toolbar, it means that the focus manager
-    // is limited to some specific elements and has moved the focus somewhere else.
-    // So in this case, we want to focus the content window.
-    // See: https://developer.mozilla.org/en/XUL_Tutorial/Focus_and_Selection#Platform_Specific_Behaviors
-    if (!this.toolbar.querySelector(":-moz-focusring")) {
-      this.win.focus();
-    }
-
-  },
-
-  /**
-   * Initialize the InspectorStore.
-   */
-  initializeStore: function IUI_initializeStore()
-  {
-    // First time opened, add the TabSelect listener
-    if (this.store.isEmpty()) {
-      this.tabbrowser.tabContainer.addEventListener("TabSelect", this, false);
-    }
-
-    // Has this windowID been inspected before?
-    if (this.store.hasID(this.winID)) {
-      this._currentInspector = this.store.getInspector(this.winID);
-      this._currentInspector._thaw();
-      let selectedNode = this.currentInspector._selectedNode;
-      if (selectedNode) {
-        this.inspectNode(selectedNode);
-      }
-      this.isDirty = this.currentInspector._isDirty;
-    } else {
-      // First time inspecting, set state to no selection + live inspection.
-      let inspector = new Inspector(this);
-      this.store.addInspector(this.winID, inspector);
-      inspector._selectedNode = null;
-      inspector._inspecting = true;
-      inspector._isDirty = this.isDirty;
-
-      inspector._htmlPanelOpen =
-        Services.prefs.getBoolPref("devtools.inspector.htmlPanelOpen");
-
-      inspector._sidebarOpen =
-        Services.prefs.getBoolPref("devtools.inspector.sidebarOpen");
-
-      inspector._activeSidebar =
-        Services.prefs.getCharPref("devtools.inspector.activeSidebar");
-
-      this.win.addEventListener("pagehide", this, true);
-
-      this._currentInspector = inspector;
-    }
-  },
-
-  /**
-   * Browse nodes according to the breadcrumbs layout, only for some specific
-   * elements of the UI.
-   */
-   setupNavigationKeys: function IUI_setupNavigationKeys()
-   {
-     // UI elements that are arrow keys sensitive:
-     // - the Inspector toolbar.
-
-     this.onKeypress = this.onKeypress.bind(this);
-
-     this.toolbar.addEventListener("keypress", this.onKeypress, true);
-   },
-
-  /**
-   * Remove the event listeners for the arrowkeys.
-   */
-   removeNavigationKeys: function IUI_removeNavigationKeys()
-   {
-      this.toolbar.removeEventListener("keypress", this.onKeypress, true);
-   },
-
-  /**
-   * Close inspector UI and associated panels. Unhighlight and stop inspecting.
-   * Remove event listeners for document scrolling, resize,
-   * tabContainer.TabSelect and others.
-   *
-   * @param boolean aKeepInspector
-   *        Tells if you want the inspector associated to the current tab/window to
-   *        be cleared or not. Set this to true to save the inspector, or false
-   *        to destroy it.
-   */
-  closeInspectorUI: function IUI_closeInspectorUI(aKeepInspector)
-  {
-    if (this.closing || !this.win || !this.browser) {
-      return;
-    }
-
-    let winId = new String(this.winID); // retain this to notify observers.
-
-    this.closing = true;
-    this.toolbar.hidden = true;
-
-    this.removeNavigationKeys();
-
-    this.progressListener.destroy();
-    delete this.progressListener;
-
-    if (!aKeepInspector) {
-      this.win.removeEventListener("pagehide", this, true);
-      this.clearPseudoClassLocks();
-    } else {
-      // Update the inspector before closing.
-      if (this.selection) {
-        this.currentInspector._selectedNode = this.selection;
-      }
-      this.currentInspector._inspecting = this.inspecting;
-      this.currentInspector._isDirty = this.isDirty;
-    }
-
-    if (this.store.isEmpty()) {
-      this.tabbrowser.tabContainer.removeEventListener("TabSelect", this, false);
-    }
-
-    this.chromeWin.removeEventListener("keypress", this, false);
-
-    this.stopInspecting();
-
-    // close the sidebar
-    if (this._sidebar) {
-      this._sidebar.destroy();
-      this._sidebar = null;
-    }
-
-    let deck = this.chromeDoc.getElementById("devtools-sidebar-deck");
-    deck.removeEventListener("mouseenter", this, true);
-    deck.removeEventListener("mouseleave", this, true);
-
-    this.highlighter.destroy();
-    this.highlighter = null;
-
-    if (this.breadcrumbs) {
-      this.breadcrumbs.destroy();
-      this.breadcrumbs = null;
-    }
-
-    if (aKeepInspector) {
-      this._currentInspector._freeze();
-    } else {
-      this.store.deleteInspector(this.winID);
-    }
-    delete this._currentInspector;
-
-    this.inspectorUICommand.setAttribute("checked", "false");
-
-    this.browser = this.win = null; // null out references to browser and window
-    this.winID = null;
-    this.selection = null;
-    this.closing = false;
-    this.isDirty = false;
-
-    delete this.stylePanel;
-    delete this.inspectorUICommand;
-    delete this.inspectCommand;
-    delete this.toolbar;
-
-    Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.CLOSED, null);
-
-    if (!aKeepInspector)
-      Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.DESTROYED, winId);
-  },
-
-  /**
-   * Begin inspecting webpage, attach page event listeners, activate
-   * highlighter event listeners.
-   */
-  startInspecting: function IUI_startInspecting()
-  {
-    this.inspectCommand.setAttribute("checked", "true");
-
-    this.inspecting = true;
-    this.highlighter.unlock();
-    this._notifySelected();
-    this._currentInspector.emit("unlocked");
-  },
-
-  _notifySelected: function IUI__notifySelected(aFrom)
-  {
-    this._currentInspector._cancelLayoutChange();
-    this._currentInspector.emit("select", aFrom);
-  },
-
-  /**
-   * Stop inspecting webpage, detach page listeners, disable highlighter
-   * event listeners.
-   * @param aPreventScroll
-   *        Prevent scroll in the HTML tree?
-   */
-  stopInspecting: function IUI_stopInspecting(aPreventScroll)
-  {
-    if (!this.inspecting) {
-      return;
-    }
-
-    this.inspectCommand.setAttribute("checked", "false");
-
-    this.inspecting = false;
-
-    if (this.closing)
-      return;
-
-    if (this.highlighter.getNode()) {
-      this.select(this.highlighter.getNode(), true, !aPreventScroll);
-    } else {
-      this.select(null, true, true);
-    }
-
-    this.highlighter.lock();
-    this._notifySelected();
-    this._currentInspector.emit("locked");
-  },
-
-  /**
-   * Select an object in the inspector.
-   * @param aNode
-   *        node to inspect
-   * @param forceUpdate
-   *        force an update?
-   * @param aScroll boolean
-   *        scroll the tree panel?
-   * @param aFrom [optional] string
-   *        which part of the UI the selection occured from
-   */
-  select: function IUI_select(aNode, forceUpdate, aScroll, aFrom)
-  {
-    if (!aNode)
-      aNode = this.defaultSelection;
-
-    if (forceUpdate || aNode != this.selection) {
-      if (aFrom != "breadcrumbs") {
-        this.clearPseudoClassLocks();
-      }
-
-      this.selection = aNode;
-      if (!this.inspecting) {
-        this.highlighter.highlight(this.selection);
-      }
-    }
-
-    this.breadcrumbs.update();
-    this.chromeWin.Tilt.update(aNode);
-
-    this._notifySelected(aFrom);
-  },
-
-  /**
-   * Toggle the pseudo-class lock on the currently inspected element. If the
-   * pseudo-class is :hover or :active, that pseudo-class will also be toggled
-   * on every ancestor of the element, mirroring real :hover and :active
-   * behavior.
-   * 
-   * @param aPseudo the pseudo-class lock to toggle, e.g. ":hover"
-   */
-  togglePseudoClassLock: function IUI_togglePseudoClassLock(aPseudo)
-  {
-    if (DOMUtils.hasPseudoClassLock(this.selection, aPseudo)) {
-      this.breadcrumbs.nodeHierarchy.forEach(function(crumb) {
-        DOMUtils.removePseudoClassLock(crumb.node, aPseudo);
-      });
-    } else {
-      let hierarchical = aPseudo == ":hover" || aPseudo == ":active";
-      let node = this.selection;
-      do {
-        DOMUtils.addPseudoClassLock(node, aPseudo);
-        node = node.parentNode;
-      } while (hierarchical && node.parentNode)
-    }
-    this.nodeChanged("pseudoclass");
-  },
-
-  /**
-   * Clear all pseudo-class locks applied to elements in the node hierarchy
-   */
-  clearPseudoClassLocks: function IUI_clearPseudoClassLocks()
-  {
-    this.breadcrumbs.nodeHierarchy.forEach(function(crumb) {
-      if (LayoutHelpers.isNodeConnected(crumb.node)) {
-        DOMUtils.clearPseudoClassLocks(crumb.node);
-      }
-    });
-  },
-
-  /**
-   * Called when the highlighted node is changed by a tool.
-   *
-   * @param object aUpdater
-   *        The tool that triggered the update (if any), that tool's
-   *        onChanged will not be called.
-   */
-  nodeChanged: function IUI_nodeChanged(aUpdater)
-  {
-    this.highlighter.updateInfobar();
-    this.highlighter.invalidateSize();
-    this.breadcrumbs.updateSelectors();
-    this._currentInspector.emit("change", aUpdater);
-  },
-
-  /////////////////////////////////////////////////////////////////////////
-  //// Event Handling
-
-  highlighterReady: function IUI_highlighterReady()
-  {
-    let self = this;
-
-    this.highlighter.addListener("locked", function() {
-      self.stopInspecting();
-    });
-
-    this.highlighter.addListener("unlocked", function() {
-      self.startInspecting();
-    });
-
-    this.highlighter.addListener("nodeselected", function() {
-      self.select(self.highlighter.getNode(), false, false);
-    });
-
-    this.highlighter.addListener("pseudoclasstoggled", function(aPseudo) {
-      self.togglePseudoClassLock(aPseudo);
-    });
-
-    if (this.currentInspector._inspecting) {
-      this.startInspecting();
-      this.highlighter.unlock();
-    } else {
-      this.highlighter.lock();
-    }
-
-    Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.STATE_RESTORED, null);
-
-    this.highlighter.highlight();
-
-    if (this.currentInspector._sidebarOpen) {
-      this._sidebar.show();
-    }
-
-    Services.obs.notifyObservers({wrappedJSObject: this},
-                                 INSPECTOR_NOTIFICATIONS.OPENED, null);
-  },
-
-  /**
-   * Main callback handler for events.
-   *
-   * @param event
-   *        The event to be handled.
-   */
-  handleEvent: function IUI_handleEvent(event)
-  {
-    let winID = null;
-    let win = null;
-    let inspectorClosed = false;
-
-    switch (event.type) {
-      case "TabSelect":
-        winID = this.getWindowID(this.tabbrowser.selectedBrowser.contentWindow);
-        if (this.isInspectorOpen && winID != this.winID) {
-          this.closeInspectorUI(true);
-          inspectorClosed = true;
-        }
-
-        if (winID && this.store.hasID(winID)) {
-          if (inspectorClosed && this.closing) {
-            Services.obs.addObserver(function reopenInspectorForTab() {
-              Services.obs.removeObserver(reopenInspectorForTab,
-                INSPECTOR_NOTIFICATIONS.CLOSED, false);
-
-              this.openInspectorUI();
-            }.bind(this), INSPECTOR_NOTIFICATIONS.CLOSED, false);
-          } else {
-            this.openInspectorUI();
-          }
-        }
-
-        if (this.store.isEmpty()) {
-          this.tabbrowser.tabContainer.removeEventListener("TabSelect", this,
-                                                         false);
-        }
-        break;
-      case "keypress":
-        switch (event.keyCode) {
-          case this.chromeWin.KeyEvent.DOM_VK_ESCAPE:
-            this.closeInspectorUI(false);
-            event.preventDefault();
-            event.stopPropagation();
-            break;
-      }
-      case "pagehide":
-        win = event.originalTarget.defaultView;
-        // Skip iframes/frames.
-        if (!win || win.frameElement || win.top != win) {
-          break;
-        }
-
-        win.removeEventListener(event.type, this, true);
-
-        winID = this.getWindowID(win);
-        if (winID && winID != this.winID) {
-          this.store.deleteInspector(winID);
-        }
-
-        if (this.store.isEmpty()) {
-          this.tabbrowser.tabContainer.removeEventListener("TabSelect", this,
-                                                         false);
-        }
-        break;
-      case "mouseleave":
-        this.highlighter.show();
-        break;
-      case "mouseenter":
-        this.highlighter.hide();
-        break;
-    }
-  },
-
-  /*
-   * handles "keypress" events.
-  */
-  onKeypress: function IUI_onKeypress(event)
-  {
-    let node = null;
-    let bc = this.breadcrumbs;
-    switch (event.keyCode) {
-      case this.chromeWin.KeyEvent.DOM_VK_LEFT:
-        if (bc.currentIndex != 0)
-          node = bc.nodeHierarchy[bc.currentIndex - 1].node;
-        if (node && this.highlighter.isNodeHighlightable(node))
-          this.highlighter.highlight(node);
-        event.preventDefault();
-        event.stopPropagation();
-        break;
-      case this.chromeWin.KeyEvent.DOM_VK_RIGHT:
-        if (bc.currentIndex < bc.nodeHierarchy.length - 1)
-          node = bc.nodeHierarchy[bc.currentIndex + 1].node;
-        if (node && this.highlighter.isNodeHighlightable(node)) {
-          this.highlighter.highlight(node);
-        }
-        event.preventDefault();
-        event.stopPropagation();
-        break;
-      case this.chromeWin.KeyEvent.DOM_VK_UP:
-        if (this.selection) {
-          // Find a previous sibling that is highlightable.
-          node = this.selection.previousSibling;
-          while (node && !this.highlighter.isNodeHighlightable(node)) {
-            node = node.previousSibling;
-          }
-        }
-        if (node && this.highlighter.isNodeHighlightable(node)) {
-          this.highlighter.highlight(node, true);
-        }
-        event.preventDefault();
-        event.stopPropagation();
-        break;
-      case this.chromeWin.KeyEvent.DOM_VK_DOWN:
-        if (this.selection) {
-          // Find a next sibling that is highlightable.
-          node = this.selection.nextSibling;
-          while (node && !this.highlighter.isNodeHighlightable(node)) {
-            node = node.nextSibling;
-          }
-        }
-        if (node && this.highlighter.isNodeHighlightable(node)) {
-          this.highlighter.highlight(node, true);
-        }
-        event.preventDefault();
-        event.stopPropagation();
-        break;
-    }
-  },
-
-  /**
-   * Return the currently-selected node for the purposes of the
-   * context menu.  This is usually the highlighter selection, unless
-   * the markup panel has a selected node that can't be highlighted
-   * (such as a text node).  This will be fixed once the highlighter/inspector
-   * is confortable with non-element nodes being the current selection.
-   * See bug 785180.
-   */
-  _contextSelection: function IUI__contextSelection()
-  {
-    let inspector = this.currentInspector;
-    if (inspector.markup) {
-      return inspector.markup.selected;
-    }
-    return this.selection;
-  },
-
-  /**
-   * Copy the innerHTML of the selected Node to the clipboard. Called via the
-   * Inspector:CopyInner command.