[Pkg-mozext-commits] [firebug] 01/16: Sync FBTrace and Firebug code base

David Prévot taffit at moszumanska.debian.org
Mon Mar 31 22:45:30 UTC 2014


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to tag fbtest-1.11.1
in repository firebug.

commit df0c88febfa89367d82ba4bbc13ce31774f9548f
Author: Jan Odvarko <odvarko at gmail.com>
Date:   Tue Dec 4 09:54:22 2012 +0100

    Sync FBTrace and Firebug code base
---
 .../chrome/firebug/content/accessible/a11y.js      |   31 +-
 .../chrome/firebug/content/branch.properties       |    2 +-
 .../firebug/content/bti/inProcess/browser.js       |   89 +-
 .../content/bti/inProcess/compilationunit.js       |    9 +-
 .../content/bti/inProcess/javascripttool.js        |   21 +-
 .../chrome/firebug/content/chrome/activation.js    |   91 +-
 .../chrome/firebug/content/chrome/annotations.js   |   15 +-
 .../chrome/firebug/content/chrome/chrome.js        |  231 ++--
 .../FBTrace/chrome/firebug/content/chrome/menu.js  |   63 +-
 .../firebug/content/chrome/panelActivation.js      |   15 +-
 .../FBTrace/chrome/firebug/content/chrome/reps.js  |  629 ++++++----
 .../chrome/firebug/content/chrome/tabContext.js    |    4 +-
 .../chrome/firebug/content/chrome/tabWatcher.js    |   11 +-
 .../chrome/firebug/content/chrome/tableRep.js      |   13 +-
 .../chrome/firebug/content/chrome/window.js        |   10 +-
 .../firebug/content/console/autoCompleter.js       |  525 +++++---
 .../firebug/content/console/commandEditor.js       |    9 +-
 .../firebug/content/console/commandHistory.js      |   47 +-
 .../chrome/firebug/content/console/commandLine.js  |  269 ++---
 .../firebug/content/console/commandLineExposed.js  |  112 +-
 .../firebug/content/console/commandLineHelp.js     |   61 +-
 .../firebug/content/console/commandLineInclude.js  |  542 +++++++++
 .../firebug/content/console/commandLinePopup.js    |    2 +-
 .../chrome/firebug/content/console/console.js      |   27 +-
 .../chrome/firebug/content/console/consolePanel.js |   51 +-
 .../chrome/firebug/content/console/errors.js       |   18 +-
 .../chrome/firebug/content/console/eventMonitor.js |   83 +-
 .../firebug/content/console/functionMonitor.js     |  191 +++
 .../firebug/content/console/performanceTiming.js   |  630 ++++++++++
 .../chrome/firebug/content/console/profiler.js     |   30 +-
 .../chrome/firebug/content/cookies/cookie.js       |   13 +-
 .../firebug/content/cookies/cookieClipboard.js     |    9 +
 .../chrome/firebug/content/cookies/cookieModule.js |   80 +-
 .../firebug/content/cookies/cookieObserver.js      |   41 +-
 .../chrome/firebug/content/cookies/cookiePanel.js  |   28 +
 .../firebug/content/cookies/cookiePermissions.js   |    2 +-
 .../chrome/firebug/content/cookies/cookieReps.js   |   58 +-
 .../chrome/firebug/content/cookies/cookieUtils.js  |   10 +-
 .../chrome/firebug/content/cookies/menuUtils.js    |    8 +-
 .../chrome/firebug/content/css/computedPanel.js    |   13 +-
 .../chrome/firebug/content/css/cssModule.js        |   52 +-
 .../FBTrace/chrome/firebug/content/css/cssPanel.js |  769 ++++++------
 .../FBTrace/chrome/firebug/content/css/cssReps.js  |    8 +-
 .../chrome/firebug/content/css/selectorEditor.js   |  252 ++++
 .../chrome/firebug/content/css/selectorModule.js   |   74 ++
 .../chrome/firebug/content/css/selectorPanel.js    |  460 +++++++
 .../chrome/firebug/content/css/stylePanel.js       |   94 +-
 .../FBTrace/chrome/firebug/content/dom/domPanel.js |   48 +-
 .../chrome/firebug/content/editor/editor.js        |   22 +-
 trace/FBTrace/chrome/firebug/content/firebug.css   |    8 +-
 trace/FBTrace/chrome/firebug/content/firebug.js    |   87 +-
 .../chrome/firebug/content/firebugOverlay.xul      |   17 +-
 .../chrome/firebug/content/firefox/bindings.xml    |    9 +-
 .../firebug/content/firefox/browserCommands.js     |  107 ++
 .../chrome/firebug/content/firefox/browserMenu.js  |  522 ++++++++
 .../firebug/content/firefox/browserOverlay.css     |    6 +-
 .../firebug/content/firefox/browserOverlay.js      | 1258 ++++----------------
 .../firebug/content/firefox/browserOverlayLib.js   |  272 +++++
 .../firebug/content/firefox/browserToolbar.js      |  136 +++
 .../firefox/external-editors/changeeditor.js       |    4 +-
 .../content/firefox/external-editors/editors.xul   |  100 +-
 .../firefox/external-editors/externalEditors.js    |   17 +-
 .../chrome/firebug/content/firefox/firebug.xul     |   11 +-
 .../firefox/start-button/startButtonOverlay.js     |   27 +-
 .../chrome/firebug/content/html/highlighter.css    |    6 +-
 .../chrome/firebug/content/html/htmlPanel.js       |  132 +-
 .../chrome/firebug/content/html/insideOutBox.js    |    1 +
 .../chrome/firebug/content/html/inspector.js       |   53 +-
 .../FBTrace/chrome/firebug/content/html/layout.js  |  281 +++--
 .../chrome/firebug/content/js/breakpoint.js        |    3 +-
 .../FBTrace/chrome/firebug/content/js/debugger.js  |   62 +-
 .../chrome/firebug/content/js/scriptPanel.js       |   49 +-
 .../chrome/firebug/content/js/sourceCache.js       |    5 +-
 .../FBTrace/chrome/firebug/content/js/tabCache.js  |    4 +-
 .../chrome/firebug/content/js/watchPanel.js        |   59 +-
 trace/FBTrace/chrome/firebug/content/lib/array.js  |   39 +-
 trace/FBTrace/chrome/firebug/content/lib/css.js    |  201 ++--
 .../chrome/firebug/content/lib/deprecated.js       |    6 +-
 trace/FBTrace/chrome/firebug/content/lib/dom.js    |  330 ++++-
 .../FBTrace/chrome/firebug/content/lib/domplate.js |   58 +-
 trace/FBTrace/chrome/firebug/content/lib/events.js |    9 +
 trace/FBTrace/chrome/firebug/content/lib/fonts.js  |   10 +-
 trace/FBTrace/chrome/firebug/content/lib/object.js |   19 +-
 .../FBTrace/chrome/firebug/content/lib/options.js  |   12 +-
 trace/FBTrace/chrome/firebug/content/lib/string.js |   95 +-
 trace/FBTrace/chrome/firebug/content/lib/system.js |   52 +-
 trace/FBTrace/chrome/firebug/content/lib/trace.js  |   63 +-
 trace/FBTrace/chrome/firebug/content/lib/url.js    |   25 +
 .../FBTrace/chrome/firebug/content/lib/wrapper.js  |   16 +-
 trace/FBTrace/chrome/firebug/content/main.js       |    2 +-
 .../FBTrace/chrome/firebug/content/moduleConfig.js |   19 +-
 .../chrome/firebug/content/net/fontViewer.js       |    9 +-
 .../chrome/firebug/content/net/netMonitor.js       |   15 +
 .../FBTrace/chrome/firebug/content/net/netPanel.js |   10 +-
 .../chrome/firebug/content/net/netProgress.js      |   43 +-
 .../FBTrace/chrome/firebug/content/net/netReps.js  |   44 +-
 .../FBTrace/chrome/firebug/content/net/netUtils.js |    2 +
 .../chrome/firebug/content/net/requestObserver.js  |    5 +-
 .../chrome/firebug/content/net/responseObserver.js |    2 +-
 trace/FBTrace/chrome/firebug/content/net/spy.js    |  204 ++--
 .../chrome/firebug/content/net/xmlViewer.js        |    1 +
 trace/FBTrace/chrome/firebug/content/trace.js      |   10 +-
 .../firebug/modules/firebug-http-observer.js       |   30 +-
 .../chrome/firebug/modules/firebug-service.js      |   66 +-
 .../firebug/modules/firebug-trace-service.js       |  281 ++++-
 trace/FBTrace/chrome/firebug/modules/gcli.js       |  111 +-
 trace/FBTrace/chrome/firebug/modules/loader.js     |   35 +-
 trace/FBTrace/chrome/firebug/modules/locale.js     |   16 +-
 .../FBTrace/chrome/firebug/modules/mini-require.js |   15 +-
 .../chrome/firebug/modules/observer-service.js     |    4 +-
 trace/FBTrace/chrome/firebug/modules/prefLoader.js |    6 +
 .../chrome/firebug/modules/require-debug.js        |   36 +-
 .../chrome/firebug/modules/storageService.js       |   44 +-
 .../chrome/firebug/skin/classic/callstack.css      |    8 +
 .../chrome/firebug/skin/classic/console.css        |   47 +-
 .../firebug/skin/classic/cookies/cookies.css       |    4 +-
 trace/FBTrace/chrome/firebug/skin/classic/css.css  |   26 +-
 .../chrome/firebug/skin/classic/debugger.css       |    4 +-
 trace/FBTrace/chrome/firebug/skin/classic/dom.css  |   13 +-
 .../chrome/firebug/skin/classic/firebug.css        |   36 +-
 trace/FBTrace/chrome/firebug/skin/classic/html.css |    7 +-
 .../FBTrace/chrome/firebug/skin/classic/layout.css |    2 +-
 .../chrome/firebug/skin/classic/linux/firebug.css  |    6 +
 .../chrome/firebug/skin/classic/mac/debugger.css   |    4 +-
 .../chrome/firebug/skin/classic/mac/firebug.css    |   31 +-
 .../chrome/firebug/skin/classic/mac/panel.css      |    3 +
 trace/FBTrace/chrome/firebug/skin/classic/net.css  |   14 +-
 .../FBTrace/chrome/firebug/skin/classic/panel.css  |    3 +-
 .../chrome/firebug/skin/classic/panelbase.css      |    2 +-
 .../firebug/skin/classic/performanceTiming.css     |  192 +++
 .../chrome/firebug/skin/classic/selector.css       |   42 +
 .../chrome/firebug/skin/classic/tableRep.css       |    1 +
 .../chrome/firebug/skin/classic/win/firebug.css    |   24 +-
 .../chrome/firebug/skin/classic/win/linux.css      |    0
 .../chrome/firebug/skin/classic/win/panel.css      |    2 +
 135 files changed, 8030 insertions(+), 3494 deletions(-)

diff --git a/trace/FBTrace/chrome/firebug/content/accessible/a11y.js b/trace/FBTrace/chrome/firebug/content/accessible/a11y.js
index 68e086a..1875286 100644
--- a/trace/FBTrace/chrome/firebug/content/accessible/a11y.js
+++ b/trace/FBTrace/chrome/firebug/content/accessible/a11y.js
@@ -57,7 +57,7 @@ Firebug.A11yModel = Obj.extend(Firebug.Module,
         this.onNetFocus = Obj.bind(this.onNetFocus, this);
         this.onNetBlur = Obj.bind(this.onNetBlur, this);
 
-        // mark ourselves disabled so we don't performDisable() if we are not enabled.
+        // Mark ourselves disabled, so we don't performDisable() if we are not enabled.
         Firebug.chrome.window.a11yEnabled = false;
 
         Firebug.connection.addListener(this);
@@ -98,7 +98,7 @@ Firebug.A11yModel = Obj.extend(Firebug.Module,
         {
             // Update for current chrome
             this.set(value, Firebug.chrome);
-            // If the current chrome is external window, update also original chrome.
+            // If the current chrome is an external window, update also the original chrome.
             if (Firebug.chrome != Firebug.originalChrome)
             {
                 this.set(value, Firebug.originalChrome);
@@ -584,7 +584,7 @@ Firebug.A11yModel = Obj.extend(Firebug.Module,
 
     ensurePanelTabStops: function()
     {
-        // XXXjjb: seems like this shoudl be !Firebug.chrome
+        // XXXjjb: seems like this should be !Firebug.chrome
         if (!Firebug.currentContext || !Firebug.currentContext.chrome)
             return;
         var panel = Firebug.chrome.getSelectedPanel();
@@ -1037,7 +1037,7 @@ Firebug.A11yModel = Obj.extend(Firebug.Module,
                 cell = Dom.getChildByClass(cell, "a11yFocus");
             this.focus(cell);
         }
-        // for Net Panel. Focus selected tab rather than the tablist
+        // for Net Panel. Focus selected tab rather than the tab list
         else if (Css.hasClass(row, "netInfoTabs"))
         {
             var tabs = row.getElementsByClassName("netInfoTab");
@@ -1237,6 +1237,11 @@ Firebug.A11yModel = Obj.extend(Firebug.Module,
     onObjectBoxSelected: function(objectBox, forceFocus)
     {
         var panel = Firebug.getElementPanel(objectBox);
+
+        // See issue 5934
+        if (panel.editing)
+            return;
+
         var panelA11y = this.getPanelA11y(panel);
         if (!panelA11y)
             return;
@@ -1547,7 +1552,8 @@ Firebug.A11yModel = Obj.extend(Firebug.Module,
     onBeforeCSSRulesAdded: function(panel)
     {
         // Panel content is about to be recreated, possibly wiping out focus.
-        // Use the focused element's xpath to remember which rule had focus so that it can be refocused when the panel content is drawn again
+        // Use the focused element's xpath to remember which rule had focus,
+        // so that it can be refocused when the panel content is drawn again
         var panelA11y = this.getPanelA11y(panel);
         if (!panelA11y || !this.panelHasFocus(panel))
             return;
@@ -2285,7 +2291,8 @@ Firebug.A11yModel = Obj.extend(Firebug.Module,
 
         var node = line.getElementsByClassName("sourceRowText").item(0);
         this.insertCaretToNode(panel, node);
-        this.focus(focusElem); // move focus back to where it was
+        // move focus back to where it was
+        this.focus(focusElem);
     },
 
     insertCaretToNode: function(panel, node, startOffset)
@@ -2628,10 +2635,12 @@ Firebug.A11yModel = Obj.extend(Firebug.Module,
         }
         var rangeParent = Dom.getAncestorByClass(target, "netRow");
         var browser = Firebug.chrome.getPanelBrowser(panel);
-        // these two lines are necessary, because otherwise the infoTip will not have the correct dimensions when it's positioned, and the contents
-        // could be placed outside FB's viewport (making it impossible to read for keyboard users)
+        // these two lines are necessary, because otherwise the info tip will not have the correct
+        // dimensions when it's positioned, and the contentscould be placed outside of Firebug's
+        // viewport (making it impossible to read for keyboard users)
+        // This will be called again in showInfoTip
         panel.showInfoTip(browser.infoTip, target, target.offsetLeft, target.offsetTop,
-            rangeParent, 0); //will be called again in showInfoTip
+            rangeParent, 0);
         browser.infoTip.setAttribute("active", "true");
         var left = Css.hasClass(target, "netTimeCol") ?
             target.offsetLeft - browser.infoTip.offsetWidth - 12 :
@@ -3019,8 +3028,8 @@ Firebug.A11yModel = Obj.extend(Firebug.Module,
     },
 
     // These utils are almost the same as their DOM namesakes,
-    // except that that the routine skips containers that are not visible
-    // (rather than wasting time on their childnodes)
+    // except that the routine skips invisible containers
+    // (rather than wasting time on their child nodes)
     getPreviousByClass: function (node, className, downOnly, maxRoot)
     {
         if (!node)
diff --git a/trace/FBTrace/chrome/firebug/content/branch.properties b/trace/FBTrace/chrome/firebug/content/branch.properties
index 165fb92..9ab088f 100644
--- a/trace/FBTrace/chrome/firebug/content/branch.properties
+++ b/trace/FBTrace/chrome/firebug/content/branch.properties
@@ -1,5 +1,5 @@
 # DO NOT MERGE INTO TRUNK
-RELEASE=.0a0
+RELEASE=.0
 VERSION=1.11
 TRUNK=
 # To allow build.xml to drop the xpi directly into the svn working copy for getfirebug.com
diff --git a/trace/FBTrace/chrome/firebug/content/bti/inProcess/browser.js b/trace/FBTrace/chrome/firebug/content/bti/inProcess/browser.js
index f76d18d..9483eb7 100644
--- a/trace/FBTrace/chrome/firebug/content/bti/inProcess/browser.js
+++ b/trace/FBTrace/chrome/firebug/content/bti/inProcess/browser.js
@@ -155,7 +155,8 @@ Browser.prototype.clearAllBreakpoints = function()
  */
 Browser.prototype.clearAnnotations = function()
 {
-    Firebug.Activation.clearAnnotations();  // should trigger event onClearAnnotations
+    // should trigger event onClearAnnotations
+    Firebug.Activation.clearAnnotations();
 }
 
 Browser.prototype.getWebAppByWindow = function(win)
@@ -270,9 +271,17 @@ Browser.prototype.getOrCreateContextByWebApp = function(webApp)
         var context = TabWatcher.watchTopWindow(topWindow, browser.currentURI, true);
         this.setContextByWebApp(webApp, context);
 
+        // TEMP; Watch also all iframes. Firebug has been initialized when the page is already
+        // loaded and so, we can't rely on auto-registration done by FrameProgressListener.
+        Win.iterateWindows(context.window, function (win)
+        {
+            TabWatcher.watchWindow(win, context, false);
+        });
+
         browser.showFirebug = true;
 
-        Events.dispatch(TabWatcher.fbListeners, "watchBrowser", [browser]);  // TODO remove
+        // TODO remove
+        Events.dispatch(TabWatcher.fbListeners, "watchBrowser", [browser]);
     }
     return context;
 }
@@ -480,13 +489,18 @@ Browser.prototype.toggleResume = function(resume)
         FBTrace.sysout("BTI.toggleResume" + (Firebug.getSuspended() ? "OFF" : "ON") +
             " -> " + (!!resume ? "ON" : "OFF"));
 
-    // this should be the only method to call suspend and resume.
-    if (resume)  // either a new context or revisiting an old one
+    // This should be the only method to call suspend() and resume().
+    // either a new context or revisiting an old one
+    if (resume)
     {
         if (Firebug.getSuspended())
-            Firebug.resume();  // This will cause onResumeFirebug for every context including this one.
+        {
+            // This will cause onResumeFirebug for every context including this one.
+            Firebug.resume();
+        }
     }
-    else // this browser has no context
+    // this browser has no context
+    else
     {
         Firebug.suspend();
     }
@@ -681,7 +695,8 @@ var TabWatchListener =
 {
     dispatchName: "TabWatchListener",
 
-    initContext: function(context, persistedState)  // called after a context is created.
+    // called after a context is created.
+    initContext: function(context, persistedState)
     {
         context.panelName = context.browser.panelName;
         if (context.browser.sidePanelNames)
@@ -699,25 +714,29 @@ var TabWatchListener =
         Firebug.connection.toggleResume(context);
     },
 
-    /**
-     * To be called from Firebug.TabWatcher only, see selectContext
-     */
-    showContext: function(browser, context)  // Firebug.TabWatcher showContext. null context means we don't debug that browser
+    
+    // To be called from Firebug.TabWatcher only, see selectContext
+    // null as context means we don't debug that browser
+    showContext: function(browser, context)
     {
-        Firebug.chrome.setFirebugContext(context); // the context becomes the default for its view
-        Firebug.connection.toggleResume(context);  // resume, after setting Firebug.currentContext
+        // the context becomes the default for its view
+        Firebug.chrome.setFirebugContext(context);
+        // resume, after setting Firebug.currentContext
+        Firebug.connection.toggleResume(context);
 
-        Events.dispatch(Firebug.modules, "showContext", [browser, context]);  // tell modules we may show UI
+        // tell modules we may show UI
+        Events.dispatch(Firebug.modules, "showContext", [browser, context]);
 
         Firebug.showContext(browser, context);
     },
 
-    unwatchBrowser: function(browser)  // the context for this browser has been destroyed and removed
+    // The context for this browser has been destroyed and removed.
+    unwatchBrowser: function(browser)
     {
         Firebug.connection.toggleResume(false);
     },
 
-    // Either a top level or a frame, (interior window) for an exist context is seen by the tabWatcher.
+    // Either a top level or a frame (interior window) for an existing context is seen by the TabWatcher.
     watchWindow: function(context, win)
     {
         for (var panelName in context.panelMap)
@@ -750,29 +769,41 @@ var TabWatchListener =
 
     destroyContext: function(context, persistedState, browser)
     {
-        if (!context)  // then we are called just to clean up
+        // then we are called just to clean up
+        if (!context)
             return;
 
         Events.dispatch(Firebug.modules, "destroyContext", [context, persistedState]);
 
-        // xxxHonza: not sure if this code is correct. Test case: Firebug active, reload
+        // xxxHonza: Not sure if this code is correct. Test case: Firebug active, reload
         // 1) The Firebug.currentContext can be already set to the new one
         // 2) The Firebug.currentContext can be already null.
-        // Calling clearPanels is important because it also clears the statuPath, which
-        // contains references to panel objects (e.g. Page document in case of the HTML panel)
+        // Calling clearPanels() is important, because it also clears the statusPath, which
+        // contains references to panel objects (e.g. the page document in case of the HTML panel)
         if (Firebug.currentContext == context || !Firebug.currentContext)
         {
-            Firebug.chrome.clearPanels(); // disconnect the to-be-destroyed panels from the panelBar
-            Firebug.chrome.setFirebugContext(null);  // Firebug.currentContext is about to be destroyed
+            // disconnect the to-be-destroyed panels from the panelBar
+            Firebug.chrome.clearPanels();
+            // Firebug.currentContext is about to be destroyed
+            Firebug.chrome.setFirebugContext(null);
         }
 
         var browser = context.browser;
+
         // Persist remnants of the context for restoration if the user reloads
-        browser.panelName = context.panelName;
-        browser.sidePanelNames = context.sidePanelNames;
+        try
+        {
+            browser.panelName = context.panelName;
+            browser.sidePanelNames = context.sidePanelNames;
+        }
+        catch (e)
+        {
+            if (FBTrace.DBG_ERRORS)
+                FBTrace.sysout("browser.destroyContext; " + e, e);
+        }
 
-        // next the context is deleted and removed from the Firebug.TabWatcher,
-        // we clean up in unWatchBrowser
+        // Next time the context is deleted and removed from the Firebug.TabWatcher,
+        // we clean up in unWatchBrowser.
     },
 
     onSourceFileCreated: function()
@@ -809,11 +840,11 @@ var TabWatchListener =
 
 Browser.prototype.connect = function ()
 {
-    // Events fired on browser are re-broadcast to Firebug.modules
+    // Events fired on browser are re-broadcasted to Firebug.modules
     Firebug.connection.addListener(Firebug);
 
-    //Listen for preference changes. This way options module is not dependent on tools
-    //xxxHonza: can this be in Browser interface?
+    // Listen for preference changes. This way the options module is not dependent on tools
+    // xxxHonza: can this be in Browser interface?
     Options.addListener(
     {
         updateOption: function(name, value)
diff --git a/trace/FBTrace/chrome/firebug/content/bti/inProcess/compilationunit.js b/trace/FBTrace/chrome/firebug/content/bti/inProcess/compilationunit.js
index f686e47..f275e6f 100644
--- a/trace/FBTrace/chrome/firebug/content/bti/inProcess/compilationunit.js
+++ b/trace/FBTrace/chrome/firebug/content/bti/inProcess/compilationunit.js
@@ -58,7 +58,8 @@ CompilationUnit.prototype.getKind = function getKind()
 
 CompilationUnit.prototype.isExecutableLine = function isExecutableLine(lineNo)
 {
-    return this.sourceFile.isExecutableLine(lineNo);  // TODO no sourceFiles!
+    // TODO no sourceFiles!
+    return this.sourceFile.isExecutableLine(lineNo);
 }
 
 /**
@@ -103,7 +104,7 @@ CompilationUnit.prototype.getBrowserContext = function()
  */
 CompilationUnit.prototype.getBreakpoints = function()
 {
-    // return a copy of scripts so the master copy is not corrupted
+    // Return a copy of the breakpoints, so the master copy is not corrupted.
     var bps = [];
     for ( var i = 0; i < this.breakpoints.length; i++)
         bps.push(this.breakpoints[i]);
@@ -135,8 +136,8 @@ CompilationUnit.prototype.eachBreakpoint = function( fnOfLineProps )
  */
 CompilationUnit.prototype.getSourceLines = function(firstLine, lastLine, listener)
 {
-    // xxxHonza: do not cache the source lines in compilation unit
-    // The Script panel doesn't display whole script if it's downloaded
+    // xxxHonza: Do not cache the source lines in the compilation unit.
+    // The Script panel doesn't display the whole script if it's downloaded
     // partially and the following caching happens sooner.
     // Or tabCache.storeSplitLines should trigger an update.
     //if (!this.lines)
diff --git a/trace/FBTrace/chrome/firebug/content/bti/inProcess/javascripttool.js b/trace/FBTrace/chrome/firebug/content/bti/inProcess/javascripttool.js
index 2e15fed..9851083 100644
--- a/trace/FBTrace/chrome/firebug/content/bti/inProcess/javascripttool.js
+++ b/trace/FBTrace/chrome/firebug/content/bti/inProcess/javascripttool.js
@@ -39,7 +39,7 @@ JavaScriptTool.breakOnNext = function(context, enable)
 
 JavaScriptTool.setBreakpoint = function(context, url, lineNumber)
 {
-    // TODO we should be sending urls over not compilation units
+    // TODO we should be sending URLs over, not compilation units
     var compilationUnit = context.getCompilationUnit(url);
     JSDebugger.setBreakpoint(compilationUnit, lineNumber);
 };
@@ -71,7 +71,7 @@ JavaScriptTool.getBreakpointCondition = function(context, url, lineNumber)
 };
 
 // ********************************************************************************************* //
-// These functions should be on stack instead
+// These functions should be on the stack instead.
 
 JavaScriptTool.rerun = function(context)
 {
@@ -111,7 +111,8 @@ JavaScriptTool.onConnect = function(connection)
 {
     if (!Firebug.connection.getTool("script"))
     {
-        JavaScriptTool.asTool = new Tool("script"), // this is the script tool
+        // this is the script tool
+        JavaScriptTool.asTool = new Tool("script"),
         connection.registerTool(JavaScriptTool.asTool);
     }
     else
@@ -188,8 +189,12 @@ JavaScriptTool.onStartDebugging = function(context, frame)
 JavaScriptTool.onStopDebugging = function(context)
 {
     var panel = context.getPanel("script", true);
-    if (panel && panel === Firebug.chrome.getSelectedPanel())  // then we are looking at the script panel
-        panel.showNoStackFrame(); // unhighlight and remove toolbar-status line
+    // Then we are looking at the Script panel.
+    if (panel && panel === Firebug.chrome.getSelectedPanel())
+    {
+        // unhighlight and remove toolbar-status line
+        panel.showNoStackFrame();
+    }
 
     if (panel)
         panel.onStopDebugging();
@@ -217,12 +222,14 @@ JavaScriptTool.initialize = function()
     if (FBTrace.DBG_INITIALIZE)
         FBTrace.sysout("JavaScriptTool initialize");
 
-    Firebug.connection.addListener(JavaScriptTool);  // This is how we get events
+    // This is how we get events.
+    Firebug.connection.addListener(JavaScriptTool);
 }
 
 JavaScriptTool.shutdown = function()
 {
-    Firebug.connection.removeListener(JavaScriptTool);  // This is how we get events
+    // This is how we get events.
+    Firebug.connection.removeListener(JavaScriptTool);
 }
 
 // ********************************************************************************************* //
diff --git a/trace/FBTrace/chrome/firebug/content/chrome/activation.js b/trace/FBTrace/chrome/firebug/content/chrome/activation.js
index cbb9eef..c1e1f75 100644
--- a/trace/FBTrace/chrome/firebug/content/chrome/activation.js
+++ b/trace/FBTrace/chrome/firebug/content/chrome/activation.js
@@ -65,7 +65,7 @@ Firebug.Activation = Obj.extend(Firebug.Module,
         if (Firebug.allPagesActivation == "on")
             return true;
 
-        // if about:blank gets thru, 1483 fails
+        // if about:blank gets through, issue 1483 fails
         if (Firebug.filterSystemURLs && Url.isSystemURL(url))
             return false;
 
@@ -85,23 +85,31 @@ Firebug.Activation = Obj.extend(Firebug.Module,
             var hasAnnotation = Annotations.pageHasAnnotation(uri);
 
             if (FBTrace.DBG_ACTIVATION)
-                FBTrace.sysout("shouldCreateContext hasAnnotation "+hasAnnotation +
-                    " for "+uri.spec+" in "+browser.contentWindow.location +
-                    " using activateSameOrigin: "+Firebug.activateSameOrigin);
+            {
+                FBTrace.sysout("shouldCreateContext hasAnnotation " + hasAnnotation +
+                    " for " + uri.spec + " in " +
+                    (browser ? browser.contentWindow.location : "no browser") +
+                    " using activateSameOrigin: " + Firebug.activateSameOrigin);
+            }
 
             // Annotated, so return the value.
             if (hasAnnotation)
                 return this.checkAnnotation(browser, uri);
 
-            if (browser.FirebugLink) // then Firebug.TabWatcher found a connection
+            // Then Firebug.TabWatcher found a connection.
+            if (browser.FirebugLink)
             {
                 var dst = browser.FirebugLink.dst;
                 var dstURI = this.convertToURIKey(dst.spec, Firebug.activateSameOrigin);
+
                 if (FBTrace.DBG_ACTIVATION)
+                {
                     FBTrace.sysout("shouldCreateContext found FirebugLink pointing to " +
                         dstURI.spec, browser.FirebugLink);
+                }
 
-                if (dstURI && dstURI.equals(uri)) // and it matches us now
+                // And it matches us now.
+                if (dstURI && dstURI.equals(uri))
                 {
                     var srcURI = this.convertToURIKey(browser.FirebugLink.src.spec,
                         Firebug.activateSameOrigin);
@@ -109,18 +117,25 @@ Firebug.Activation = Obj.extend(Firebug.Module,
                     if (srcURI)
                     {
                         if (FBTrace.DBG_ACTIVATION)
+                        {
                             FBTrace.sysout("shouldCreateContext found FirebugLink pointing from " +
                                 srcURI.spec, browser.FirebugLink);
+                        }
 
-                        // and it's on the same domain
+                        // And it's on the same domain.
                         if (srcURI.schemeIs("file") || (dstURI.host == srcURI.host))
                         {
                             hasAnnotation = Annotations.pageHasAnnotation(srcURI);
-                            if (hasAnnotation) // and the source page was annotated.
+                            // And the source page was annotated.
+                            if (hasAnnotation)
                             {
                                 var srcShow = this.checkAnnotation(browser, srcURI);
-                                if (srcShow)  // and the source annotation said show it
-                                    this.watchBrowser(browser);  // so we show dst as well.
+                                // And the source annotation said show it.
+                                if (srcShow)
+                                {
+                                    // So we show dst as well.
+                                    this.watchBrowser(browser);
+                                }
                                 return srcShow;
                             }
                         }
@@ -144,10 +159,14 @@ Firebug.Activation = Obj.extend(Firebug.Module,
                         browser.contentWindow.opener.location);
 
                 if (openerContext)
-                    return true;  // popup windows of Firebugged windows are Firebugged
+                {
+                    // popup windows of Firebugged windows are Firebugged
+                    return true;
+                }
             }
 
-            return false;   // don't createContext
+            // don't createContext
+            return false;
         }
         catch (exc)
         {
@@ -162,7 +181,7 @@ Firebug.Activation = Obj.extend(Firebug.Module,
         return this.shouldCreateContext(context.browser, context.getWindowLocation().toString());
     },
 
-    // Firebug is opened in browser
+    // Firebug is opened in the browser.
     watchBrowser: function(browser)
     {
         try
@@ -177,14 +196,20 @@ Firebug.Activation = Obj.extend(Firebug.Module,
         }
     },
 
-    // Firebug closes in browser
+    // Firebug closes in the browser.
     unwatchBrowser: function(browser, userCommands)
     {
         var uri = browser.currentURI.spec;
-        if (userCommands)  // then mark to not open virally.
+        // Then mark to not open virally.
+        if (userCommands)
+        {
             this.setPageAnnotation(uri, "firebugged.closed");
+        }
         else
-            this.removePageAnnotation(uri); // unmark this URI
+        {
+            // unmark this URI
+            this.removePageAnnotation(uri);
+        }
     },
 
     clearAnnotations: function()
@@ -195,10 +220,10 @@ Firebug.Activation = Obj.extend(Firebug.Module,
         Firebug.connection.dispatch("onClearAnnotations", []);
     },
 
-    // process the URL to canonicalize it. Need not be reversible.
+    // Process the URL to canonicalize it. This needs not be reversible.
     convertToURIKey: function(url, sameOrigin)
     {
-        // Remove fragment, it shouldn't have any impact on the activation.
+        // Remove the fragment. It shouldn't have any impact on the activation.
         url = url.replace(/#.*/, "");
 
         var uri = Url.makeURI(Url.normalizeURL(url));
@@ -206,26 +231,32 @@ Firebug.Activation = Obj.extend(Firebug.Module,
         if (Firebug.filterSystemURLs && Url.isSystemURL(url))
             return uri;
 
-        if (url == "about:blank")  // avoid exceptions.
+        // avoid exceptions
+        if (url == "about:blank")
             return uri;
 
         if (uri && sameOrigin)
         {
             try
             {
-                // returns the string before the path (such as "scheme://user:password@host:port").
+                // Returns the string before the path (such as "scheme://user:password@host:port").
                 var prePath = uri.prePath;
                 var shortURI = Url.makeURI(prePath);
                 if (!shortURI)
                     return uri;
 
-                // annoying "about" URIs throw if you access .host
+                // Annoying "about" URIs throw if .host is accessed
                 if (shortURI.scheme === "about")
                     return shortURI;
 
                 if (shortURI.scheme === "file")
                     return shortURI;
 
+                return shortURI;
+
+                // This makes a.co.uk -> co.uk, mail.cn.mozilla.com -> cn.mozilla.com and 
+                // blog.getfirebug.com -> getfirebug.com, which is wrong. See issue 2202.)
+                /*
                 var host = shortURI.host;
                 if (host)
                 {
@@ -234,14 +265,13 @@ Firebug.Activation = Obj.extend(Firebug.Module,
                     // 1) www.google.com -> google.com
                     // 2) www.stuff.co.nz -> stuff.co.nz
                     // 3) getfirebug.com -> getfirebug.com
-                    // (XXX: This makes a.co.uk -> co.uk and mail.cn.mozilla.com -> cn.mozilla.com,
-                    // which is wrong. See issue 2202.)
                     var levels = host.split('.');
                     if (levels.length > 2)
                         levels = levels.slice(1);
                     shortURI.host = levels.join('.');
                     return shortURI;
                 }
+                */
             }
             catch (exc)
             {
@@ -253,6 +283,7 @@ Firebug.Activation = Obj.extend(Firebug.Module,
                 return uri;
             }
         }
+
         return uri;
     },
 
@@ -264,11 +295,17 @@ Firebug.Activation = Obj.extend(Firebug.Module,
             FBTrace.sysout("shouldCreateContext read back annotation " + annotation +
                 " for uri " + uri.spec);
 
-        // then the user closed Firebug on this page last time
+        // Then the user closed Firebug on this page last time.
         if ((Firebug.allPagesActivation != "on") && (annotation.indexOf("closed") > 0))
-            return false;   // annotated as 'closed', don't create
+        {
+            // annotated as 'closed', don't create
+            return false;
+        }
         else
-            return true;    // annotated, createContext
+        {
+            // annotated, createContext
+            return true;
+        }
     },
 
     setPageAnnotation: function(currentURI, annotation)
@@ -310,7 +347,7 @@ Firebug.Activation = Obj.extend(Firebug.Module,
             FBTrace.sysout("Firebug.Activation.unwatchBrowser untagged "+uri.spec);
     },
 
-    // stops at the first fn(uri) that returns a true value
+    // Stops at the first fn(uri) that returns a true value.
     iterateAnnotations: function(fn)
     {
         var annotations = Annotations.getAnnotations(this.annotationName);
diff --git a/trace/FBTrace/chrome/firebug/content/chrome/annotations.js b/trace/FBTrace/chrome/firebug/content/chrome/annotations.js
index 9ca46b8..dc52dd1 100644
--- a/trace/FBTrace/chrome/firebug/content/chrome/annotations.js
+++ b/trace/FBTrace/chrome/firebug/content/chrome/annotations.js
@@ -98,7 +98,9 @@ var Annotations = Obj.extend(Firebug.Module,
             // Initialize output stream.
             var outputStream = Cc["@mozilla.org/network/file-output-stream;1"]
                 .createInstance(Ci.nsIFileOutputStream);
-            outputStream.init(this.file, 0x02 | 0x08 | 0x20, 0666, 0); // write, create, truncate
+            // write, create, truncate
+            // see https://developer.mozilla.org/en-US/docs/PR_Open#Parameters
+            outputStream.init(this.file, 0x02 | 0x08 | 0x20, 0666, 0);
 
             // Convert data to JSON.
             var arr = [];
@@ -112,7 +114,7 @@ var Annotations = Obj.extend(Firebug.Module,
 
             var jsonString = JSON.stringify(arr);
 
-            // Store annotations.
+            // Store annotations
             outputStream.write(jsonString, jsonString.length);
             outputStream.close();
 
@@ -151,11 +153,12 @@ var Annotations = Obj.extend(Firebug.Module,
             var cstream = Cc["@mozilla.org/intl/converter-input-stream;1"]
                 .createInstance(Ci.nsIConverterInputStream);
 
-            // loadAnnotations input stream.
-            inputStream.init(this.file, 0x01 | 0x08, 0666, 0); // read, create
+            // loadAnnotations input stream
+            // read, create
+            inputStream.init(this.file, 0x01 | 0x08, 0666, 0);
             cstream.init(inputStream, "UTF-8", 0, 0);
 
-            // Load annotations.
+            // Load annotations
             var json = "";
             var data = {};
             while (cstream.readString(-1, data) != 0)
@@ -168,7 +171,7 @@ var Annotations = Obj.extend(Firebug.Module,
             if (!arr)
                 return;
 
-            // Convert to map for faster lookup.
+            // convert to map for faster lookup
             for (var i=0; i<arr.length; i++)
                 this.annotations[arr[i].uri] = arr[i].value;
 
diff --git a/trace/FBTrace/chrome/firebug/content/chrome/chrome.js b/trace/FBTrace/chrome/firebug/content/chrome/chrome.js
index eaf6c62..a557cd2 100644
--- a/trace/FBTrace/chrome/firebug/content/chrome/chrome.js
+++ b/trace/FBTrace/chrome/firebug/content/chrome/chrome.js
@@ -58,10 +58,12 @@ const statusCropSize = 20;
 
 // ********************************************************************************************* //
 
-var ChromeFactory =  // factory is global in module loading window
+// factory is global in module loading window
+var ChromeFactory =
 {
 
-createFirebugChrome: function(win)  // chrome is created in caller window.
+// chrome is created in caller window.
+createFirebugChrome: function(win)
 {
     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
     // Private
@@ -77,7 +79,6 @@ createFirebugChrome: function(win)  // chrome is created in caller window.
 var FirebugChrome =
 {
     // TODO: remove this property, add getters for location, title, focusedElement, setter popup
-
     dispatchName: "FirebugChrome",
 
     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -156,13 +157,14 @@ var FirebugChrome =
                 (panelBar1 ? panelBar1.browser.ownerDocument.documentURI : "no panel bar"), win);
 
         // At this point both panelBars can be loaded already, since the src is specified
-        // in firebugOveralay.xul (asynchronously loaded). If yes, start up
-        // the initialization sequence now.
+        // in firebugOverlay.xul (asynchronously loaded). If yes, start up the initialization
+        // sequence now.
         if (browser1Complete && browser2Complete)
         {
             setTimeout(function()
             {
-                FirebugChrome.initializeUI();  // the chrome bound into this scope
+                // chrome bound into this scope
+                FirebugChrome.initializeUI();
             })
         }
     },
@@ -175,7 +177,7 @@ var FirebugChrome =
         if (FBTrace.DBG_INITIALIZE)
             FBTrace.sysout("chrome.initializeUI;");
 
-        // we listen for panel update
+        // listen for panel updates
         Firebug.registerUIListener(this);
 
         try
@@ -210,7 +212,7 @@ var FirebugChrome =
             var mainTabBox = panelBar1.ownerDocument.getElementById("fbPanelBar1-tabBox");
             Events.addEventListener(mainTabBox, "mousedown", onMainTabBoxMouseDown, false);
 
-            // The side panel bar doesn't care about this event.  It must, however,
+            // The side panel bar doesn't care about this event. It must, however,
             // prevent it from bubbling now that we allow the side panel bar to be
             // *inside* the main panel bar.
             Events.addEventListener(panelBar2, "selectingPanel", stopBubble, false);
@@ -225,11 +227,11 @@ var FirebugChrome =
             Firebug.internationalizeUI(win.document);
             Firebug.internationalizeUI(top.document);
 
-            // xxxHonza: Is there any reason why we don't distribute "initializeUI"
+            // xxxHonza: Is there any reason why we don't distribute "initializeUI"?
             // event to modules?
             Firebug.initializeUI();
 
-            // Append all registered stylesheets into Firebug UI.
+            // Append all registered stylesheets into Firebug UI
             for (var i=0; i<Firebug.stylesheets.length; i++)
             {
                 var uri = Firebug.stylesheets[i];
@@ -240,7 +242,7 @@ var FirebugChrome =
                 FBTrace.sysout("chrome.initializeUI; Custom stylesheet appended " +
                     Firebug.stylesheets.length, Firebug.stylesheets);
 
-            // Fire event for window event listeners.
+            // Fire event for window event listeners
             Firebug.sendLoadEvent();
         }
         catch (exc)
@@ -311,7 +313,7 @@ var FirebugChrome =
     },
 
     /**
-     * Checking first window in back order, (Most recent window). is itself firebug ?
+     * Checks if the Firebug window has the focus (is the most recent window)
      */
     hasFocus: function()
     {
@@ -363,7 +365,7 @@ var FirebugChrome =
 
     disableOff: function(collapse)
     {
-        // disable/enable this button in the Firebug.chrome window.
+        // disable/enable this button in the Firebug.chrome window
         Dom.collapse(FirebugChrome.$("fbCloseButton"), collapse);
     },
 
@@ -376,7 +378,8 @@ var FirebugChrome =
 
         // Command Line Popup can be displayed for all the other panels
         // (except for the Console panel)
-        // XXXjjb, xxxHonza: this should be somehow better, more generic and extensible...
+        // XXXjjb, xxxHonza, xxxsz: this should be somehow better, more generic and extensible,
+        // e.g. by asking each panel if it supports the Command Line Popup 
         var consolePanelType = Firebug.getPanelType("console");
         if (consolePanelType == panelType)
         {
@@ -415,16 +418,20 @@ var FirebugChrome =
            .getService(Components.interfaces.nsIProperties)
            .get("TmpD", Components.interfaces.nsIFile);
 
-        file.append("firebug");   // extensions sub-directory
+        // extensions sub-directory
+        file.append("firebug");
         file.append("panelSave.html");
         file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666);
-        foStream.init(file, 0x02 | 0x08 | 0x20, 0664, 0);   // write, create, truncate
-        serializer.serializeToStream(doc, foStream, "");   // rememeber, doc is the DOM tree
+        // write, create, truncate
+        foStream.init(file, 0x02 | 0x08 | 0x20, 0664, 0);
+        // remember, doc is the DOM tree
+        serializer.serializeToStream(doc, foStream, "");
         foStream.close();
         return file.path;
     },
 
-    updatePanelBar1: function(panelTypes)  // part of initializeUI
+    // part of initializeUI
+    updatePanelBar1: function(panelTypes)
     {
         var mainPanelTypes = [];
         for (var i = 0; i < panelTypes.length; ++i)
@@ -501,7 +508,10 @@ var FirebugChrome =
         {
             this.positionInitialzed = true;
             if (Firebug.framePosition != "detached" && Firebug.framePosition != "bottom")
-                this.setPosition(); // null only updates frame position without side effects
+            {
+                // null only updates frame position without side effects
+                this.setPosition();
+            }
         }
     },
 
@@ -519,11 +529,12 @@ var FirebugChrome =
         Dom.collapse(Firebug.chrome.$("fbContentBox"), false);
     },
 
-    syncResumeBox: function(context)  // only called when detached
+    // only called when detached
+    syncResumeBox: function(context)
     {
         var resumeBox = Firebug.chrome.$('fbResumeBox');
 
-        // xxxHonza: Don't focus Firebug window now. It would bring Firebug detached window
+        // xxxHonza: Don't focus the Firebug window now. It would bring the detached Firebug window
         // to the top every time the attached Firefox page is refreshed, which is annoying.
         //this.focus();  // bring to users attention
 
@@ -537,7 +548,8 @@ var FirebugChrome =
         {
             Firebug.chrome.toggleOpen(false);
             Dom.collapse(resumeBox, false);
-            Firebug.chrome.window.top.document.title =
+
+            Firebug.chrome.window.parent.document.title =
                 Locale.$STR("Firebug - inactive for current website");
         }
     },
@@ -570,7 +582,7 @@ var FirebugChrome =
         var i, currentIndex = newIndex = -1, currentPanel = this.getSelectedPanel(), newPanel;
         var panelTypes = Firebug.getMainPanelTypes(Firebug.currentContext);
 
-        // Get current panel's index (is there a simpler way for this?
+        // get the current panel's index (is there a simpler way for this?)
         for (i = 0; i < panelTypes.length; i++)
         {
             if (panelTypes[i].prototype.name === currentPanel.name)
@@ -628,10 +640,10 @@ var FirebugChrome =
     /**
      * Set this.location on the current panel or one given by name.
      * The location object should be known to the caller to be of the correct type for the panel,
-     * eg SourceFile for Script panel
-     * @param object the location object, null selects default location
-     * @param panelName the .name field for the desired panel, null means current panel
-     * @param sidePanelName I don't know how this affects the outcome
+     * e.g. SourceFile for Script panel
+     * @param object location object, null selects default location
+     * @param panelName name of the panel to select, null means current panel
+     * @param sidePanelName name of the side panel to select
      */
     navigate: function(object, panelName, sidePanelName)
     {
@@ -648,9 +660,9 @@ var FirebugChrome =
     /**
      *  Set this.selection by object type analysis, passing the object to all panels to
      *      find the best match
-     *  @param object the new this.selection object
-     *  @param panelName matching panel.name will be used, if its supportsObject returns true value
-     *  @param sidePanelName default side panel name used, if its supportsObject returns true value
+     *  @param object new this.selection object
+     *  @param panelName matching panel.name will be used, if its supportsObject returns true
+     *  @param sidePanelName default side panel name used, if its supportsObject returns true
      *  @param forceUpdate if true, then (object === this.selection) is ignored and
      *      updateSelection is called
      */
@@ -662,7 +674,7 @@ var FirebugChrome =
 
         var bestPanelName = getBestPanelName(object, Firebug.currentContext, panelName);
 
-        // Allow refresh if needed (the last argument).
+        // allow refresh if needed (last argument)
         var panel = this.selectPanel(bestPanelName, sidePanelName/*, true*/);
         if (panel)
             panel.select(object, forceUpdate);
@@ -712,7 +724,7 @@ var FirebugChrome =
 
     switchToPanel: function(context, switchToPanelName)
     {
-        // Remember the previous panel and bar state so we can revert if the user cancels
+        // Remember the previous panel and bar state so we can revert if the user cancels.
         this.previousPanelName = context.panelName;
         this.previousSidePanelName = context.sidePanelName;
         this.previouslyCollapsed = FirebugChrome.$("fbContentBox").collapsed;
@@ -850,7 +862,7 @@ var FirebugChrome =
             if (!panelName)
                 panelName = context.panelName? context.panelName : Firebug.defaultPanelName;
 
-            // Make HTML panel the default panel, which is displayed
+            // Make the HTML panel the default panel, which is displayed
             // to the user the very first time.
             if (!panelName || !Firebug.getPanelType(panelName))
                 panelName = "html";
@@ -874,7 +886,7 @@ var FirebugChrome =
             var panelTypes = Firebug.getMainPanelTypes(Firebug.currentContext);
             panelBar1.updatePanels(panelTypes);
 
-            // Upadate also BON tab flag (orange background if BON is active)
+            // Update also BON tab flag (orange background if BON is active)
             // every time the user changes the current tab in Firefox.
             Firebug.Breakpoint.updatePanelTabs(Firebug.currentContext);
         }
@@ -913,7 +925,7 @@ var FirebugChrome =
             }
             else
             {
-                // if the context changes we need to refresh the panel
+                // If the context changes, we need to refresh the panel.
                 panelBar2.selectPanel(panelBar2.selectedPanel.name, true);
             }
         }
@@ -936,11 +948,11 @@ var FirebugChrome =
         if (Firebug.currentContext)
         {
             var title = Firebug.currentContext.getTitle();
-            win.top.document.title = Locale.$STRF("WindowTitle", [title]);
+            win.parent.document.title = Locale.$STRF("WindowTitle", [title]);
         }
         else
         {
-            win.top.document.title = Locale.$STR("Firebug");
+            win.parent.document.title = Locale.$STR("Firebug");
         }
     },
 
@@ -994,8 +1006,8 @@ var FirebugChrome =
             }
             else
             {
-                // Alright, let's update visibility of the separator. The separator
-                // is displayed only, if there are some other buttons on the left side.
+                // Update the visibility of the separator. The separator
+                // is displayed only if there are some other buttons on the left side.
                 // Before showing the status separator let's see whether there are any other
                 // buttons on the left.
                 var hide = true;
@@ -1016,7 +1028,7 @@ var FirebugChrome =
 
                 panelStatus.lastPanelName = panel.name;
 
-                // If the object already exists in the list, just select it and keep the path
+                // If the object already exists in the list, just select it and keep the path.
                 var selection = panel.selection;
                 var existingItem = panelStatus.getItemByObject(panel.selection);
                 if (existingItem)
@@ -1110,7 +1122,7 @@ var FirebugChrome =
         var vertical = pos == "top" || pos == "bottom";
         var after = pos == "bottom" || pos == "right";
 
-        var document = window.top.document;
+        var document = window.parent.document;
         var container = document.getElementById(vertical ? "appcontent" : "browser");
 
         var splitter = Firefox.getElementById("fbContentSplitter");
@@ -1151,7 +1163,7 @@ var FirebugChrome =
     swapBrowsers: function(oldBrowser, newBrowser)
     {
         var oldDoc = oldBrowser.contentDocument
-        // Panels remember top window, for which they were first opened.
+        // Panels remember the top window, for which they were first opened.
         // So we need to destroy their views.
         var styleSheet = oldDoc.styleSheets[0];
         var rulePos = styleSheet.cssRules.length;
@@ -1231,8 +1243,8 @@ var FirebugChrome =
 
     setChromeDocumentAttribute: function(id, name, value)
     {
-        // Call as Firebug.chrome.setChromeDocumentAttribute() to set attributes
-        // in another window.
+        // call as Firebug.chrome.setChromeDocumentAttribute() to set attributes
+        // in another window
         var elt = FirebugChrome.$(id);
         if (elt)
             elt.setAttribute(name, value);
@@ -1296,7 +1308,7 @@ var FirebugChrome =
 
     getElementById: function(id)
     {
-        // The document we close over not the global.
+        // The document we close over, not the global.
         return win.document.getElementById(id);
     },
 
@@ -1310,7 +1322,9 @@ var FirebugChrome =
         var zoom = Firebug.Options.getZoomByTextSize(value);
         var zoomString = (zoom * 100) + "%";
 
-        var fontSizeAdjust = zoom * 0.547; // scale the aspect relative to 11pt Lucida Grande
+        // scale the aspect relative to 11pt Lucida Grande
+        // xxxsz: The magic number 0.547 should be replaced some logic retrieving this value.
+        var fontSizeAdjust = zoom * 0.547;
         var contentBox = Firebug.chrome.$("fbContentBox");
         contentBox.style.fontSizeAdjust = fontSizeAdjust;
 
@@ -1376,16 +1390,16 @@ var FirebugChrome =
 
             var sidePanel = panelBar2.selectedPanel;
             if (sidePanel)
-                sidePanel.select(object);
+                sidePanel.refresh();
         }
     },
 
-    // called on setTimeout after sourceBox viewport has been repainted
+    // called on setTimeout() after sourceBox viewport has been repainted
     onApplyDecorator: function(sourceBox)
     {
     },
 
-    // called on scrollTo, passing in the selected line
+    // called on scrollTo() passing in the selected line
     onViewportChange: function(sourceLink)
     {
     },
@@ -1427,7 +1441,7 @@ var FirebugChrome =
               toggleFirebug.setAttribute("tooltiptext", Locale.$STR("firebug.menu.tip.Minimize_Firebug"));
             }
 
-            // If Firebug is detached, hide the menu ('Open Firebug' shortcut doesn't hide,
+            // If Firebug is detached, hide the menu. ('Open Firebug' shortcut doesn't hide
             // but just focuses the external window)
             if (Firebug.isDetached())
                 toggleFirebug.setAttribute("collapsed", (collapsed == "true" ? "false" : "true"));
@@ -1465,7 +1479,7 @@ var FirebugChrome =
 
     onContextShowing: function(event)
     {
-        // xxxHonza: This context-menu support can be used even in a separate window, which
+        // xxxHonza: This context menu support can be used even in a separate window, which
         // doesn't contain the Firebug UI (panels).
         //if (!panelBar1.selectedPanel)
         //    return false;
@@ -1477,13 +1491,13 @@ var FirebugChrome =
         var target = win.document.popupNode;
         var panel = target ? Firebug.getElementPanel(target) : null;
 
-        // the event must be on our chrome not inside the panel
+        // The event must be on our chrome not inside the panel.
         if (!panel)
             panel = panelBar1 ? panelBar1.selectedPanel : null;
 
         Dom.eraseNode(popup);
 
-        // Make sure the Copy action is only available if there is actually someting
+        // Make sure the Copy action is only available if there is actually something
         // selected in the panel.
         var sel = target.ownerDocument.defaultView.getSelection();
         if (!this.contextMenuObject &&
@@ -1502,7 +1516,7 @@ var FirebugChrome =
         else if (target && panel)
             object = panel.getPopupObject(target);
         else if (target)
-            // xxxHonza: What about a node from different document? Is that OK?
+            // xxxHonza: What about a node from a different document? Is that OK?
             object = Firebug.getRepObject(target);
 
         this.contextMenuObject = null;
@@ -1511,68 +1525,55 @@ var FirebugChrome =
         var realObject = rep ? rep.getRealObject(object, Firebug.currentContext) : null;
         var realRep = realObject ? Firebug.getRep(realObject, Firebug.currentContext) : null;
 
-        if (FBTrace.DBG_OPTIONS)
-            FBTrace.sysout("chrome.onContextShowing object:"+object+" rep: "+rep+
-                " realObject: "+realObject+" realRep:"+realRep);
+        if (FBTrace.DBG_MENU)
+        {
+            FBTrace.sysout("chrome.onContextShowing object:"+object+", rep: "+rep+
+                ", realObject: "+realObject+", realRep:"+realRep);
+        }
 
+        // 1. Add the custom menu items from the realRep
         if (realObject && realRep)
         {
-            // 1. Add the custom menu items from the realRep
-            var menu = realRep.getContextMenuItems(realObject, target, Firebug.currentContext);
-            if (menu)
-            {
-                for (var i = 0; i < menu.length; ++i)
-                    Menu.createMenuItem(popup, menu[i]);
-            }
+            var items = realRep.getContextMenuItems(realObject, target, Firebug.currentContext);
+            if (items)
+                Menu.createMenuItems(popup, items);
         }
 
+        // 2. Add the custom menu items from the original rep
         if (object && rep && rep != realRep)
         {
-            // 1. Add the custom menu items from the original rep
             var items = rep.getContextMenuItems(object, target, Firebug.currentContext);
             if (items)
-            {
-                for (var i = 0; i < items.length; ++i)
-                    Menu.createMenuItem(popup, items[i]);
-            }
+                Menu.createMenuItems(popup, items);
         }
 
-        // 1. Add the custom menu items from the panel
+        // 3. Add the custom menu items from the panel
         if (panel)
         {
             var items = panel.getContextMenuItems(realObject, target);
             if (items)
-            {
-                for (var i = 0; i < items.length; ++i)
-                    Menu.createMenuItem(popup, items[i]);
-            }
+                Menu.createMenuItems(popup, items);
         }
 
-        // 2. Add the inspect menu items
+        // 4. Add the inspect menu items
         if (realObject && rep && rep.inspectable)
         {
-            var separator = null;
-
             var items = this.getInspectMenuItems(realObject);
-            for (var i = 0; i < items.length; ++i)
-            {
-                if (popup.firstChild && !separator)
-                    separator = Menu.createMenuSeparator(popup);
 
-                Menu.createMenuItem(popup, items[i]);
-            }
+            // Separate existing menu items from 'inspect' menu items.
+            if (popup.firstChild && items.length > 0)
+                Menu.createMenuSeparator(popup);
+
+            Menu.createMenuItems(popup, items);
         }
 
-        // 3. Add menu items from uiListeners
+        // 5. Add menu items from uiListeners
         var items = [];
         Events.dispatch(Firebug.uiListeners, "onContextMenu", [items, object, target,
             Firebug.currentContext, panel, popup]);
 
         if (items)
-        {
-            for (var i = 0; i < items.length; ++i)
-                Menu.createMenuItem(popup, items[i]);
-        }
+            Menu.createMenuItems(popup, items);
 
         if (!popup.firstChild)
             return false;
@@ -1624,14 +1625,14 @@ var FirebugChrome =
 
         var object;
 
-        /* XXXjjb This causes the Script panel to show the function body over and over.
-         * We need to clear it at least, but really we need to understand why the tooltip
+        /* XXXjjb: This causes the Script panel to show the function body over and over.
+         * We need to clear it at least, but actually we need to understand why the tooltip
          * should show the context menu object at all. One thing the contextMenuObject supports
          * is peeking at function bodies when stopped at a breakpoint.
          * That case could be supported with clearing the contextMenuObject, but we don't
-         * know, if that breaks something else. So maybe a popupMenuObject should be set
-         * on the context if that is what we want to support
-         * The other complication is, that there seems to be another tooltip.
+         * know if that breaks something else. So maybe a popupMenuObject should be set
+         * on the context if that is what we want to support.
+         * The other complication is that there seems to be another tooltip.
         if (this.contextMenuObject)
         {
             object = this.contextMenuObject;
@@ -1708,7 +1709,7 @@ var FirebugChrome =
 
     breakOnNext: function(context, event)
     {
-        // Avoid bubbling from associated options.
+        // avoid bubbling from associated options
         if (event.target.id != "cmd_firebug_toggleBreakOn")
             return;
 
@@ -1764,9 +1765,8 @@ var FirebugChrome =
                 break;
             }
         }
-    },
-
-};  // end of FirebugChrome
+    }
+};
 
 // ********************************************************************************************* //
 // Local Helpers
@@ -1776,7 +1776,7 @@ function panelSupportsObject(panelType, object, context)
     if (panelType)
     {
         try {
-            // This tends to throw exceptions often, because some objects are weird
+            // This tends to throw exceptions often because some objects are weird
             return panelType.prototype.supportsObject(object, typeof object, context)
         } catch (exc) {}
     }
@@ -1789,7 +1789,7 @@ function getBestPanelName(object, context, panelName)
     if (!panelName && context)
         panelName = context.panelName;
 
-    // Check if the panel type of the suggested panel supports the object, and if so, go with it
+    // Check if the panel type of the suggested panel supports the object, and if so, go with it.
     if (panelName)
     {
         var panelType = Firebug.getPanelType(panelName);
@@ -1798,7 +1798,7 @@ function getBestPanelName(object, context, panelName)
     }
 
     // The suggested name didn't pan out, so search for the panel type with the
-    // most specific level of support
+    // most specific level of support.
     return getBestPanelSupportingObject(object, context);
 }
 
@@ -1834,7 +1834,7 @@ function getBestSidePanelName(sidePanelName, panelTypes)
 {
     if (sidePanelName)
     {
-        // Verify, that the suggested panel name is in the acceptable list
+        // Verify, that the suggested panel name is in the acceptable list.
         for (var i = 0; i < panelTypes.length; ++i)
         {
             if (panelTypes[i].prototype.name == sidePanelName)
@@ -1842,7 +1842,7 @@ function getBestSidePanelName(sidePanelName, panelTypes)
         }
     }
 
-    // Default to the first panel type in the list
+    // Default to the first panel type in the list.
     return panelTypes.length ? panelTypes[0].prototype.name : null;
 }
 
@@ -1863,10 +1863,11 @@ function browser1Loaded()
 
     if (browser1.complete && browser2.complete)
     {
-        // initializeUI is executed asynchronously, which solves the issue 3442
-        // The problem has been introduced (from unknown reason) by revision R12210
+        // initializeUI() is executed asynchronously (solves issue 3442)
+        // The problem has been introduced (for an unknown reason) by revision R12210
         setTimeout(function() {
-            FirebugChrome.initializeUI();  // the chrome bound into this scope
+            // chrome bound into this scope
+            FirebugChrome.initializeUI();
         });
     }
 
@@ -1890,7 +1891,8 @@ function browser2Loaded()
     {
         // See browser1Loaded for more info.
         setTimeout(function() {
-            FirebugChrome.initializeUI();  // the chrome bound into this scope
+            // chrome bound into this scope
+            FirebugChrome.initializeUI();
         });
     }
 
@@ -1900,11 +1902,10 @@ function browser2Loaded()
 
 function onBlur(event)
 {
-    // XXXjjb this seems like a waste: called continuously to clear possible highlight I guess.
-    // XXXhh Is this really necessary? I disabled it for now as this was preventing me
+    // XXXjjb: this seems like a waste: called continuously to clear possible highlight I guess.
+    // XXXhh: Is this really necessary? I disabled it for now as this was preventing me
     // to show highlights on focus
     //Firebug.Inspector.highlightObject(null, Firebug.currentContext);
-
 }
 
 function onSelectLocation(event)
@@ -1940,9 +1941,9 @@ function onSelectingPanel(event)
         panel.navigate(panel.location);
 
     // Hide all toolbars now. It's a responsibility of the new selected panel to show
-    // those toolbars, that are necessary. This avoids the situation, when naughty panel
-    // doesn't clean up its toolbars. This must be done before 'showPanel', where visibility
-    // of the BON buttons is managed.
+    // those toolbars, that are necessary. This avoids the situation when a naughty panel
+    // doesn't clean up its toolbars. This must be done before 'showPanel' is dispatched,
+    // where the visibility of the BON buttons is managed.
     var toolbar = FirebugChrome.$("fbToolbarInner");
     var child = toolbar.firstChild;
     while (child)
@@ -1951,14 +1952,14 @@ function onSelectingPanel(event)
         child = child.nextSibling;
     }
 
-    // Those extensions that don't use XUL overlays (e.g. bootstrapped extensions)
+    // Those extensions that don't use XUL overlays (i.e. bootstrapped extensions)
     // can provide toolbar buttons throug Firebug APIs.
     var panelToolbar = FirebugChrome.$("fbPanelToolbar");
     Dom.eraseNode(panelToolbar);
 
     if (panel)
     {
-        // Get buttons from the current panel.
+        // get buttons from current panel
         var buttons;
         if (panel.getPanelToolbarButtons)
             buttons = panel.getPanelToolbarButtons();
@@ -1984,7 +1985,7 @@ function onSelectingPanel(event)
     Firebug.chrome.syncLocationList();
     Firebug.chrome.syncStatusPath();
 
-    //xxxjjb unfortunately the callstack side panel depends on the status path (sync after.)
+    //xxxjjb: unfortunately the Stack side panel depends on the status path (sync after.)
     Firebug.chrome.syncSidePanels();
 }
 
diff --git a/trace/FBTrace/chrome/firebug/content/chrome/menu.js b/trace/FBTrace/chrome/firebug/content/chrome/menu.js
index 57b3508..c156834 100644
--- a/trace/FBTrace/chrome/firebug/content/chrome/menu.js
+++ b/trace/FBTrace/chrome/firebug/content/chrome/menu.js
@@ -4,9 +4,10 @@ define([
     "firebug/lib/trace",
     "firebug/lib/locale",
     "firebug/lib/options",
-    "firebug/lib/css"
+    "firebug/lib/css",
+    "firebug/lib/deprecated"
 ],
-function(FBTrace, Locale, Options, Css) {
+function(FBTrace, Locale, Options, Css, Deprecated) {
 
 // ********************************************************************************************* //
 // Constants
@@ -15,23 +16,47 @@ var Menu = {};
 
 // ********************************************************************************************* //
 
-Menu.createMenu = function(popup, label)
+Menu.createMenu = function(popup, item)
 {
+    if (typeof item == "string")
+    {
+        return Deprecated.deprecated("The function's header changed to "+
+            "createMenu(popup, item)",
+            Menu.createMenu, [popup, {label: item}])();
+    }
+
     var menu = popup.ownerDocument.createElement("menu");
-    menu.setAttribute("label", label);
+
+    Menu.setItemIntoElement(menu, item);
 
     var menuPopup = popup.ownerDocument.createElement("menupopup");
 
     popup.appendChild(menu);
     menu.appendChild(menuPopup);
 
+    if (item.items)
+    {
+        for (var i = 0, len = item.items.length; i < len; ++i)
+            Menu.createMenuItem(menuPopup, item.items[i]);
+    }
+
     return menuPopup;
 };
 
+// Menu.createMenuItems(popup, items[, before])
+Menu.createMenuItems = function(popup, items, before)
+{
+    for (var i=0; i<items.length; i++)
+        Menu.createMenuItem(popup, items[i], before);
+};
+
 Menu.createMenuItem = function(popup, item, before)
 {
-    if (typeof(item) == "string" && item.charAt(0) == "-")
-        return Menu.createMenuSeparator(popup, before);
+    if ((typeof(item) == "string" && item == "-") || item.label == "-")
+        return Menu.createMenuSeparator(popup, item, before);
+
+    if (item.items)
+        return Menu.createMenu(popup, item);
 
     var menuitem = popup.ownerDocument.createElement("menuitem");
 
@@ -100,6 +125,9 @@ Menu.setItemIntoElement = function(element, item)
     if (item.name)
         element.setAttribute("name", item.name);
 
+    if (item.items && (item.command || item.commandID))
+        element.setAttribute("type", "splitmenu");
+
     return element;
 }
 
@@ -116,17 +144,30 @@ Menu.createMenuHeader = function(popup, item)
     return header;
 };
 
-Menu.createMenuSeparator = function(popup, before)
+Menu.createMenuSeparator = function(popup, item, before)
 {
+    if (item instanceof Node)
+    {
+        return Deprecated.deprecated("The function's header changed to "+
+            "createMenuSeparator(popup, item, before)",
+            Menu.createMenuSeparator, [popup, null, before])();
+    }
+
     if (!popup.firstChild)
         return;
 
-    var menuitem = popup.ownerDocument.createElement("menuseparator");
+    if (FBTrace.DBG_MENU)
+        FBTrace.sysout("createMenuSeparator", {popup: popup, item: item, before: before});
+
+    var menuItem = popup.ownerDocument.createElement("menuseparator");
+    if (typeof item == "object" && item.id)
+        menuItem.setAttribute("id", item.id);
+
     if (before)
-        popup.insertBefore(menuitem, before);
+        popup.insertBefore(menuItem, before);
     else
-        popup.appendChild(menuitem);
-    return menuitem;
+        popup.appendChild(menuItem);
+    return menuItem;
 };
 
 /**
diff --git a/trace/FBTrace/chrome/firebug/content/chrome/panelActivation.js b/trace/FBTrace/chrome/firebug/content/chrome/panelActivation.js
index a66b00f..5e436e1 100644
--- a/trace/FBTrace/chrome/firebug/content/chrome/panelActivation.js
+++ b/trace/FBTrace/chrome/firebug/content/chrome/panelActivation.js
@@ -8,9 +8,8 @@ define([
     "firebug/lib/domplate",
     "firebug/lib/url",
     "firebug/lib/dom",
-    "firebug/js/fbs",   // bug712289
 ],
-function(Obj, Firebug, Firefox, Locale, Domplate, Url, Dom, FBS) {
+function(Obj, Firebug, Firefox, Locale, Domplate, Url, Dom) {
 
 // ************************************************************************************************
 // Constants
@@ -18,7 +17,7 @@ function(Obj, Firebug, Firefox, Locale, Domplate, Url, Dom, FBS) {
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
-const prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch2);
+const prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
 
 
 /**
@@ -334,16 +333,6 @@ Firebug.DisabledPanelBox = domplate(Firebug.Rep,
         var parentNode = this.getParentNode(browser);
         this.tag.replace(args, parentNode, this);
         parentNode.removeAttribute("collapsed");
-
-        // bug712289
-        if (panelName == "script" && !FBS.isJSDAvailable())
-        {
-            Dom.hide(parentNode.querySelector(".descImage"), true);
-            Dom.hide(parentNode.querySelector(".objectLink"), true);
-
-            var desc = parentNode.querySelector(".disabledPanelDescription");
-            desc.innerHTML = Locale.$STR("moduleManager.scriptPanelNotAvailable");
-        }
     },
 
     /**
diff --git a/trace/FBTrace/chrome/firebug/content/chrome/reps.js b/trace/FBTrace/chrome/firebug/content/chrome/reps.js
index 8e34005..71e124f 100644
--- a/trace/FBTrace/chrome/firebug/content/chrome/reps.js
+++ b/trace/FBTrace/chrome/firebug/content/chrome/reps.js
@@ -103,6 +103,17 @@ FirebugReps.Null = domplate(Firebug.Rep,
 
 // ********************************************************************************************* //
 
+FirebugReps.Hint = domplate(Firebug.Rep,
+{
+    tag: OBJECTBOX("$object"),
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+    className: "hint",
+});
+
+// ********************************************************************************************* //
+
 FirebugReps.Nada = domplate(Firebug.Rep,
 {
     tag: SPAN(""),
@@ -285,6 +296,7 @@ FirebugReps.Func = domplate(Firebug.Rep,
         var monitored = scriptInfo ? FBS.fbs.isMonitored(scriptInfo.sourceFile.href,
             scriptInfo.lineNo) : false;
 
+        var self = this;
         var name = script ? StackFrame.getFunctionName(script, context) : fn.name;
         return [
             {
@@ -293,7 +305,11 @@ FirebugReps.Func = domplate(Firebug.Rep,
                 nol10n: true,
                 type: "checkbox",
                 checked: monitored,
-                command: Obj.bindFixed(this.monitor, this, fn, monitored)
+                command: function()
+                {
+                    var checked = this.hasAttribute("checked");
+                    self.monitor(fn, !checked);
+                }
             },
             "-",
             {
@@ -509,42 +525,34 @@ FirebugReps.Reference = domplate(Firebug.Rep,
 
 // ********************************************************************************************* //
 
-FirebugReps.Arr = domplate(Firebug.Rep,
+FirebugReps.ArrBase = domplate(FirebugReps.Obj,
 {
-    tag:
-        OBJECTBOX({_repObject: "$object",
-            $hasTwisty: "$object|hasSpecialProperties",
-            onclick: "$onToggleProperties"},
-            SPAN({"class": "arrayLeftBracket", role: "presentation"}, "["),
-            FOR("item", "$object|longArrayIterator",
-                TAG("$item.tag", {object: "$item.object"}),
-                SPAN({"class": "arrayComma", role: "presentation"}, "$item.delim")
-            ),
-            SPAN({"class": "arrayRightBracket", role: "presentation"}, "]"),
-            SPAN({"class": "arrayProperties", role: "group"})
-        ),
+    className: "array",
+    toggles: new ToggleBranch.ToggleBranch(),
 
-    shortTag:
-        OBJECTBOX({_repObject: "$object",
-            $hasTwisty: "$object|hasSpecialProperties",
-            onclick: "$onToggleProperties"},
-            SPAN({"class": "arrayLeftBracket", role: "presentation"}, "["),
-            FOR("item", "$object|shortArrayIterator",
-                TAG("$item.tag", {object: "$item.object"}),
-                SPAN({"class": "arrayComma", role: "presentation"}, "$item.delim")
-            ),
-            SPAN({"class": "arrayRightBracket"}, "]"),
-            SPAN({"class": "arrayProperties", role: "group"})
-        ),
+    titleTag:
+        SPAN({"class": "objectTitle"}, "$object|getTitleTag"),
+
+    getTitle: function(object, context)
+    {
+        return "[" + object.length + "]";
+    },
+
+    supportsObject: function(object, type)
+    {
+        return this.isArray(object);
+    },
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
     longArrayIterator: function(array)
     {
-       return this.arrayIterator(array, 300);
+        return this.arrayIterator(array, 300);
     },
 
     shortArrayIterator: function(array)
     {
-       return this.arrayIterator(array, Options.get("ObjectShortIteratorMax"));
+        return this.arrayIterator(array, Options.get("ObjectShortIteratorMax"));
     },
 
     arrayIterator: function(array, max)
@@ -586,8 +594,6 @@ FirebugReps.Arr = domplate(Firebug.Rep,
         return items;
     },
 
-    toggles: new ToggleBranch.ToggleBranch(),
-
     getItemIndex: function(child)
     {
         var arrayIndex = 0;
@@ -662,23 +668,16 @@ FirebugReps.Arr = domplate(Firebug.Rep,
 
     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
-    className: "array",
-
-    supportsObject: function(object, type, context)
-    {
-        return this.isArray(object, context ? context.window : null);
-    },
-
     highlightObject: function(object, context, target)
     {
-        // Highlighting huge amount of elements on the page can cause sericous performance
+        // Highlighting huge amount of elements on the page can cause serious performance
         // problems (see issue 4736). So, avoid highlighting if the number of elements in
         // the array exceeds specified limit.
         var arr = this.getRealObject(object, context);
         var limit = Options.get("multiHighlightLimit");
         if (!arr || (limit > 0 && arr.length > limit))
         {
-            if (Css.hasClass(target, "arrayLeftBracket ") ||
+            if (Css.hasClass(target, "arrayLeftBracket") ||
                 Css.hasClass(target, "arrayRightBracket"))
             {
                 var tooltip = Locale.$STRF("console.multiHighlightLimitExceeded", [limit]);
@@ -695,61 +694,160 @@ FirebugReps.Arr = domplate(Firebug.Rep,
         Firebug.Inspector.highlightObject(arr, context);
     },
 
-    // http://code.google.com/p/fbug/issues/detail?id=874
-    // BEGIN Yahoo BSD Source (modified here)  YAHOO.lang.isArray, YUI 2.2.2 June 2007
-    isArray: function(obj, win)
+    isArray: function(obj)
     {
-        win = win || window;
+        return false;
+    }
+});
+
+// ********************************************************************************************* //
+
+FirebugReps.Arr = domplate(FirebugReps.ArrBase,
+{
+    tag:
+        OBJECTBOX({_repObject: "$object",
+            $hasTwisty: "$object|hasSpecialProperties",
+            onclick: "$onToggleProperties"},
+            SPAN({"class": "arrayLeftBracket", role: "presentation"}, "["),
+            FOR("item", "$object|longArrayIterator",
+                TAG("$item.tag", {object: "$item.object"}),
+                SPAN({"class": "arrayComma", role: "presentation"}, "$item.delim")
+            ),
+            SPAN({"class": "arrayRightBracket", role: "presentation"}, "]"),
+            SPAN({"class": "arrayProperties", role: "group"})
+        ),
 
-        var view = Wrapper.getContentView(win);
+    shortTag:
+        OBJECTBOX({_repObject: "$object",
+            $hasTwisty: "$object|hasSpecialProperties",
+            onclick: "$onToggleProperties"},
+            SPAN({"class": "arrayLeftBracket", role: "presentation"}, "["),
+            FOR("item", "$object|shortArrayIterator",
+                TAG("$item.tag", {object: "$item.object"}),
+                SPAN({"class": "arrayComma", role: "presentation"}, "$item.delim")
+            ),
+            SPAN({"class": "arrayRightBracket"}, "]"),
+            SPAN({"class": "arrayProperties", role: "group"})
+        ),
 
+    // http://code.google.com/p/fbug/issues/detail?id=874
+    isArray: function(obj)
+    {
         try
         {
-            if (!obj)
-                return false;
-            // do this first to avoid security 1000 errors
-            else if (obj instanceof Ci.nsIDOMHistory)
-                return false;
-            // do this first to avoid security 1000 errors
-            else if ("StorageList" in view && obj instanceof view.StorageList)
-                return false;
-            // do this first to avoid exceptions
-            else if (obj.toString() === "[xpconnect wrapped native prototype]")
-                return false;
-            else if (isFinite(obj.length) && typeof obj.splice === "function")
+            if (Arr.isArray(obj))
                 return true;
             else if (isFinite(obj.length) && typeof obj.callee === "function") // arguments
                 return true;
-            else if (obj instanceof view.HTMLCollection)
-                return true;
-            else if (obj instanceof view.NodeList)
-                return true;
         }
-        catch (exc)
-        {
-            try
-            {
-                if (FBTrace.DBG_ERRORS)
-                {
-                    // Something weird: without the try/catch, OOM, with no exception??
-                    FBTrace.sysout("isArray FAILS: " + exc, exc);
-                    FBTrace.sysout("isArray Fails on obj " + obj);
-                }
-            }
-            catch (exexc)
-            {
-                FBTrace.sysout("isArray double ERROR " + exexc, exexc);
-            }
-        }
-
+        catch (exc) {}
         return false;
+    }
+});
+
+// ********************************************************************************************* //
+
+/**
+ * Any arrayish object that is not directly Array type (e.g. HTMLCollection, NodeList, etc.)
+ */
+FirebugReps.ArrayLikeObject = domplate(FirebugReps.ArrBase,
+{
+    tag:
+        OBJECTBOX({_repObject: "$object",
+            $hasTwisty: "$object|hasSpecialProperties",
+            onclick: "$onToggleProperties"},
+            A({"class": "objectTitle objectLink", onclick: "$onClickTitle"},
+                "$object|getTitle"
+            ),
+            SPAN({"class": "arrayLeftBracket", role: "presentation"}, "["),
+            FOR("item", "$object|longArrayIterator",
+                TAG("$item.tag", {object: "$item.object"}),
+                SPAN({"class": "arrayComma", role: "presentation"}, "$item.delim")
+            ),
+            SPAN({"class": "arrayRightBracket", role: "presentation"}, "]"),
+            SPAN({"class": "arrayProperties", role: "group"})
+        ),
+
+    shortTag:
+        OBJECTBOX({_repObject: "$object",
+            $hasTwisty: "$object|hasSpecialProperties",
+            onclick: "$onToggleProperties"},
+            A({"class": "objectTitle objectLink", onclick: "$onClickTitle"},
+                "$object|getTitle"
+            ),
+            SPAN({"class": "arrayLeftBracket", role: "presentation"}, "["),
+            FOR("item", "$object|shortArrayIterator",
+                TAG("$item.tag", {object: "$item.object"}),
+                SPAN({"class": "arrayComma", role: "presentation"}, "$item.delim")
+            ),
+            SPAN({"class": "arrayRightBracket"}, "]"),
+            SPAN({"class": "arrayProperties", role: "group"})
+        ),
+
+    onClickTitle: function(event)
+    {
+        var obj = Firebug.getRepObject(event.target);
+        Firebug.chrome.select(obj);
     },
-    // END Yahoo BSD SOURCE See license below.
 
-    getTitle: function(object, context)
+    getTitle: function(obj, context)
     {
-        return "[" + object.length + "]";
-    }
+        var arr = Wrapper.unwrapObject(obj);
+        const re =/\[object ([^\]]*)/;
+        var label = Str.safeToString(arr);
+        var m = re.exec(label);
+        if (m)
+            return m[1] || label;
+
+        if ((arr instanceof Ci.nsIDOMDOMTokenList) || (this.isTokenList_Fx19(obj)))
+            return "DOMTokenList";
+
+        return "";
+    },
+
+    isArray: function(obj)
+    {
+        if (this.isArrayLike_Fx19(obj))
+            return true;
+
+        return Arr.isArrayLike(obj);
+    },
+
+    /**
+     * Hack for Firefox 19 where obj instanceof Ci.nsIDOMDOMTokenList doesn't work.
+     */
+    isTokenList_Fx19: function(obj)
+    {
+        var context = Firebug.currentContext;
+        if (!context)
+            return false;
+
+        var view = Wrapper.getContentView(context.window);
+        if (!view)
+            return false;
+
+        obj = Wrapper.unwrapObject(obj);
+        return (obj instanceof view.DOMTokenList);
+    },
+
+    /**
+     * Hack for Firefox 19 where obj instanceof Ci.nsIDOMDOMTokenList,
+     * Ci.nsIDOMHTMLCollection and nsIDOMNodeList doesn't work.
+     */
+    isArrayLike_Fx19: function(obj)
+    {
+        var context = Firebug.currentContext;
+        if (!context)
+            return false;
+
+        var view = Wrapper.getContentView(context.window);
+        if (!view)
+            return false;
+
+        obj = Wrapper.unwrapObject(obj);
+        return (obj instanceof view.DOMTokenList) || (obj instanceof view.HTMLCollection) ||
+            (obj instanceof view.NodeList);
+    },
 });
 
 // ********************************************************************************************* //
@@ -910,14 +1008,12 @@ FirebugReps.Element = domplate(Firebug.Rep,
     {
         try
         {
-            return elt.getAttribute("class")
-                ? ("." + elt.getAttribute("class").split(" ")[0])
-                : "";
+            return elt.classList.length > 0 ? ("." + elt.classList[0]) : "";
         }
         catch (err)
         {
+            return "";
         }
-        return "";
     },
 
     getValue: function(elt)
@@ -1054,6 +1150,57 @@ FirebugReps.Element = domplate(Firebug.Rep,
         System.copyToClipboard(csspath);
     },
 
+    paste: function(elt, clipboardContent, mode)
+    {
+        if (elt instanceof window.HTMLElement)
+            return this.pasteHTML.apply(this, arguments);
+        else
+            return this.pasteXML.apply(this, arguments);
+    },
+
+    pasteHTML: function(elt, clipboardContent, mode)
+    {
+        if (mode === "replaceInner")
+            elt.innerHTML = clipboardContent;
+        else if (mode === "replaceOuter")
+            elt.outerHTML = clipboardContent;
+        else
+            elt.insertAdjacentHTML(mode, clipboardContent);
+    },
+
+    pasteXML: function(elt, clipboardContent, mode)
+    {
+        var contextNode, parentNode = elt.parentNode;
+        if (["beforeBegin", "afterEnd", "replaceOuter"].indexOf(mode) >= 0)
+            contextNode = parentNode;
+        else
+            contextNode = elt;
+
+        var pastedElements = Dom.markupToDocFragment(clipboardContent, contextNode);
+        switch (mode)
+        {
+            case "beforeBegin":
+                parentNode.insertBefore(pastedElements, elt);
+                break;
+            case "afterBegin":
+                elt.insertBefore(pastedElements, elt.firstChild);
+                break;
+            case "beforeEnd":
+                elt.appendChild(pastedElements);
+                break;
+            case "afterEnd":
+                Dom.insertAfter(pastedElements, elt);
+                break;
+            case "replaceInner":
+                Dom.eraseNode(elt);
+                elt.appendChild(pastedElements);
+                break;
+            case "replaceOuter":
+                parentNode.replaceChild(pastedElements, elt);
+                break;
+        }
+    },
+
     persistor: function(context, xpath)
     {
         var elts = xpath
@@ -1111,9 +1258,14 @@ FirebugReps.Element = domplate(Firebug.Rep,
 
     getContextMenuItems: function(elt, target, context)
     {
+        // XXX: Temporary fix for issue 5577.
+        if (Dom.getAncestorByClass(target, "cssElementRuleContainer"))
+            return;
+
         var type;
-        var monitored = EventMonitor.areEventsMonitored(elt, null, context);
         var items = [];
+        var clipboardContent = System.getStringDataFromClipboard();
+        var isEltRoot = (elt === elt.ownerDocument.documentElement);
 
         if (Xml.isElementHTML(elt) || Xml.isElementXHTML(elt))
             type = "HTML";
@@ -1155,6 +1307,57 @@ FirebugReps.Element = domplate(Firebug.Rep,
                 tooltiptext: "html.tip.Copy_CSS_Path",
                 id: "fbCopyCSSPath",
                 command: Obj.bindFixed(this.copyCSSPath, this, elt)
+            },
+            {
+                label: Locale.$STRF("html.menu.Paste", [type]),
+                tooltiptext: Locale.$STRF("html.tip.Paste", [type]),
+                disabled: !clipboardContent,
+                id: "fbPaste",
+                items: [
+                    {
+                        label: "html.menu.Paste_Replace_Content",
+                        tooltiptext: "html.tip.Paste_Replace_Content",
+                        id: "fbPasteReplaceInner",
+                        command: Obj.bindFixed(this.paste, this, elt, clipboardContent, 
+                            "replaceInner")
+                    },
+                    {
+                        label: "html.menu.Paste_Replace_Node",
+                        tooltiptext: "html.tip.Paste_Replace_Node",
+                        id: "fbPasteReplaceOuter",
+                        disabled: isEltRoot,
+                        command: Obj.bindFixed(this.paste, this, elt, clipboardContent, 
+                            "replaceOuter")
+                    },
+                    {
+                        label: "html.menu.Paste_AsFirstChild",
+                        tooltiptext: "html.tip.Paste_AsFirstChild",
+                        id: "fbPasteFirstChild",
+                        command: Obj.bindFixed(this.paste, this, elt, clipboardContent,
+                            "afterBegin")
+                    },
+                    {
+                        label: "html.menu.Paste_AsLastChild",
+                        tooltiptext: "html.tip.Paste_AsLastChild",
+                        id: "fbPasteLastChild",
+                        command: Obj.bindFixed(this.paste, this, elt, clipboardContent, "beforeEnd")
+                    },
+                    {
+                        label: "html.menu.Paste_Before",
+                        tooltiptext: "html.tip.Paste_Before",
+                        id: "fbPasteBefore",
+                        disabled: isEltRoot,
+                        command: Obj.bindFixed(this.paste, this, elt, clipboardContent,
+                            "beforeBegin")
+                    },
+                    {
+                        label: "html.menu.Paste_After",
+                        tooltiptext: "html.tip.Paste_After",
+                        id: "fbPasteAfter",
+                        disabled: isEltRoot,
+                        command: Obj.bindFixed(this.paste, this, elt, clipboardContent, "afterEnd")
+                    }
+                ]
             }
         ]);
 
@@ -1178,9 +1381,12 @@ FirebugReps.Element = domplate(Firebug.Rep,
                 tooltiptext: "html.tip.Show_Events_In_Console",
                 id: "fbShowEventsInConsole",
                 type: "checkbox",
-                checked: monitored,
-                command: Obj.bindFixed(EventMonitor.toggleMonitorEvents,
-                    EventMonitor, elt, null, monitored, context)
+                checked: EventMonitor.areEventsMonitored(elt, null, context),
+                command: function()
+                {
+                    var checked = this.hasAttribute("checked");
+                    EventMonitor.toggleMonitorEvents(elt, null, !checked, context);
+                }
             },
             "-",
             {
@@ -1239,7 +1445,6 @@ FirebugReps.TextNode = domplate(Firebug.Rep,
 
 // ********************************************************************************************* //
 
-var regexpConstructorRE = /RegExp/;
 FirebugReps.RegExp = domplate(Firebug.Rep,
 {
     tag:
@@ -1255,8 +1460,7 @@ FirebugReps.RegExp = domplate(Firebug.Rep,
     {
         try
         {
-            return type == "object" && object && object.constructor && object.constructor.toString &&
-                regexpConstructorRE.test(object.constructor.toString());
+            return type == "object" && Object.prototype.toString.call(object) === "[object RegExp]";
         }
         catch (err)
         {
@@ -1591,20 +1795,29 @@ FirebugReps.Window = domplate(Firebug.Rep,
 
 FirebugReps.Event = domplate(Firebug.Rep,
 {
-    tag: TAG("$copyEventTag", {object: "$object|copyEvent"}),
+    className: "event",
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+    tag:
+        TAG("$copyEventTag", {object: "$object|copyEvent"}),
 
     copyEventTag:
         OBJECTLINK("$object|summarizeEvent"),
 
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
     summarizeEvent: function(event)
     {
-        var info = [event.type, ' '];
+        var info = [event.type, " "];
 
         var eventFamily = Events.getEventFamily(event.type);
         if (eventFamily == "mouse")
             info.push("clientX=", event.clientX, ", clientY=", event.clientY);
         else if (eventFamily == "key")
             info.push("charCode=", event.charCode, ", keyCode=", event.keyCode);
+        else if (event.type == "message")
+            info.push("origin=", event.origin, ", data=", event.data);
 
         return info.join("");
     },
@@ -1616,8 +1829,6 @@ FirebugReps.Event = domplate(Firebug.Rep,
 
     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
-    className: "object",
-
     supportsObject: function(object, type)
     {
         return object instanceof window.Event || object instanceof Dom.EventCopy;
@@ -1631,6 +1842,52 @@ FirebugReps.Event = domplate(Firebug.Rep,
 
 // ********************************************************************************************* //
 
+FirebugReps.EventLog = domplate(FirebugReps.Event,
+{
+    className: "eventLog",
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+    tag:
+        TAG("$copyEventTag", {object: "$object|copyEvent"}),
+
+    copyEventTag:
+        SPAN(
+            OBJECTLINK("$object|summarizeEvent"),
+            SPAN("&nbsp"),
+            SPAN("»"),
+            SPAN("&nbsp"),
+            TAG("$object|getTargetTag", {object: "$object|getTarget"})
+        ),
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+    copyEvent: function(log)
+    {
+        return new Dom.EventCopy(log.event);
+    },
+
+    getTarget: function(event)
+    {
+        return event.target;
+    },
+
+    getTargetTag: function(event)
+    {
+        var rep = Firebug.getRep(event.target);
+        return rep.shortTag ? rep.shortTag : rep.tag;
+    },
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+    supportsObject: function(object, type)
+    {
+        return object instanceof EventMonitor.EventLog;
+    },
+});
+
+// ********************************************************************************************* //
+
 FirebugReps.SourceLink = domplate(Firebug.Rep,
 {
     tag:
@@ -2289,12 +2546,13 @@ FirebugReps.ErrorMessage = domplate(Firebug.Rep,
         // so let's try to skip those
         if (error.source)
             return "syntax";
-        else if (error.lineNo == 1 && Url.getFileExtension(error.href) != "js")
-            return "none";
         else if (error.category == "css")
             return "show";
         else if (!error.href || !error.lineNo)
             return "none";
+        // Why do we have that at all?
+        else if (error.lineNo == 1 && Url.getFileExtension(error.href) != "js")
+            return "none";
         else
             return "show";
     },
@@ -2573,9 +2831,9 @@ FirebugReps.nsIDOMHistory = domplate(Firebug.Rep,
         try
         {
             var items = history.length;
-            return items + " history entries";
+            return Locale.$STRP("firebug.reps.historyEntries", [items]);
         }
-        catch(exc)
+        catch (exc)
         {
             return "object does not support history (nsIDOMHistory)";
         }
@@ -2586,7 +2844,7 @@ FirebugReps.nsIDOMHistory = domplate(Firebug.Rep,
         try
         {
             var history = event.currentTarget.repObject;
-            var items = history.length;  // if this throws, then unsupported
+            history.length;  // if this throws, then unsupported
             Firebug.chrome.select(history);
         }
         catch (exc)
@@ -2759,112 +3017,6 @@ FirebugReps.Storage = domplate(Firebug.Rep,
 
 // ********************************************************************************************* //
 
-FirebugReps.StorageList = domplate(Firebug.Rep,
-{
-    tag:
-        OBJECTLINK(
-            SPAN({"class": "storageTitle"}, "$object|summarize "),
-            FOR("prop", "$object|longPropIterator",
-                "$prop.name",
-                SPAN({"class": "objectEqual", role: "presentation"}, "$prop.equal"),
-                TAG("$prop.tag", {object: "$prop.object"}),
-                SPAN({"class": "objectComma", role: "presentation"}, "$prop.delim")
-            )
-        ),
-
-    shortTag:
-        OBJECTLINK({onclick: "$onClick"},
-            SPAN({"class": "storageTitle"}, "$object|summarize "),
-            FOR("prop", "$object|shortPropIterator",
-                "$prop.name",
-                SPAN({"class": "objectEqual", role: "presentation"}, "$prop.equal"),
-                TAG("$prop.tag", {object: "$prop.object"}),
-                SPAN({"class": "objectComma", role: "presentation"}, "$prop.delim")
-            )
-        ),
-
-    onClick: function(event)
-    {
-        var globalStorage = event.currentTarget.repObject;
-        var context = Firebug.currentContext;
-        var domain = context.window.location.hostname;
-
-        Firebug.chrome.select(globalStorage.namedItem(domain));
-        Events.cancelEvent(event);
-    },
-
-    summarize: function(globalStorage)
-    {
-        try
-        {
-            var context = Firebug.currentContext;
-            var domain = context.window.location.hostname;
-            var length = globalStorage.namedItem(domain).length;
-            return Locale.$STRP("firebug.storage.totalItems", [length]) + " ";
-        }
-        catch (e)
-        {
-            if (FBTrace.DBG_ERRORS)
-                FBTrace.sysout("reps.StorageList.summarize; EXCEPTION " + e, e);
-        }
-        return "";
-    },
-
-    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-    className: "StorageList",
-
-    supportsObject: function(object, type)
-    {
-        return ("StorageList" in window && object instanceof window.StorageList);
-    },
-
-    getRealObject: function(object, context)
-    {
-        try
-        {
-            var domain = context.window.location.hostname;
-            return globalStorage.namedItem(domain);
-        }
-        catch (e)
-        {
-            if (FBTrace.DBG_ERRORS)
-                FBTrace.sysout("reps.StorageList.getRealObject; EXCEPTION " + e, e);
-        }
-    },
-
-    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-    // Iterator
-
-    longPropIterator: function(object)
-    {
-        return this.propIterator(object, 100);
-    },
-
-    shortPropIterator: function(object)
-    {
-        return this.propIterator(object, Options.get("ObjectShortIteratorMax"));
-    },
-
-    propIterator: function(object, max)
-    {
-        try
-        {
-            var context = Firebug.currentContext;
-            var domain = context.window.location.hostname;
-            return FirebugReps.Storage.propIterator(object.namedItem(domain), max);
-        }
-        catch (e)
-        {
-            if (FBTrace.DBG_ERRORS)
-                FBTrace.sysout("reps.StorageList.propIterator; EXCEPTION " + e, e);
-        }
-        return [];
-    },
-});
-
-// ********************************************************************************************* //
-
 FirebugReps.XPathResult = domplate(FirebugReps.Arr,
 {
     className: "array xPathResult",
@@ -3034,7 +3186,7 @@ FirebugReps.NamedNodeMap = domplate(Firebug.Rep,
         ),
 
     shortTag:
-        OBJECTLINK({onclick: "$onClick"},
+        OBJECTLINK(
             SPAN({"class": "arrayLeftBracket", role: "presentation"}, "["),
             FOR("prop", "$object|shortPropIterator",
                 SPAN({"class": "nodeName"}, "$prop.name"),
@@ -3045,16 +3197,6 @@ FirebugReps.NamedNodeMap = domplate(Firebug.Rep,
             SPAN({"class": "arrayRightBracket", role: "presentation"}, "]")
         ),
 
-    onClick: function(event)
-    {
-        var globalStorage = event.currentTarget.repObject;
-        var context = Firebug.currentContext;
-        var domain = context.window.location.hostname;
-
-        Firebug.chrome.select(globalStorage.namedItem(domain));
-        Events.cancelEvent(event);
-    },
-
     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
     className: "NamedNodeMap",
@@ -3181,14 +3323,14 @@ FirebugReps.ErrorCopy = function(message)
 // Registration
 
 Firebug.registerRep(
-    FirebugReps.nsIDOMHistory, // make this early to avoid exceptions
     FirebugReps.Undefined,
     FirebugReps.Null,
     FirebugReps.Number,
-    FirebugReps.RegExp,
     FirebugReps.String,
+    FirebugReps.nsIDOMHistory, // make this early to avoid exceptions
+    FirebugReps.ApplicationCache, // this also
+    FirebugReps.RegExp,
     FirebugReps.Window,
-    FirebugReps.ApplicationCache, // must come before Arr (array) else exceptions.
     FirebugReps.ErrorMessage,
     FirebugReps.Element,
     FirebugReps.TextNode,
@@ -3205,13 +3347,14 @@ Firebug.registerRep(
     FirebugReps.Except,
     FirebugReps.XML,
     FirebugReps.Arr,
+    FirebugReps.ArrayLikeObject,
     FirebugReps.XPathResult,
     FirebugReps.Storage,
-    FirebugReps.StorageList,
     FirebugReps.Attr,
     FirebugReps.Date,
     FirebugReps.NamedNodeMap,
-    FirebugReps.Reference
+    FirebugReps.Reference,
+    FirebugReps.EventLog
 );
 
 Firebug.setDefaultReps(FirebugReps.Func, FirebugReps.Obj);
@@ -3220,43 +3363,3 @@ return Firebug.Reps = FirebugReps;
 
 // ********************************************************************************************* //
 }});
-
-// ********************************************************************************************* //
-
-/*
- * The following is http://developer.yahoo.com/yui/license.txt and applies to only code labeled
- * "Yahoo BSD Source" in only this file reps.js.  John J. Barton June 2007.
- *
-Software License Agreement (BSD License)
-
-Copyright (c) 2006, Yahoo! Inc.
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms, with or without modification, are
-permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of Yahoo! Inc. nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of Yahoo! Inc.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
-TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-// ********************************************************************************************* //
diff --git a/trace/FBTrace/chrome/firebug/content/chrome/tabContext.js b/trace/FBTrace/chrome/firebug/content/chrome/tabContext.js
index ea334f6..4ca0aa9 100644
--- a/trace/FBTrace/chrome/firebug/content/chrome/tabContext.js
+++ b/trace/FBTrace/chrome/firebug/content/chrome/tabContext.js
@@ -215,7 +215,7 @@ Firebug.TabContext.prototype =
         // to iframes (documents), which can be already unloaded at this point.
         // Removing listeners from such 'unloaded' documents (or window) can throw
         // "TypeError: can't access dead object"
-        // We should avoid these exceptions (event if they are not representing mem leaks)
+        // We should avoid these exceptions (even if they are not representing memory leaks)
         this.unregisterAllListeners();
 
         state.panelState = {};
@@ -350,7 +350,7 @@ Firebug.TabContext.prototype =
         catch (exc)
         {
             if (FBTrace.DBG_ERRORS)
-                FBTrace.sysout("tabContext.destroy FAILS "+exc, exc);
+                FBTrace.sysout("tabContext.destroy FAILS (" + panelName + ") " + exc, exc);
 
             // the destroy failed, don't keep the bad state
             delete state.panelState[panelName];
diff --git a/trace/FBTrace/chrome/firebug/content/chrome/tabWatcher.js b/trace/FBTrace/chrome/firebug/content/chrome/tabWatcher.js
index f08513a..5103f10 100644
--- a/trace/FBTrace/chrome/firebug/content/chrome/tabWatcher.js
+++ b/trace/FBTrace/chrome/firebug/content/chrome/tabWatcher.js
@@ -99,7 +99,16 @@ Firebug.TabWatcher = Obj.extend(new Firebug.Listener(),
         var tabBrowser = Firefox.getElementById("content");
         if (tabBrowser)
         {
-            tabBrowser.removeProgressListener(TabProgressListener);
+            try
+            {
+                // Exception thrown: tabBrowser.removeProgressListener is not a function
+                // when Firebug is in detached state and the origin browser window is closed.
+                tabBrowser.removeProgressListener(TabProgressListener);
+            }
+            catch (e)
+            {
+                FBTrace.sysout("tabWatcher.destroy; EXCEPTION " + e, e);
+            }
 
             var browsers = Firefox.getBrowsers();
             for (var i = 0; i < browsers.length; ++i)
diff --git a/trace/FBTrace/chrome/firebug/content/chrome/tableRep.js b/trace/FBTrace/chrome/firebug/content/chrome/tableRep.js
index eb230f0..aad5f43 100644
--- a/trace/FBTrace/chrome/firebug/content/chrome/tableRep.js
+++ b/trace/FBTrace/chrome/firebug/content/chrome/tableRep.js
@@ -19,10 +19,10 @@ with (Domplate) {
 FirebugReps.Table = domplate(Firebug.Rep,
 {
     className: "table",
-
+    tableClassName: "dataTable",
     tag:
         DIV({"class": "dataTableSizer", "tabindex": "-1" },
-            TABLE({"class": "dataTable", cellspacing: 0, cellpadding: 0, width: "100%",
+            TABLE({"class": "$tableClassName", cellspacing: 0, cellpadding: 0, width: "100%",
                 "role": "grid"},
                 THEAD({"class": "dataTableThead", "role": "presentation"},
                     TR({"class": "headerRow focusRow dataTableRow subFocusRow", "role": "row",
@@ -194,7 +194,7 @@ FirebugReps.Table = domplate(Firebug.Rep,
     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
     // Console logging
 
-    log: function(data, cols, context)
+    log: function(data, cols, context, object)
     {
         // No arguments passed into console.table method, bail out for now,
         // but some error message could be displayed in the future.
@@ -211,7 +211,12 @@ FirebugReps.Table = domplate(Firebug.Rep,
         try
         {
             this.columns = columns;
-            var row = Firebug.Console.log({data: data, columns: columns}, context, "table", this, true);
+
+            var object = object || {};
+            object.data = data;
+            object.columns = columns;
+
+            var row = Firebug.Console.log(object, context, "table", this, true);
 
             // Set vertical height for scroll bar.
             var tBody = row.querySelector(".dataTableTbody");
diff --git a/trace/FBTrace/chrome/firebug/content/chrome/window.js b/trace/FBTrace/chrome/firebug/content/chrome/window.js
index 5759451..1a97330 100644
--- a/trace/FBTrace/chrome/firebug/content/chrome/window.js
+++ b/trace/FBTrace/chrome/firebug/content/chrome/window.js
@@ -101,9 +101,17 @@ Win.getRootWindow = function(win)
 {
     for (; win; win = win.parent)
     {
-        if (!win.parent || win == win.parent || !(win.parent instanceof win.Window) )
+        if (!win.parent || win == win.parent)
+            return win;
+
+        // When checking the 'win.parent' type we need to use the target
+        // type from the same scope. i.e. from win.parent
+        // Iframes from different domains can use different Window type than
+        // the top level window.
+        if (!(win.parent instanceof win.parent.Window))
             return win;
     }
+
     return null;
 };
 
diff --git a/trace/FBTrace/chrome/firebug/content/console/autoCompleter.js b/trace/FBTrace/chrome/firebug/content/console/autoCompleter.js
index 225feec..2a23b88 100644
--- a/trace/FBTrace/chrome/firebug/content/console/autoCompleter.js
+++ b/trace/FBTrace/chrome/firebug/content/console/autoCompleter.js
@@ -4,7 +4,6 @@ define([
     "firebug/lib/object",
     "firebug/firebug",
     "firebug/lib/domplate",
-    "firebug/chrome/reps",
     "firebug/lib/locale",
     "firebug/lib/events",
     "firebug/lib/wrapper",
@@ -13,14 +12,11 @@ define([
     "firebug/lib/array",
     "firebug/editor/editor"
 ],
-function(Obj, Firebug, Domplate, FirebugReps, Locale, Events, Wrapper, Dom, Str, Arr, Editor) {
+function(Obj, Firebug, Domplate, Locale, Events, Wrapper, Dom, Str, Arr, Editor) {
 
 // ********************************************************************************************* //
 // Constants
 
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-
 const kwActions = ["throw", "return", "in", "instanceof", "delete", "new",
                    "typeof", "void", "yield"];
 const reOpenBracket = /[\[\(\{]/;
@@ -28,6 +24,8 @@ const reCloseBracket = /[\]\)\}]/;
 const reJSChar = /[a-zA-Z0-9$_]/;
 const reLiteralExpr = /^[ "0-9,]*$/;
 
+var measureCache = {};
+
 // ********************************************************************************************* //
 // JavaScript auto-completion
 
@@ -44,7 +42,9 @@ Firebug.JSAutoCompleter = function(textBox, completionBox, options)
     this.completionBase = {
         pre: null,
         expr: null,
-        candidates: []
+        forceShowPopup: false,
+        candidates: [],
+        hiddenCandidates: []
     };
     this.completions = null;
 
@@ -79,7 +79,9 @@ Firebug.JSAutoCompleter = function(textBox, completionBox, options)
         this.completionBase = {
             pre: null,
             expr: null,
-            candidates: []
+            forceShowPopup: false,
+            candidates: [],
+            hiddenCandidates: []
         };
         this.completions = null;
 
@@ -94,6 +96,7 @@ Firebug.JSAutoCompleter = function(textBox, completionBox, options)
     this.hideForExpression = function()
     {
         this.completionBase.candidates = [];
+        this.completionBase.hiddenCandidates = [];
         this.completions = null;
 
         this.showCompletions(false);
@@ -183,14 +186,17 @@ Firebug.JSAutoCompleter = function(textBox, completionBox, options)
         var prevCompletions = this.completions;
 
         // We only need to calculate a new candidate list if the expression has
-        // changed (we can ignore this.completionBase.pre since completions do not
+        // changed (we can ignore completionBase.pre since completions do not
         // depend upon that).
         if (preExpr !== this.completionBase.expr)
         {
             this.completionBase.expr = preExpr;
-            this.completionBase.candidates = autoCompleteEval(context, preExpr, spreExpr,
+            var ev = autoCompleteEval(context, preExpr, spreExpr,
                 this.options.includeCurrentScope);
             prevCompletions = null;
+            this.completionBase.candidates = ev.completions;
+            this.completionBase.hiddenCandidates = ev.hiddenCompletions;
+            this.completionBase.forceShowPopup = false;
         }
 
         this.createCompletions(prop, prevCompletions);
@@ -205,41 +211,60 @@ Firebug.JSAutoCompleter = function(textBox, completionBox, options)
      */
     this.createCompletions = function(prefix, prevCompletions)
     {
-        var candidates = this.completionBase.candidates;
-        var valid = [], ciValid = [];
-
         if (!this.completionBase.expr && !prefix)
         {
             // Don't complete "".
             this.completions = null;
             return;
         }
+        if (!this.completionBase.candidates.length && !prefix)
+        {
+            // Don't complete empty objects -> toString.
+            this.completions = null;
+            return;
+        }
 
+        var mustMatchFirstLetter = (this.completionBase.expr === "");
+        var clist = [
+            this.completionBase.candidates,
+            this.completionBase.hiddenCandidates
+        ], cind = 0;
+        var valid = [], ciValid = [];
         var lowPrefix = prefix.toLowerCase();
-        for (var i = 0; i < candidates.length; ++i)
+        while (ciValid.length === 0 && cind < 2)
         {
-            // Mark a candidate as matching if it matches the prefix case-
-            // insensitively, and shares its upper-case characters.
-            var name = candidates[i];
-            if (!Str.hasPrefix(name.toLowerCase(), lowPrefix))
-                continue;
-
-            var fail = false;
-            for (var j = 0; j < prefix.length; ++j)
+            var candidates = clist[cind];
+            for (var i = 0; i < candidates.length; ++i)
             {
-                var ch = prefix.charAt(j);
-                if (ch !== ch.toLowerCase() && ch !== name.charAt(j))
+                // Mark a candidate as matching if it matches the prefix case-
+                // insensitively, and shares its upper-case characters. The
+                // exception to this is that for global completions, the first
+                // character must match exactly (see issue 6030).
+                var name = candidates[i];
+                if (!Str.hasPrefix(name.toLowerCase(), lowPrefix))
+                    continue;
+
+                if (mustMatchFirstLetter && name.charAt(0) !== prefix.charAt(0))
+                    continue;
+
+                var fail = false;
+                for (var j = 0; j < prefix.length; ++j)
                 {
-                    fail = true;
-                    break;
+                    var ch = prefix.charAt(j);
+                    if (ch !== ch.toLowerCase() && ch !== name.charAt(j))
+                    {
+                        fail = true;
+                        break;
+                    }
+                }
+                if (!fail)
+                {
+                    ciValid.push(name);
+                    if (Str.hasPrefix(name, prefix))
+                        valid.push(name);
                 }
             }
-            if (!fail)
-            {
-                ciValid.push(name);
-                if (Str.hasPrefix(name, prefix))
-                    valid.push(name);
-            }
+            ++cind;
         }
 
         if (ciValid.length > 0)
@@ -250,18 +275,16 @@ Firebug.JSAutoCompleter = function(textBox, completionBox, options)
 
             this.completions = {
                 list: (hasMatchingCase ? valid : ciValid),
-                prefix: prefix
+                prefix: prefix,
+                hidePopup: (cind === 2)
             };
             this.completions.index = this.pickDefaultCandidate(prevCompletions);
 
             if (hasMatchingCase)
             {
                 var find = valid[this.completions.index];
-                this.completions = {
-                    list: ciValid,
-                    prefix: prefix,
-                    index: ciValid.indexOf(find)
-                };
+                this.completions.list = ciValid;
+                this.completions.index = ciValid.indexOf(find);
             }
         }
         else
@@ -290,11 +313,13 @@ Firebug.JSAutoCompleter = function(textBox, completionBox, options)
 
         // Special-case certain expressions.
         var special = {
-            "": ["document", "console", "window", "parseInt", "undefined"],
+            "": ["document", "console", "frames", "window", "parseInt", "undefined",
+                "Array", "Math", "Object", "String", "XMLHttpRequest", "Window"],
             "window.": ["console"],
             "location.": ["href"],
             "document.": ["getElementById", "addEventListener", "createElement",
-                "documentElement"]
+                "documentElement"],
+            "Object.prototype.toString": ["call"]
         };
         if (special.hasOwnProperty(this.completionBase.expr))
         {
@@ -312,12 +337,32 @@ Firebug.JSAutoCompleter = function(textBox, completionBox, options)
             }
         }
 
+        // 'prototype' is a good default if it exists.
+        ind = list.indexOf("prototype");
+        if (ind !== -1)
+            return ind;
+
         ind = 0;
         for (var i = 1; i < list.length; ++i)
         {
             if (list[i].length < list[ind].length)
                 ind = i;
         }
+
+        // Avoid some completions in favor of others.
+        var replacements = {
+            "toSource": "toString",
+            "toFixed": "toString",
+            "watch": "toString",
+            "pattern": "parentNode"
+        };
+        if (replacements.hasOwnProperty(list[ind]))
+        {
+            var ind2 = list.indexOf(replacements[list[ind]]);
+            if (ind2 !== -1)
+                return ind2;
+        }
+
         return ind;
     };
 
@@ -378,12 +423,16 @@ Firebug.JSAutoCompleter = function(textBox, completionBox, options)
     {
         this.completionBox.value = this.getCompletionBoxValue();
 
-        var show = this.showCompletionPopup ||
-            (this.completionPopup && this.completionPopup.state === "open");
-        if (show && this.completions && this.completions.list.length > 1)
+        if (this.completions && (this.completionBase.forceShowPopup ||
+            (this.completions.list.length > 1 && this.showCompletionPopup &&
+             !this.completions.hidePopup)))
+        {
             this.popupCandidates(cycling);
+        }
         else
+        {
             this.closePopup();
+        }
     };
 
     /**
@@ -498,20 +547,24 @@ Firebug.JSAutoCompleter = function(textBox, completionBox, options)
             // does not close itself and prevent event propagation on keypress.
             // (Unless the popup is only open due to Ctrl+Space, in which case
             // that's precisely what we want.)
-            if (this.showCompletionPopup)
+            if (!this.forceShowPopup)
                 this.closePopup();
         }
         else if (event.keyCode === KeyEvent.DOM_VK_SPACE && Events.isControl(event))
         {
-            // Force-show the completion popup.
             if (!this.completions)
             {
                 // If completions have been hidden, show them again.
                 this.hide();
                 this.complete(context);
             }
-            if (this.completionPopup && this.completions)
+
+            if (this.completions && !this.isPopupOpen())
+            {
+                // Force-show the completion popup.
+                this.completionBase.forceShowPopup = true;
                 this.popupCandidates(false);
+            }
         }
     };
 
@@ -640,12 +693,12 @@ Firebug.JSAutoCompleter = function(textBox, completionBox, options)
         this.selectedPopupElement = null;
 
         var vbox = this.completionPopup.ownerDocument.createElement("vbox");
-        this.completionPopup.appendChild(vbox);
         vbox.classList.add("fbCommandLineCompletions");
+        this.completionPopup.appendChild(vbox);
 
         var title = this.completionPopup.ownerDocument.
-            createElementNS("http://www.w3.org/1999/xhtml","div");
-        title.innerHTML = Locale.$STR("console.Use Arrow keys, Tab or Enter");
+            createElementNS("http://www.w3.org/1999/xhtml", "div");
+        title.textContent = Locale.$STR("console.Use Arrow keys, Tab or Enter");
         title.classList.add("fbPopupTitle");
         vbox.appendChild(title);
 
@@ -696,25 +749,23 @@ Firebug.JSAutoCompleter = function(textBox, completionBox, options)
 
         for (var i = this.popupTop; i < this.popupBottom; i++)
         {
-            var completion = list[i];
             var prefixLen = this.completions.prefix.length;
+            var completion = list[i];
 
             var hbox = this.completionPopup.ownerDocument.
-                createElementNS("http://www.w3.org/1999/xhtml","div");
+                createElementNS("http://www.w3.org/1999/xhtml", "div");
             hbox.completionIndex = i;
 
             var pre = this.completionPopup.ownerDocument.
-                createElementNS("http://www.w3.org/1999/xhtml","span");
-            var preText = this.textBox.value;
-            if (prefixLen)
-                preText = preText.slice(0, -prefixLen) + completion.slice(0, prefixLen);
-            pre.innerHTML = Str.escapeForTextNode(preText);
+                createElementNS("http://www.w3.org/1999/xhtml", "span");
+            var preText = this.completionBase.expr + completion.substr(0, prefixLen);
+            pre.textContent = preText;
             pre.classList.add("userTypedText");
 
             var post = this.completionPopup.ownerDocument.
-                createElementNS("http://www.w3.org/1999/xhtml","span");
+                createElementNS("http://www.w3.org/1999/xhtml", "span");
             var postText = completion.substr(prefixLen);
-            post.innerHTML = Str.escapeForTextNode(postText);
+            post.textContent = postText;
             post.classList.add("completionText");
 
             if (i === selIndex)
@@ -728,7 +779,24 @@ Firebug.JSAutoCompleter = function(textBox, completionBox, options)
         if (this.selectedPopupElement)
             this.selectedPopupElement.setAttribute("selected", "true");
 
-        this.completionPopup.openPopup(this.textBox, "before_start", 0, 0, false, false);
+        // Open the popup at the pixel position of the start of the completed
+        // expression. The text length times the width of a single character,
+        // plus apparent padding, is a good enough approximation of this.
+        var chWidth = this.getCharWidth(this.completionBase.pre);
+        var offsetX = Math.round(this.completionBase.pre.length * chWidth) + 2;
+        this.completionPopup.openPopup(this.textBox, "before_start", offsetX, 0, false, false);
+    };
+
+    this.getCharWidth = function(text)
+    {
+        var size = Firebug.textSize;
+        if (!measureCache[size])
+        {
+            var measurer = this.options.popupMeasurer;
+            measurer.style.fontSizeAdjust = this.textBox.style.fontSizeAdjust;
+            measureCache[size] = measurer.offsetWidth / 60;
+        }
+        return measureCache[size];
     };
 
     this.isPopupOpen = function()
@@ -825,25 +893,6 @@ Firebug.JSAutoCompleter = function(textBox, completionBox, options)
 // ********************************************************************************************* //
 
 /**
- * A dummy auto-completer, set as current by CommandLine.setAutoCompleter when
- * no completion is supposed to be done (such as in the large command line,
- * currently, or when there is no context).
- */
-Firebug.EmptyJSAutoCompleter = function()
-{
-    this.empty = true;
-    this.shutdown = function() {};
-    this.hide = function() {};
-    this.complete = function() {};
-    this.acceptReturn = function() { return true; };
-    this.revert = function() { return false; };
-    this.handleKeyDown = function() {};
-    this.handleKeyPress = function() {};
-};
-
-// ********************************************************************************************* //
-
-/**
  * An (abstract) editor with simple JavaScript auto-completion.
  */
 Firebug.JSEditor = function()
@@ -1271,8 +1320,7 @@ function killCompletions(expr, origExpr)
 }
 
 // Types the autocompletion knows about, some of their non-enumerable properties,
-// and the return types of some member functions, included in the Firebug.CommandLine
-// object to make it more easily extensible.
+// and the return types of some member functions.
 
 var AutoCompletionKnownTypes = {
     "void": {
@@ -1457,9 +1505,8 @@ var AutoCompletionKnownTypes = {
         "tan": "|Number"
     },
     "Number": {
-        // There are also toFixed and valueOf, but they are left out because
-        // they steal focus from toString by being shorter (in the case of
-        // toFixed), and because they are used very seldom.
+        "valueOf": "|Number",
+        "toFixed": "|String",
         "toExponential": "|String",
         "toPrecision": "|String",
         "toLocaleString": "|String",
@@ -1471,8 +1518,7 @@ var LinkType = {
     "PROPERTY": 0,
     "INDEX": 1,
     "CALL": 2,
-    "SAFECALL": 3,
-    "RETVAL_HEURISTIC": 4
+    "RETVAL_HEURISTIC": 3
 };
 
 function getKnownType(t)
@@ -1535,77 +1581,178 @@ function getTypeExtractionExpression(command)
     return ret;
 }
 
-function propChainBuildComplete(out, context, tempExpr, result)
+/**
+ * Compare two property names a and b with a custom sort order. The comparison
+ * is lexicographical, but treats _ as higher than other letters in the
+ * beginning of the word, so that:
+ *  $ < AutoCompleter < add_widget < additive < _ < _priv < __proto__
+ * @return -1, 0 or 1 depending on whether (a < b), (a == b) or (a > b).
+ */
+function comparePropertyNames(lhs, rhs)
 {
-    var complete = null, command = null;
-    if (tempExpr.fake)
+    var len = Math.min(lhs.length, rhs.length);
+    for (var i = 0; i < len; ++i)
     {
-        var name = tempExpr.value.val;
-        complete = getFakeCompleteKeys(name);
-        if (!getKnownType(name)._fb_ignorePrototype)
-            command = name + ".prototype";
+        var u1 = (lhs.charAt(i) === "_");
+        var u2 = (rhs.charAt(i) === "_");
+        if (!u1 && !u2)
+            break;
+        if (!u1 || !u2)
+            return (u1 ? 1 : -1);
     }
-    else
+
+    if (lhs < rhs)
+        return -1;
+    return (lhs === rhs ? 0 : 1);
+}
+
+function propertiesToHide(expr, obj)
+{
+    var ret = [];
+
+    // __{define,lookup}[SG]etter__ appear as own properties on lots of DOM objects.
+    ret.push("__defineGetter__", "__defineSetter__",
+        "__lookupGetter__", "__lookupSetter__");
+
+    // function.caller/argument are deprecated and ugly.
+    if (typeof obj === "function")
+        ret.push("caller", "arguments");
+
+    if (Object.prototype.toString.call(obj) === "[object String]")
+    {
+        // Unused, cluttery.
+        ret.push("toLocaleLowerCase", "toLocaleUpperCase", "quote", "bold",
+            "italics", "fixed", "fontsize", "fontcolor", "link", "anchor",
+            "strike", "small", "big", "blink", "sup", "sub");
+    }
+
+    if (expr === "" || expr === "window.")
+    {
+        // Internal Firefox things.
+        ret.push("getInterface", "Components", "XPCNativeWrapper",
+            "InstallTrigger", "WindowInternal", "DocumentXBL",
+            "startProfiling", "stopProfiling", "pauseProfilers",
+            "resumeProfilers", "dumpProfile", "netscape",
+            "BoxObject", "BarProp", "BrowserFeedWriter", "ChromeWindow",
+            "ElementCSSInlineStyle", "JSWindow", "NSEditableElement",
+            "NSRGBAColor", "NSEvent", "NSXPathExpression", "ToString",
+            "OpenWindowEventDetail", "Parser", "ParserJS", "Rect",
+            "RGBColor", "ROCSSPrimitiveValue", "RequestService",
+            "PaintRequest", "PaintRequestList", "WindowUtils",
+            "GlobalPropertyInitializer", "GlobalObjectConstructor"
+        );
+
+        // Hide ourselves.
+        ret.push("_FirebugCommandLine", "_firebug");
+    }
+
+    // Old and ugly.
+    if (expr === "document.")
+        ret.push("fgColor", "vlinkColor", "linkColor");
+    if (expr === "document.body.")
+        ret.push("link", "aLink", "vLink");
+
+    // Rather universal and feel like built-ins.
+    ret.push("valueOf", "toSource", "constructor", "QueryInterface");
+
+    return ret;
+}
+
+
+function setCompletionsFromObject(out, object, context)
+{
+    // 'object' is a user-level, non-null object.
+    try
     {
-        if (typeof result === "string")
+        var isObjectPrototype = function(obj)
         {
-            // Strings only have indices as properties, use the fake object
-            // completions instead.
-            tempExpr.fake = true;
-            tempExpr.value = getKnownTypeInfo("String");
-            propChainBuildComplete(out, context, tempExpr);
-            return;
+            // Check if an object is "Object.prototype". This isn't as simple
+            // as 'obj === context.window.wrappedJSObject.Object.prototype' due
+            // to cross-window properties, nor just '!Object.getPrototypeOf(obj)'
+            // because of Object.create.
+            return !Object.getPrototypeOf(obj) && "hasOwnProperty" in obj;
+        }
+
+        var obj = object;
+        while (obj !== null)
+        {
+            var target = (isObjectPrototype(obj) ?
+                    out.hiddenCompletions : out.completions);
+            target.push.apply(target, Object.getOwnPropertyNames(obj));
+            obj = Object.getPrototypeOf(obj);
+        }
+
+        // As a special case, when completing "Object.prototype." no properties
+        // should be hidden.
+        if (isObjectPrototype(object))
+        {
+            out.completions = out.hiddenCompletions;
+            out.hiddenCompletions = [];
         }
-        else if (FirebugReps.Arr.isArray(result, context.window))
-            complete = nonNumericKeys(result);
         else
-            complete = Arr.keys(result);
-        command = getTypeExtractionExpression(tempExpr.command);
+        {
+            // Hide a list of well-chosen annoying properties.
+            var hide = propertiesToHide(out.spreExpr, object);
+            var hideMap = Object.create(null);
+            for (var i = 0; i < hide.length; ++i)
+                hideMap[hide[i]] = 1;
+            var hideRegex = /^XUL[A-Za-z]+$/;
+
+            var newCompletions = [];
+            out.completions.forEach(function(prop)
+            {
+                if (prop in hideMap || hideRegex.test(prop))
+                    out.hiddenCompletions.push(prop);
+                else
+                    newCompletions.push(prop);
+            });
+            out.completions = newCompletions;
+        }
+
+        // Firefox hides __proto__ - add it back.
+        if ("__proto__" in object)
+            out.hiddenCompletions.push("__proto__");
     }
+    catch (exc)
+    {
+        if (FBTrace.DBG_COMMANDLINE)
+            FBTrace.sysout("autoCompleter.getCompletionsFromPrototypeChain failed", exc);
+    }
+}
 
-    var done = function()
+function propChainBuildComplete(out, context, tempExpr, result)
+{
+    var done = function(result)
     {
-        if (out.indexCompletion)
+        if (result !== undefined && result !== null)
         {
-            complete = complete.map(function(x)
+            if (typeof result !== "object" && typeof result !== "function")
             {
-                x = (out.indexQuoteType === '"') ? Str.escapeJS(x): Str.escapeSingleQuoteJS(x);
-                return x + out.indexQuoteType + "]";
-            });
+                // Convert the primitive into its scope's matching object type.
+                result = Wrapper.getContentView(out.window).Object(result);
+            }
+            setCompletionsFromObject(out, result, context);
         }
-
-        // Properties may be taken from several sources, so filter out duplicates.
-        out.complete = Arr.sortUnique(complete);
     };
 
-    if (command === null)
-    {
-        done();
-    }
-    else
+    if (tempExpr.fake)
     {
-        Firebug.CommandLine.evaluate(command, context, context.thisValue, null,
+        var name = tempExpr.value.val;
+        if (getKnownType(name)._fb_ignorePrototype)
+            return;
+        var command = name + ".prototype";
+        Firebug.CommandLine.evaluate(name + ".prototype", context, context.thisValue, null,
             function found(result, context)
             {
-                if (tempExpr.fake)
-                {
-                    complete = complete.concat(Arr.keys(result));
-                }
-                else
-                {
-                    if (typeof result === "string" && getKnownType(result))
-                    {
-                        complete = complete.concat(getFakeCompleteKeys(result));
-                    }
-                }
-                done();
+                done(result);
             },
-            function failed(result, context)
-            {
-                done();
-            }
+            function failed(result, context) { }
         );
     }
+    else
+    {
+        done(result);
+    }
 }
 
 function evalPropChainStep(step, tempExpr, evalChain, out, context)
@@ -1658,14 +1805,18 @@ function evalPropChainStep(step, tempExpr, evalChain, out, context)
                 tempExpr.thisCommand = "window";
                 tempExpr.command += "[" + link.cont + "]";
             }
-            else if (type === LinkType.SAFECALL)
-            {
-                tempExpr.thisCommand = "window";
-                tempExpr.command += "(" + link.origCont + ")";
-            }
             else if (type === LinkType.CALL)
             {
-                if (link.name === "")
+                if (link.origCont !== null &&
+                     (link.name.substr(0, 3) === "get" ||
+                      (link.name.charAt(0) === "$" && link.cont.indexOf(",") === -1)))
+                {
+                    // Names beginning with get or $ are almost always getters, so
+                    // assume we can safely just call it.
+                    tempExpr.thisCommand = "window";
+                    tempExpr.command += "(" + link.origCont + ")";
+                }
+                else if (!link.name)
                 {
                     // We cannot know about functions without name; try the
                     // heuristic directly.
@@ -1673,22 +1824,14 @@ function evalPropChainStep(step, tempExpr, evalChain, out, context)
                     evalPropChainStep(step, tempExpr, evalChain, out, context);
                     return;
                 }
-
-                funcCommand = getTypeExtractionExpression(tempExpr.thisCommand);
-                break;
+                else
+                {
+                    funcCommand = getTypeExtractionExpression(tempExpr.thisCommand);
+                    break;
+                }
             }
             else if (type === LinkType.RETVAL_HEURISTIC)
             {
-                if (link.origCont !== null &&
-                     (link.name.substr(0, 3) === "get" ||
-                      (link.name.charAt(0) === "$" && link.cont.indexOf(",") === -1)))
-                {
-                    // Names beginning with get or $ are almost always getters, so
-                    // assume it is a safecall and start over.
-                    link.type = LinkType.SAFECALL;
-                    evalPropChainStep(step, tempExpr, evalChain, out, context);
-                    return;
-                }
                 funcCommand = "Function.prototype.toString.call(" + tempExpr.command + ")";
                 break;
             }
@@ -1896,9 +2039,13 @@ function evalPropChain(out, preExpr, origExpr, context)
 
 function autoCompleteEval(context, preExpr, spreExpr, includeCurrentScope)
 {
-    var out = {};
-
-    out.complete = [];
+    var out = {
+        spreExpr: spreExpr,
+        completions: [],
+        hiddenCompletions: [],
+        window: context.baseWindow || context.window
+    };
+    var indexCompletion = false;
 
     try
     {
@@ -1908,11 +2055,10 @@ function autoCompleteEval(context, preExpr, spreExpr, includeCurrentScope)
 
             // In case of array indexing, remove the bracket and set a flag to
             // escape completions.
-            out.indexCompletion = false;
             var len = spreExpr.length;
             if (len >= 2 && spreExpr[len-2] === "[" && spreExpr[len-1] === '"')
             {
-                out.indexCompletion = true;
+                indexCompletion = true;
                 out.indexQuoteType = preExpr[len-1];
                 spreExpr = spreExpr.substr(0, len-2);
                 preExpr = preExpr.substr(0, len-2);
@@ -1934,7 +2080,7 @@ function autoCompleteEval(context, preExpr, spreExpr, includeCurrentScope)
 
             // Don't auto-complete '.'.
             if (spreExpr === "")
-                return out.complete;
+                return out;
 
             evalPropChain(out, spreExpr, preExpr, context);
         }
@@ -1942,35 +2088,56 @@ function autoCompleteEval(context, preExpr, spreExpr, includeCurrentScope)
         {
             // Complete variables from the local scope
 
-            var contentView = Wrapper.getContentView(context.window);
+            var contentView = Wrapper.getContentView(out.window);
             if (context.stopped && includeCurrentScope)
             {
-                out.complete = Firebug.Debugger.getCurrentFrameKeys(context);
+                out.completions = Firebug.Debugger.getCurrentFrameKeys(context);
             }
             else if (contentView && contentView.Window &&
                 contentView.constructor.toString() === contentView.Window.toString())
                 // Cross window type pseudo-comparison
             {
-                out.complete = Arr.keys(contentView); // return is safe
-
-                // Add some known window properties
-                out.complete = out.complete.concat(getFakeCompleteKeys("Window"));
+                setCompletionsFromObject(out, contentView, context);
             }
             else  // hopefully sandbox in Chromebug
             {
-                out.complete = Arr.keys(context.global);
+                setCompletionsFromObject(out, context.global, context);
             }
+        }
 
-            // Sort the completions, and avoid duplicates.
-            out.complete = Arr.sortUnique(out.complete);
+        // Add "] to properties if we are doing index-completions.
+        if (indexCompletion)
+        {
+            function convertQuotes(x)
+            {
+                x = (out.indexQuoteType === '"') ? Str.escapeJS(x): Str.escapeSingleQuoteJS(x);
+                return x + out.indexQuoteType + "]";
+            }
+            out.completions = out.completions.map(convertQuotes);
+            out.hiddenCompletions = out.hiddenCompletions.map(convertQuotes);
         }
+
+        // Remove numeric keys.
+        var rePositiveNumber = /^[1-9][0-9]*$/;
+        var nonNumeric = function(x)
+        {
+            return x !== '0' && !rePositiveNumber.test(x);
+        }
+        out.completions = out.completions.filter(nonNumeric);
+        out.hiddenCompletions = out.hiddenCompletions.filter(nonNumeric);
+
+        // Sort the completions, and avoid duplicates.
+        // XXX: If we make it possible to show both regular and hidden completions
+        // at the same time, completions must shadow hiddenCompletions.
+        out.completions = Arr.sortUnique(out.completions, comparePropertyNames);
+        out.hiddenCompletions = Arr.sortUnique(out.hiddenCompletions, comparePropertyNames);
     }
     catch (exc)
     {
         if (FBTrace.DBG_ERRORS && FBTrace.DBG_COMMANDLINE)
             FBTrace.sysout("commandLine.autoCompleteEval FAILED", exc);
     }
-    return out.complete;
+    return out;
 }
 
 var reValidJSToken = /^[A-Za-z_$][A-Za-z_$0-9]*$/;
@@ -1988,26 +2155,6 @@ function isValidProperty(value)
     return reValidJSToken.test(value);
 }
 
-const rePositiveNumber = /^[1-9][0-9]*$/;
-function nonNumericKeys(map)  // keys will be on user-level window objects
-{
-    var keys = [];
-    try
-    {
-        for (var name in map)  // enumeration is safe
-        {
-            if (! (name === "0" || rePositiveNumber.test(name)) )
-                keys.push(name);
-        }
-    }
-    catch (exc)
-    {
-        // Sometimes we get exceptions trying to iterate properties
-    }
-
-    return keys;  // return is safe
-}
-
 function setCursorToEOL(input)
 {
     // textbox version, https://developer.mozilla.org/en/XUL/Property/inputField
diff --git a/trace/FBTrace/chrome/firebug/content/console/commandEditor.js b/trace/FBTrace/chrome/firebug/content/console/commandEditor.js
index 81241d6..3bfc49d 100644
--- a/trace/FBTrace/chrome/firebug/content/console/commandEditor.js
+++ b/trace/FBTrace/chrome/firebug/content/console/commandEditor.js
@@ -148,7 +148,8 @@ Firebug.CommandEditor = Obj.extend(Firebug.Module,
         if (Firebug.CommandEditor.ignoreChanges)
             return;
 
-        Firebug.CommandLine.onCommandLineInput(event);
+        var context = Firebug.currentContext;
+        Firebug.CommandLine.update(context);
     },
 
     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -159,12 +160,8 @@ Firebug.CommandEditor = Obj.extend(Firebug.Module,
         var popup = document.getElementById("fbCommandEditorPopup");
         Dom.eraseNode(popup);
 
-        var browserWindow = Firebug.chrome.window;
-        var commandDispatcher = browserWindow.document.commandDispatcher;
-
         var items = Firebug.CommandEditor.getContextMenuItems();
-        for (var i=0; i<items.length; i++)
-            Menu.createMenuItem(popup, items[i]);
+        Menu.createMenuItems(popup, items);
 
         if (!popup.childNodes.length)
             return;
diff --git a/trace/FBTrace/chrome/firebug/content/console/commandHistory.js b/trace/FBTrace/chrome/firebug/content/console/commandHistory.js
index 2419eda..76494db 100644
--- a/trace/FBTrace/chrome/firebug/content/console/commandHistory.js
+++ b/trace/FBTrace/chrome/firebug/content/console/commandHistory.js
@@ -24,7 +24,7 @@ Firebug.CommandHistory = function()
     const commandHistoryMax = 1000;
 
     var commandsPopup = Firebug.chrome.$("fbCommandHistory");
-    var commands = [];
+    var commands = this.commands = [];
     var commandPointer = 0;
     var commandInsertPointer = -1;
 
@@ -78,25 +78,21 @@ Firebug.CommandHistory = function()
         var command;
         var commandLine = Firebug.CommandLine.getCommandLine(context);
 
-        if (dir < 0)
-        {
-            if (commandPointer > 0)
-                commandPointer--;
-        }
-        else
-        {
-            if (commandPointer < commands.length)
-                commandPointer++;
-        }
+        commandPointer += dir;
+        if (commandPointer < 0)
+            commandPointer = 0;
+        else if (commandPointer > commands.length)
+            commandPointer = commands.length;
 
         if (commandPointer < commands.length)
         {
             command = commands[commandPointer];
             if (commandsPopup.state == "open")
             {
-                var commandElements = commandsPopup.ownerDocument.getElementsByClassName(
-                    "commandHistoryItem");
-                this.selectCommand(commandElements[commandPointer]);
+                var commandElement = commandsPopup.children[commandPointer];
+                this.selectCommand(commandElement);
+
+                Dom.scrollMenupopup(commandsPopup, commandElement);
             }
         }
         else
@@ -119,40 +115,42 @@ Firebug.CommandHistory = function()
     this.show = function(element)
     {
         if (this.isShown())
-            return this.hide;
+            return this.hide();
 
         Dom.eraseNode(commandsPopup);
 
         if(commands.length == 0)
             return;
 
-        var vbox = commandsPopup.ownerDocument.createElement("vbox");
+        var doc = commandsPopup.ownerDocument;
 
         for (var i = 0; i < commands.length; i++)
         {
-            var hbox = commandsPopup.ownerDocument.
-                createElementNS("http://www.w3.org/1999/xhtml", "div");
+            var hbox = doc.createElementNS("http://www.w3.org/1999/xhtml", "div");
 
             hbox.classList.add("commandHistoryItem");
             var shortExpr = Str.cropString(Str.stripNewLines(commands[i]), 50);
             hbox.innerHTML = Str.escapeForTextNode(shortExpr);
             hbox.value = i;
-            vbox.appendChild(hbox);
+            commandsPopup.appendChild(hbox);
 
             if (i === commandPointer)
                 this.selectCommand(hbox);
         }
 
-        commandsPopup.appendChild(vbox);
         commandsPopup.openPopup(element, "before_start", 0, 0, false, false);
 
+        // make sure last element is visible
+        setTimeout(Dom.scrollMenupopup, 10, commandsPopup, hbox);
+        this.isOpen = true;
+
         return true;
     };
 
     this.hide = function()
     {
         commandsPopup.hidePopup();
-
+        this.isOpen = false;
         return true;
     };
 
@@ -186,9 +184,13 @@ Firebug.CommandHistory = function()
 
     this.onMouseUp = function(event)
     {
+        var i = event.target.value;
+        if (i == undefined)
+            return;
+
         var commandLine = Firebug.CommandLine.getCommandLine(Firebug.currentContext);
 
-        commandLine.value = commands[event.target.value];
+        commandLine.value = commands[i];
         commandPointer = event.target.value;
 
         Firebug.CommandLine.commandHistory.hide();
@@ -198,6 +200,7 @@ Firebug.CommandHistory = function()
     {
         Firebug.chrome.setGlobalAttribute("fbCommandLineHistoryButton", "checked", "false");
         Firebug.chrome.setGlobalAttribute("fbCommandEditorHistoryButton", "checked", "false");
+        this.isOpen = false;
     };
 };
 
diff --git a/trace/FBTrace/chrome/firebug/content/console/commandLine.js b/trace/FBTrace/chrome/firebug/content/console/commandLine.js
index ff77b31..d0dada8 100644
--- a/trace/FBTrace/chrome/firebug/content/console/commandLine.js
+++ b/trace/FBTrace/chrome/firebug/content/console/commandLine.js
@@ -18,16 +18,17 @@ define([
     "firebug/lib/xml",
     "firebug/lib/array",
     "firebug/lib/persist",
-    "firebug/console/eventMonitor",
     "firebug/lib/keywords",
     "firebug/console/console",
     "firebug/console/commandLineHelp",
+    "firebug/console/commandLineInclude",
     "firebug/console/commandLineExposed",
     "firebug/console/autoCompleter",
     "firebug/console/commandHistory"
 ],
 function(Obj, Firebug, FirebugReps, Locale, Events, Wrapper, Url, Css, Dom, Firefox, Win, System,
-    Xpath, Str, Xml, Arr, Persist, EventMonitor, Keywords, Console, CommandLineHelp) {
+    Xpath, Str, Xml, Arr, Persist, Keywords, Console, CommandLineHelp,
+    CommandLineInclude, CommandLineExposed) {
 
 // ********************************************************************************************* //
 // Constants
@@ -351,7 +352,8 @@ Firebug.CommandLine = Obj.extend(Firebug.Module,
 
     evaluateInWebPage: function(expr, context, targetWindow)
     {
-        var win = targetWindow || context.window;
+        var win = targetWindow ? targetWindow :
+            (context.baseWindow ? context.baseWindow : context.window);
         var element = Dom.addScript(win.document, "_firebugInWebPage", expr);
         if (!element)
             return;
@@ -450,6 +452,10 @@ Firebug.CommandLine = Obj.extend(Firebug.Module,
 
         if (noscript && noScriptURI)
             noscript.setJSEnabled(noScriptURI, false);
+
+        var consolePanel = Firebug.currentContext.panelMap.console;
+        if (consolePanel)
+            Dom.scrollToBottom(consolePanel.panelNode);
     },
 
     enterInspect: function(context)
@@ -564,7 +570,8 @@ Firebug.CommandLine = Obj.extend(Firebug.Module,
         var commandLine = this.getSingleRowCommandLine();
         var commandEditor = this.getCommandEditor();
 
-        if (saveMultiLine)  // we are just closing the view
+        // we are just closing the view
+        if (saveMultiLine)
         {
             commandLine.value = commandEditor.value;
             return;
@@ -579,8 +586,6 @@ Firebug.CommandLine = Obj.extend(Firebug.Module,
                 commandEditor.value = Str.cleanIndentation(text);
             else
                 commandLine.value = Str.stripNewLines(text);
-
-            this.setAutoCompleter();
         }
         // else we may be hiding a panel while turning Firebug off
     },
@@ -623,56 +628,40 @@ Firebug.CommandLine = Obj.extend(Firebug.Module,
     {
         Firebug.Module.initialize.apply(this, arguments);
 
-        this.autoCompleter = new Firebug.EmptyJSAutoCompleter();
+        this.setAutoCompleter();
         this.commandHistory = new Firebug.CommandHistory();
 
         if (Firebug.commandEditor)
             this.setMultiLine(true, Firebug.chrome);
     },
 
+    // (Re)create the auto-completer for the small command line.
     setAutoCompleter: function()
     {
-        var context = Firebug.currentContext;
-
-        // xxxHonza: see http://code.google.com/p/fbug/issues/detail?id=4901#c21
         if (this.autoCompleter)
             this.autoCompleter.shutdown();
 
-        // Set the auto-completer even if the command-editor is currently displayed
-        // in the Console panel. This is to make the auto-completion work even in
-        // the small-command-line available on other panels (see issue 5006).
-
-        if (!context/* || Firebug.commandEditor*/)
-        {
-            this.autoCompleter = new Firebug.EmptyJSAutoCompleter();
-        }
-        else
-        {
-            // Always create the auto-completer for the single command line.
-            var commandLine = this.getSingleRowCommandLine();
-            var completionBox = this.getCompletionBox();
-
-            var options = {
-                showCompletionPopup: Firebug.Options.get("commandLineShowCompleterPopup"),
-                completionPopup: Firebug.chrome.$("fbCommandLineCompletionList"),
-                tabWarnings: true,
-                includeCurrentScope: true
-            };
+        var commandLine = this.getSingleRowCommandLine();
+        var completionBox = this.getCompletionBox();
+
+        var options = {
+            showCompletionPopup: Firebug.Options.get("commandLineShowCompleterPopup"),
+            completionPopup: Firebug.chrome.$("fbCommandLineCompletionList"),
+            popupMeasurer: Firebug.chrome.$("fbCommandLineMeasurer"),
+            tabWarnings: true,
+            includeCurrentScope: true
+        };
 
-            this.autoCompleter = new Firebug.JSAutoCompleter(commandLine,
-                completionBox, options);
-        }
+        this.autoCompleter = new Firebug.JSAutoCompleter(commandLine, completionBox, options);
     },
 
     initializeUI: function()
     {
-        this.onCommandLineFocus = Obj.bind(this.onCommandLineFocus, this);
         this.onCommandLineInput = Obj.bind(this.onCommandLineInput, this);
-        this.onCommandLineBlur = Obj.bind(this.onCommandLineBlur, this);
+        this.onCommandLineOverflow = Obj.bind(this.onCommandLineOverflow, this);
         this.onCommandLineKeyUp = Obj.bind(this.onCommandLineKeyUp, this);
         this.onCommandLineKeyDown = Obj.bind(this.onCommandLineKeyDown, this);
         this.onCommandLineKeyPress = Obj.bind(this.onCommandLineKeyPress, this);
-        this.onCommandLineOverflow = Obj.bind(this.onCommandLineOverflow, this);
         this.attachListeners();
     },
 
@@ -680,35 +669,28 @@ Firebug.CommandLine = Obj.extend(Firebug.Module,
     {
         var commandLine = this.getSingleRowCommandLine();
 
-        Events.addEventListener(commandLine, "focus", this.onCommandLineFocus, true);
         Events.addEventListener(commandLine, "input", this.onCommandLineInput, true);
         Events.addEventListener(commandLine, "overflow", this.onCommandLineOverflow, true);
         Events.addEventListener(commandLine, "keyup", this.onCommandLineKeyUp, true);
         Events.addEventListener(commandLine, "keydown", this.onCommandLineKeyDown, true);
         Events.addEventListener(commandLine, "keypress", this.onCommandLineKeyPress, true);
-        Events.addEventListener(commandLine, "blur", this.onCommandLineBlur, true);
-
-        Firebug.Console.addListener(this);  // to get onConsoleInjected
     },
 
     shutdown: function()
     {
         var commandLine = this.getSingleRowCommandLine();
 
-        // Make sure all listeners registered by the auto completer are removed.
         if (this.autoCompleter)
             this.autoCompleter.shutdown();
 
         if (this.commandHistory)
             this.commandHistory.detachListeners();
 
-        Events.removeEventListener(commandLine, "focus", this.onCommandLineFocus, true);
         Events.removeEventListener(commandLine, "input", this.onCommandLineInput, true);
         Events.removeEventListener(commandLine, "overflow", this.onCommandLineOverflow, true);
         Events.removeEventListener(commandLine, "keyup", this.onCommandLineKeyUp, true);
         Events.removeEventListener(commandLine, "keydown", this.onCommandLineKeyDown, true);
         Events.removeEventListener(commandLine, "keypress", this.onCommandLineKeyPress, true);
-        Events.removeEventListener(commandLine, "blur", this.onCommandLineBlur, true);
     },
 
     destroyContext: function(context, persistedState)
@@ -810,6 +792,11 @@ Firebug.CommandLine = Obj.extend(Firebug.Module,
 
     onCommandLineKeyDown: function(event)
     {
+        // XXX: Temporary hack to make FireClosure work (until that gets a new
+        // release out)
+        if (!this.autoCompleter.shouldIncludeHint && Firebug.JSAutoCompleter.transformScopeExpr)
+            this.setAutoCompleter();
+
         var context = Firebug.currentContext;
 
         this.autoCompleter.handleKeyDown(event, context);
@@ -875,6 +862,9 @@ Firebug.CommandLine = Obj.extend(Firebug.Module,
                 return true;
         }
 
+        if (this.commandHistory.isOpen && !event.metaKey && !event.ctrlKey && !event.altKey)
+            this.commandHistory.hide();
+
         return false;
     },
 
@@ -882,32 +872,10 @@ Firebug.CommandLine = Obj.extend(Firebug.Module,
     {
         var context = Firebug.currentContext;
 
-        if (!this.commandHistory.isShown())
-        {
-            this.autoCompleter.complete(context);
-        }
-
-        // Always update the buffer in context, even if command line is empty.
+        this.autoCompleter.complete(context);
         this.update(context);
     },
 
-    onCommandLineBlur: function(event)
-    {
-    },
-
-    onCommandLineFocus: function(event)
-    {
-        if (FBTrace.DBG_COMMANDLINE)
-        {
-            var context = Firebug.currentContext;
-            FBTrace.sysout("commandLine.onCommandLineFocus; for: " +
-                (context ? context.getName() : "no context"));
-        }
-
-        if (this.autoCompleter.empty)
-            this.setAutoCompleter();
-    },
-
     isAttached: function(context, win)
     {
         if (!context)
@@ -935,20 +903,6 @@ Firebug.CommandLine = Obj.extend(Firebug.Module,
         Dom.collapse(Firebug.chrome.$("fbSidePanelDeck"), true);
     },
 
-    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-    // Firebug.Console listener
-
-    onConsoleInjected: function(context, win)
-    {
-        // for some reason the console has been injected. If the user had focus in the command
-        // line they want it added in the page also. If the user has the cursor in the command
-        // line and reloads, the focus will already be there. issue 1339
-        var isFocused = Firebug.CommandEditor.hasFocus();
-        isFocused = isFocused || (this.getSingleRowCommandLine().getAttribute("focused") == "true");
-        if (isFocused)
-            setTimeout(this.onCommandLineFocus);
-    },
-
     getCommandLine: function(context)
     {
         return (!this.isInOtherPanel(context) && Firebug.commandEditor) ? 
@@ -1034,27 +988,66 @@ Firebug.CommandLine.CommandHandler = Obj.extend(Object,
 });
 
 // ********************************************************************************************* //
-// Command line APIs definition
-//
-// These functions will be called in the extension like this:
-//   subHandler.apply(api, userObjects);
-// where subHandler is one of the entries below, api is this object and userObjects are entries in
-// an array we created in the web page.
+// Command Line API
 
+/**
+ * These functions will be called in the extension like this:
+ *
+ * subHandler.apply(api, userObjects);
+ *
+ * Where subHandler is one of the entries below, api is this object and userObjects
+ * are entries in an array we created in the web page.
+ */
 function FirebugCommandLineAPI(context)
 {
-    this.$ = function(id)  // returns unwrapped elements from the page
+    // returns unwrapped elements from the page
+    this.$ = function(selector, start)
     {
-        return Wrapper.unwrapObject(context.baseWindow.document).getElementById(id);
+        if (start && start.querySelector && (
+            start.nodeType == Node.ELEMENT_NODE ||
+            start.nodeType == Node.DOCUMENT_NODE ||
+            start.nodeType == Node.DOCUMENT_FRAGMENT_NODE))
+        {
+            return start.querySelector(selector);
+        }
+
+        var result = context.baseWindow.document.querySelector(selector);
+        if (result == null && (selector || "")[0] !== "#")
+        {
+            if (context.baseWindow.document.getElementById(selector))
+            {
+                // This should be removed in the next minor (non-bugfix) version
+                var msg = Locale.$STRF("warning.dollar_change", [selector]);
+                Firebug.Console.log(msg, context, "warn");
+                result = null;
+            }
+        }
+
+        return result;
     };
 
-    this.$$ = function(selector) // returns unwrapped elements from the page
+    // returns unwrapped elements from the page
+    this.$$ = function(selector, start)
     {
-        var result = Wrapper.unwrapObject(context.baseWindow.document).querySelectorAll(selector);
+        var result;
+
+        if (start && start.querySelectorAll && (
+            start.nodeType == Node.ELEMENT_NODE ||
+            start.nodeType == Node.DOCUMENT_NODE ||
+            start.nodeType == Node.DOCUMENT_FRAGMENT_NODE))
+        {
+            result = start.querySelectorAll(selector);
+        }
+        else
+        {
+            result = context.baseWindow.document.querySelectorAll(selector);
+        }
+
         return Arr.cloneArray(result);
     };
 
-    this.$x = function(xpath, contextNode, resultType) // returns unwrapped elements from the page
+    // returns unwrapped elements from the page
+    this.$x = function(xpath, contextNode, resultType)
     {
         var XPathResultType = XPathResult.ANY_TYPE;
 
@@ -1075,18 +1068,18 @@ function FirebugCommandLineAPI(context)
             case "node":
                 XPathResultType = XPathResult.FIRST_ORDERED_NODE_TYPE;
                 break;
-                
+
             case "nodes":
                 XPathResultType = XPathResult.UNORDERED_NODE_ITERATOR_TYPE;
                 break;
         }
 
         var doc = Wrapper.unwrapObject(context.baseWindow.document);
-        
         return Xpath.evaluateXPath(doc, xpath, contextNode, XPathResultType);
     };
 
-    this.$n = function(index) // values from the extension space
+    // values from the extension space
+    this.$n = function(index)
     {
         var htmlPanel = context.getPanel("html", true);
         if (!htmlPanel)
@@ -1119,17 +1112,20 @@ function FirebugCommandLineAPI(context)
         if (entry)
             context.baseWindow = entry.win;
 
-        Firebug.Console.log(["Current window:", context.baseWindow], context, "info");
+        var format = Locale.$STR("commandline.CurrentWindow") + " %o";
+        Firebug.Console.logFormatted([format, context.baseWindow], context, "info");
         return Firebug.Console.getDefaultReturnValue(context.window);
     };
 
-    this.clear = function()  // no web page interaction
+    // no web page interaction
+    this.clear = function()
     {
         Firebug.Console.clear(context);
         return Firebug.Console.getDefaultReturnValue(context.window);
     };
 
-    this.inspect = function(obj, panelName)  // no web page interaction
+    // no web page interaction
+    this.inspect = function(obj, panelName)
     {
         Firebug.chrome.select(obj, panelName);
         return Firebug.Console.getDefaultReturnValue(context.window);
@@ -1137,12 +1133,14 @@ function FirebugCommandLineAPI(context)
 
     this.keys = function(o)
     {
-        return Arr.keys(o);  // the object is from the page, unwrapped
+        // the object is from the page, unwrapped
+        return Arr.keys(o);
     };
 
     this.values = function(o)
     {
-        return Arr.values(o); // the object is from the page, unwrapped
+        // the object is from the page, unwrapped
+        return Arr.values(o);
     };
 
     this.debug = function(fn)
@@ -1193,42 +1191,12 @@ function FirebugCommandLineAPI(context)
         return Firebug.Console.getDefaultReturnValue(context.window);
     };
 
-    this.monitorEvents = function(object, types)
-    {
-        EventMonitor.monitorEvents(object, types, context);
-        return Firebug.Console.getDefaultReturnValue(context.window);
-    };
-
-    this.unmonitorEvents = function(object, types)
-    {
-        EventMonitor.unmonitorEvents(object, types, context);
-        return Firebug.Console.getDefaultReturnValue(context.window);
-    };
-
-    this.profile = function(title)
-    {
-        Firebug.Profiler.startProfiling(context, title);
-        return Firebug.Console.getDefaultReturnValue(context.window);
-    };
-
-    this.profileEnd = function()
-    {
-        Firebug.Profiler.stopProfiling(context);
-        return Firebug.Console.getDefaultReturnValue(context.window);
-    };
-
     this.copy = function(x)
     {
         System.copyToClipboard(x);
         return Firebug.Console.getDefaultReturnValue(context.window);
     };
 
-    this.help = function()
-    {
-        CommandLineHelp.render(context);
-        return Firebug.Console.getDefaultReturnValue(context.window);
-    };
-
     // xxxHonza: removed from 1.10 (issue 5599)
     /*this.memoryProfile = function(title)
     {
@@ -1241,6 +1209,35 @@ function FirebugCommandLineAPI(context)
         Firebug.MemoryProfiler.stop(context);
         return Firebug.Console.getDefaultReturnValue(context.window);
     };*/
+
+    function createHandler(config, name)
+    {
+        return function()
+        {
+            try
+            {
+                return config.handler.call(null, context, arguments);
+            }
+            catch (err)
+            {
+                Firebug.Console.log(err, context, "errorMessage");
+
+                if (FBTrace.DBG_ERRORS)
+                {
+                    FBTrace.sysout("commandLine.api; EXCEPTION when executing " +
+                        "a command: " + name + ", " + err, err);
+                }
+            }
+        }
+    }
+
+    // Register user commands.
+    var commands = CommandLineExposed.userCommands;
+    for (var name in commands)
+    {
+        var config = commands[name];
+        this[name] = createHandler(config, name);
+    }
 }
 
 // ********************************************************************************************* //
@@ -1350,15 +1347,19 @@ Firebug.CommandLine.injector =
             delete context.activeCommandLineHandlers[consoleHandler.token];
 
             if (FBTrace.DBG_COMMANDLINE)
-                FBTrace.sysout("commandLine.detachCommandLineListener "+boundHandler+
-                    " in window with console "+win.location);
+            {
+                FBTrace.sysout("commandLine.detachCommandLineListener " + boundHandler +
+                    " in window with console " + win.location);
+            }
         }
         else
         {
             if (FBTrace.DBG_ERRORS || FBTrace.DBG_COMMANDLINE)
+            {
                 FBTrace.sysout("commandLine.removeCommandLineListener; ERROR no handler! " +
                     "This could cause memory leaks, please report an issue if you see this. " +
                     context.getName());
+            }
         }
     },
 
@@ -1405,7 +1406,7 @@ function CommandLineHandler(context, win)
 
         // Appends variables into the api.
         var htmlPanel = context.getPanel("html", true);
-        var vars = htmlPanel ? htmlPanel.getInspectorVars():null;
+        var vars = htmlPanel ? htmlPanel.getInspectorVars() : null;
 
         for (var prop in vars)
         {
@@ -1420,7 +1421,8 @@ function CommandLineHandler(context, win)
                 }
             }
 
-            this.api[prop] = createHandler(prop);  // XXXjjb should these be removed?
+            // XXXjjb should these be removed?
+            this.api[prop] = createHandler(prop);
         }
 
         if (!Firebug.CommandLine.CommandHandler.handle(event, this.api, win))
@@ -1449,6 +1451,7 @@ function getNoScript()
     return this.noscript;
 }
 
+
 // ********************************************************************************************* //
 // Registration
 
diff --git a/trace/FBTrace/chrome/firebug/content/console/commandLineExposed.js b/trace/FBTrace/chrome/firebug/content/console/commandLineExposed.js
index 6f4b298..bc29ef3 100644
--- a/trace/FBTrace/chrome/firebug/content/console/commandLineExposed.js
+++ b/trace/FBTrace/chrome/firebug/content/console/commandLineExposed.js
@@ -1,11 +1,10 @@
 /* See license.txt for terms of usage */
 
 define([
-    "firebug/firebug",
     "firebug/lib/wrapper",
     "firebug/lib/events",
 ],
-function(Firebug, Wrapper, Events) {
+function(Wrapper, Events) {
 
 // ********************************************************************************************* //
 // Command Line APIs
@@ -13,14 +12,16 @@ function(Firebug, Wrapper, Events) {
 // List of command line APIs
 var commands = ["$", "$$", "$x", "$n", "cd", "clear", "inspect", "keys",
     "values", "debug", "undebug", "monitor", "unmonitor", "traceCalls", "untraceCalls",
-    "traceAll", "untraceAll", "monitorEvents", "unmonitorEvents", "profile", "profileEnd",
-    "copy" /*, "memoryProfile", "memoryProfileEnd"*/];
+    "traceAll", "untraceAll", "copy" /*, "memoryProfile", "memoryProfileEnd"*/];
 
 // List of shortcuts for some console methods
 var consoleShortcuts = ["dir", "dirxml", "table"];
 
 // List of console variables.
-var props = ["$0", "$1", "help"];
+var props = ["$0", "$1"];
+
+// Registered commands, name -> config object.
+var userCommands = {};
 
 // ********************************************************************************************* //
 // Command Line Implementation
@@ -52,6 +53,24 @@ function createFirebugCommandLine(context, win)
     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
     // Exposed Properties
 
+    function createCommandHandler(cmd) {
+        return function() {
+            return notifyFirebug(arguments, cmd, "firebugExecuteCommand");
+        }
+    }
+
+    function createShortcutHandler(cmd) {
+        return function() {
+            return console[cmd].apply(console, arguments);
+        }
+    }
+
+    function createVariableHandler(prop) {
+        return function() {
+            return notifyFirebug(arguments, prop, "firebugExecuteCommand");
+        }
+    }
+
     // Define command line methods
     for (var i=0; i<commands.length; i++)
     {
@@ -61,16 +80,12 @@ function createFirebugCommandLine(context, win)
         if (command in contentView)
             continue;
 
-        function createCommandHandler(cmd) {
-            return function() {
-                return notifyFirebug(arguments, cmd, "firebugExecuteCommand");
-            }
-        }
-
         commandLine[command] = createCommandHandler(command);
         commandLine.__exposedProps__[command] = "rw";
     }
 
+    var console = Firebug.ConsoleExposed.createFirebugConsole(context, win);
+
     // Define shortcuts for some console methods
     for (var i=0; i<consoleShortcuts.length; i++)
     {
@@ -80,14 +95,8 @@ function createFirebugCommandLine(context, win)
         if (command in contentView)
             continue;
 
-        function createShortcutHandler(cmd) {
-            return function() {
-                return contentView.console[cmd].apply(contentView.console, arguments);
-            }
-        }
-
         commandLine[command] = createShortcutHandler(command);
-        commandLine.__exposedProps__[command] = "rw";
+        commandLine.__exposedProps__[command] = "r";
     }
 
     // Define console variables.
@@ -97,16 +106,31 @@ function createFirebugCommandLine(context, win)
         if (prop in contentView)
             continue;
 
-        function createVariableHandler(prop) {
-            return function() {
-                return notifyFirebug(arguments, prop, "firebugExecuteCommand");
-            }
-        }
-
         commandLine.__defineGetter__(prop, createVariableHandler(prop));
         commandLine.__exposedProps__[prop] = "r";
     }
 
+    // Define user registered commands.
+    for (var name in userCommands)
+    {
+        // If the method is already defined, don't override it.
+        if (name in contentView)
+            continue;
+
+        var config = userCommands[name];
+
+        if (config.getter)
+        {
+            commandLine.__defineGetter__(name, createVariableHandler(name));
+            commandLine.__exposedProps__[name] = "r";
+        }
+        else
+        {
+            commandLine[name] = createCommandHandler(name);
+            commandLine.__exposedProps__[name] = "r";
+        }
+    }
+
     attachCommandLine();
 
     // xxxHonza: TODO make this private.
@@ -245,6 +269,43 @@ document.documentElement.appendChild(script);
 */
 
 // ********************************************************************************************* //
+// User Commands
+
+function registerCommand(name, config)
+{
+    if (commands[name] || consoleShortcuts[name] || props[name] || userCommands[name])
+    {
+        if (FBTrace.DBG_ERRORS)
+        {
+            FBTrace.sysout("firebug.registerCommand; ERROR This command is already " +
+                "registered: " + name);
+        }
+
+        return false;
+    }
+
+    userCommands[name] = config;
+    return true;
+}
+
+function unregisterCommand(name)
+{
+    if (!userCommands[name])
+    {
+        if (FBTrace.DBG_ERRORS)
+        {
+            FBTrace.sysout("firebug.unregisterCommand; ERROR This command is not " +
+                "registered: " + name);
+        }
+
+        return false;
+    }
+
+    delete userCommands[name];
+    return true;
+}
+
+// ********************************************************************************************* //
 // Registration
 
 Firebug.CommandLineExposed =
@@ -253,6 +314,9 @@ Firebug.CommandLineExposed =
     commands: commands,
     consoleShortcuts: consoleShortcuts,
     properties: props,
+    userCommands: userCommands,
+    registerCommand: registerCommand,
+    unregisterCommand: unregisterCommand,
 };
 
 return Firebug.CommandLineExposed;
diff --git a/trace/FBTrace/chrome/firebug/content/console/commandLineHelp.js b/trace/FBTrace/chrome/firebug/content/console/commandLineHelp.js
index 7d9b607..b0e385e 100644
--- a/trace/FBTrace/chrome/firebug/content/console/commandLineHelp.js
+++ b/trace/FBTrace/chrome/firebug/content/console/commandLineHelp.js
@@ -1,13 +1,17 @@
 /* See license.txt for terms of usage */
 
 define([
+    "firebug/firebug",
     "firebug/lib/domplate",
     "firebug/lib/locale",
     "firebug/lib/dom",
     "firebug/console/commandLineExposed",
     "firebug/chrome/window",
+    "firebug/lib/xpcom",
+    "firebug/lib/events",
 ],
-function(Domplate, Locale, Dom, CommandLineExposed, Win) { with (Domplate) {
+function(Firebug, Domplate, Locale, Dom, CommandLineExposed, Win, Xpcom, Events) {
+with (Domplate) {
 
 // ********************************************************************************************* //
 // Constants
@@ -19,6 +23,8 @@ var CMD_TYPE_COMMAND = 1;
 var CMD_TYPE_SHORTCUT = 2;
 var CMD_TYPE_PROPERTY = 3;
 
+const prompts = Xpcom.CCSV("@mozilla.org/embedcomp/prompt-service;1", "nsIPromptService");
+
 // ********************************************************************************************* //
 // Domplates
 
@@ -35,6 +41,7 @@ var HelpCaption = domplate(
         )
 });
 
+// The table UI should be based on tableRep
 var HelpTable = domplate(
 {
     tag:
@@ -85,8 +92,22 @@ var HelpEntry = domplate(
 
     onClick: function(event)
     {
+        Events.cancelEvent(event);
+
         var object = Firebug.getRepObject(event.target);
-        Win.openNewTab("http://getfirebug.com/wiki/index.php/" + object.name);
+
+        if (object.noUserHelpUrl)
+        {
+            prompts.alert(null, Locale.$STR("Firebug"),
+                Locale.$STR("console.cmd.helpUrlNotAvailable"));
+            return;
+        }
+
+        var helpUrl = "http://getfirebug.com/wiki/index.php/" + object.name;
+        if (object.helpUrl)
+            helpUrl = object.helpUrl;
+
+        Win.openNewTab(helpUrl);
     },
 
     getName: function(object)
@@ -99,6 +120,9 @@ var HelpEntry = domplate(
 
     getDesc: function(object)
     {
+        if (object.nol10n)
+            return object.desc;
+
         return Locale.$STR(object.desc);
     }
 });
@@ -147,6 +171,23 @@ var CommandLineHelp = domplate(
             })
         }
 
+        for (var name in CommandLineExposed.userCommands)
+        {
+            var config = CommandLineExposed.userCommands[name];
+            commands.push({
+                name: name,
+                desc: config.description,
+                nol10n: true,
+                noUserHelpUrl: !config.helpUrl,
+                helpUrl: config.helpUrl ? config.helpUrl: null,
+                type: config.getter ? CMD_TYPE_PROPERTY : CMD_TYPE_COMMAND,
+            })
+        }
+
+        // Sort commands
+        commands.sort(function sortName(a, b) { return a.name > b.name ? 1 : -1; });
+
+        // Generate table
         HelpEntry.tag.insertRows({commands: commands}, tBody);
 
         return row;
@@ -154,8 +195,24 @@ var CommandLineHelp = domplate(
 });
 
 // ********************************************************************************************* //
+// Command Implementation
+
+function onExecuteCommand(context)
+{
+    CommandLineHelp.render(context);
+    return Firebug.Console.getDefaultReturnValue(context.window);
+}
+
+// ********************************************************************************************* //
 // Registration
 
+Firebug.registerCommand("help", {
+    getter: true,
+    helpUrl: "http://getfirebug.com/wiki/index.php/help",
+    handler: onExecuteCommand.bind(this),
+    description: Locale.$STR("console.cmd.help.help")
+});
+
 return CommandLineHelp;
 
 // ********************************************************************************************* //
diff --git a/trace/FBTrace/chrome/firebug/content/console/commandLineInclude.js b/trace/FBTrace/chrome/firebug/content/console/commandLineInclude.js
new file mode 100644
index 0000000..c5489b1
--- /dev/null
+++ b/trace/FBTrace/chrome/firebug/content/console/commandLineInclude.js
@@ -0,0 +1,542 @@
+/* See license.txt for terms of usage */
+
+define([
+    "firebug/chrome/reps",
+    "firebug/lib/domplate",
+    "firebug/lib/locale",
+    "firebug/lib/dom",
+    "firebug/chrome/window",
+    "firebug/lib/css",
+    "firebug/lib/string",
+    "firebug/lib/options",
+    "firebug/chrome/menu",
+    "firebug/lib/system",
+    "firebug/lib/xpcom",
+    "firebug/lib/object",
+    "firebug/editor/editor",
+],
+function(FirebugReps, Domplate, Locale, Dom, Win, Css, Str, Options, Menu, System, Xpcom, Obj) {
+with (Domplate) {
+
+// ********************************************************************************************* //
+// Constants
+
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+const removeConfirmation = "commandline.include.removeConfirmation";
+const prompts = Xpcom.CCSV("@mozilla.org/embedcomp/prompt-service;1", "nsIPromptService");
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+var ScratchpadManager;
+
+try
+{
+    var scope = {};
+    Cu.import("resource:///modules/devtools/scratchpad-manager.jsm", scope);
+    ScratchpadManager = scope.ScratchpadManager;
+}
+catch(ex)
+{
+    // Scratchpad does not exists (when using Seamonkey ...)
+}
+
+var storageScope = {};
+Cu.import("resource://firebug/storageService.js", storageScope);
+
+// ********************************************************************************************* //
+// Implementation
+
+var CommandLineIncludeRep = domplate(FirebugReps.Table,
+{
+    tableClassName: "tableCommandLineInclude dataTable",
+
+    tag:
+        FirebugReps.OBJECTBOX({_repObject: "$object"},
+            FirebugReps.Table.tag
+        ),
+
+    inspectable: false,
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+    // Domplate Handlers
+
+    getValueTag: function(object)
+    {
+        if (object.cons === DomplateTag)
+            return object;
+        else
+            return FirebugReps.Table.getValueTag(object);
+    },
+
+    getUrlTag: function(href, aliasName)
+    {
+        var urlTag =
+            SPAN({style:"height:100%"},
+                A({"href": href, "target": "_blank", "class": "url"},
+                    Str.cropString(href, 100)
+                ),
+                SPAN({"class": "commands"}
+                // xxxFlorent: temporarily disabled, see: 
+                //    http://code.google.com/p/fbug/issues/detail?id=5878#c27
+                /*,
+                IMG({
+                    "src":"blank.gif",
+                    "class":"closeButton ",
+                    onclick: this.deleteAlias.bind(this, aliasName),
+                })*/
+                )
+            );
+
+        return urlTag;
+    },
+
+    displayAliases: function(context)
+    {
+        var store = CommandLineInclude.getStore();
+        var keys = store.getKeys();
+        var arrayToDisplay = [];
+        var returnValue = Firebug.Console.getDefaultReturnValue(context.window);
+
+        if (keys.length === 0)
+        {
+            var msg = Locale.$STR("commandline.include.noDefinedAlias");
+            Firebug.Console.log(msg, context, null, FirebugReps.Hint);
+            return returnValue;
+        }
+
+        for (var i=0; i<keys.length; i++)
+        {
+            var aliasName = keys[i];
+            arrayToDisplay.push({
+                "alias": SPAN({"class":"aliasName", "data-aliasname": aliasName}, aliasName),
+                "URL": this.getUrlTag(store.getItem(aliasName), aliasName, context)
+            });
+        }
+
+        var input = new CommandLineIncludeObject();
+        this.log(arrayToDisplay, ["alias", "URL"], context, input);
+        return returnValue;
+    },
+
+    deleteAlias: function(aliasName, ev)
+    {
+        // NOTE: that piece of code has not been tested since deleting aliases through the table 
+        // has been disabled.
+        // Once it is enabled again, make sure FBTests is available for this feature
+        var store = CommandLine.getStore();
+        if (! Options.get(removeConfirmation))
+        {
+            var check = {value: false};
+            var flags = prompts.BUTTON_POS_0 * prompts.BUTTON_TITLE_YES +
+            prompts.BUTTON_POS_1 * prompts.BUTTON_TITLE_NO;
+
+            if  (prompts.confirmEx(context.chrome.window, Locale.$STR("Firebug"),
+                Locale.$STR("commandline.include.confirmDelete"), flags, "", "", "",
+                Locale.$STR("Do_not_show_this_message_again"), check) > 0)
+            {
+                return;
+            }
+
+            // Update 'Remove Cookies' confirmation option according to the value
+            // of the dialog's "do not show again" checkbox.
+            Options.set(removeConfirmation, !check.value);
+        }
+        store.removeItem(aliasName);
+    },
+
+    startEditing: function(target)
+    {
+        var editor = this.getEditor(target.ownerDocument);
+        Firebug.Editor.startEditing(target, target.dataset.aliasname, editor);
+    },
+
+    editAliasName: function(tr)
+    {
+        var target = tr.querySelector(".aliasName");
+        this.startEditing(target);
+    },
+
+    editAliasURL: function(tr)
+    {
+        var target = tr.querySelector(".url");
+        this.startEditing(target);
+    },
+
+    openInScratchpad: function(url)
+    {
+        var spWin = ScratchpadManager.openScratchpad();
+        var scriptContent = null;
+        var editor = null;
+
+        spWin.onload = function()
+        {
+            var spInstance = spWin.Scratchpad;
+            //intro = spInstance.strings.GetStringFromName("scratchpadIntro");
+            spInstance.addObserver(
+            {
+                onReady: function()
+                {
+                    editor = spInstance.editor;
+
+                    // if the content of the script is loaded, we write the content in the editor
+                    // otherwise, we write a text that asks the user to wait
+                    if (scriptContent)
+                        editor.setText(scriptContent);
+                    else
+                        editor.setText("// "+Locale.$STR("scratchpad.loading"));
+                }
+            });
+        }
+
+        var xhr = new XMLHttpRequest({mozAnon: true});
+        xhr.open("GET", url, true);
+
+        xhr.onload = function()
+        {
+            if (spWin.closed)
+                return;
+
+            scriptContent = xhr.responseText;
+
+            // if the editor is ready, we put the content on it now
+            // otherwise, we wait for the editor
+            if (editor)
+                editor.setText(scriptContent);
+        }
+
+        xhr.onerror = function()
+        {
+            if (spWin.closed)
+                return;
+
+            spInstance.setText("// "+Locale.$STR("scratchpad.failLoading"));
+        }
+
+        xhr.send(null);
+    },
+
+    supportsObject: function(object, type)
+    {
+        return object instanceof CommandLineIncludeObject;
+    },
+
+    getContextMenuItems: function(object, target, context)
+    {
+        var tr = Dom.getAncestorByTagName(target, "tr");
+        if (!tr)
+            return [];
+
+        var url = tr.querySelector("a.url").href;
+        var aliasName = tr.querySelector(".aliasName").dataset.aliasname;
+        var context = Firebug.currentContext;
+        var items = [
+            {
+                label: "CopyLocation",
+                id: "fbCopyLocation",
+                tooltiptext: "clipboard.tip.Copy_Location",
+                command: Obj.bindFixed(System.copyToClipboard, System, url)
+            },
+            // xxxFlorent: temporarily disabled, see: 
+            //    http://code.google.com/p/fbug/issues/detail?id=5878#c27
+            /*"-",
+            {
+                label: "commandline.label.EditAliasName",
+                id: "fbEditAliasName",
+                tooltiptext: "commandline.tip.Edit_Alias_Name",
+                command: this.editAliasName.bind(this, tr)
+            },
+            {
+                label: "commandline.label.EditAliasURL",
+                id: "fbEditAliasUrl",
+                tooltiptext: "commandline.tip.Edit_Alias_URL",
+                command: this.editAliasURL.bind(this, tr)
+            },
+            {
+                label: "commandline.label.DeleteAlias",
+                id: "fbDeleteAlias",
+                tooltiptext: "commandline.tip.Delete_Alias",
+                command: this.deleteAlias.bind(this, aliasName, ev)
+            },*/
+            "-",
+            {
+                label: Locale.$STRF("commandline.label.IncludeScript", [aliasName]),
+                id: "fbInclude",
+                tooltiptext: "commandline.tip.Include_Script",
+                command: Obj.bindFixed(CommandLineInclude.include, CommandLineInclude,
+                    context, aliasName)
+            },
+            "-",
+            {
+                label: "OpenInTab",
+                id: "fbOpenInTab",
+                tooltiptext: "firebug.tip.Open_In_Tab",
+                command: Obj.bindFixed(Win.openNewTab, Win, url)
+            }
+        ];
+
+        if (ScratchpadManager)
+        {
+            items.push({
+                label: "commandline.label.OpenInScratchpad",
+                id: "fbOpenInScratchpad",
+                tooltiptext: "commandline.tip.Open_In_Scratchpad",
+                command: this.openInScratchpad.bind(this, url)
+            });
+        }
+
+        return items;
+    },
+
+    getEditor: function(doc)
+    {
+        if (!this.editor)
+            this.editor = new IncludeEditor(doc);
+        return this.editor;
+    }
+});
+
+// ********************************************************************************************* //
+
+function CommandLineIncludeObject()
+{
+}
+
+// ********************************************************************************************* //
+
+var CommandLineInclude =
+{
+    onSuccess: function(newAlias, context, loadingMsgRow, xhr)
+    {
+        var urlComponent = xhr.channel.URI.QueryInterface(Ci.nsIURL);
+        var filename = urlComponent.fileName, url = urlComponent.spec;
+        // clear the message saying "loading..."
+        this.clearLoadingMessage(loadingMsgRow);
+
+        if (newAlias)
+        {
+            var store = this.getStore();
+            store.setItem(newAlias, url);
+            this.log("aliasCreated", [newAlias], [context, "info"]);
+        }
+
+        this.log("includeSuccess", [filename], [context, "info", true]);
+    },
+
+    onError: function(context, url, loadingMsgRow)
+    {
+        this.clearLoadingMessage(loadingMsgRow);
+        this.log("loadFail", [url], [context, "error"]);
+    },
+
+    clearLoadingMessage: function(loadingMsgRow)
+    {
+        if (loadingMsgRow && loadingMsgRow.parentNode)
+            loadingMsgRow.parentNode.removeChild(loadingMsgRow);
+    },
+
+    getStore: function()
+    {
+        if (!this.store)
+            this.store = storageScope.StorageService.getStorage("includeAliases.json");
+        return this.store;
+    },
+
+    log: function(localeStr, localeArgs, logArgs, noAutoPrefix)
+    {
+        var prefixedLocaleStr = (noAutoPrefix ? localeStr : "commandline.include."+localeStr);
+
+        var msg = Locale.$STRF(prefixedLocaleStr, localeArgs);
+        logArgs.unshift([msg]);
+        return Firebug.Console.logFormatted.apply(Firebug.Console, logArgs);
+    },
+
+    // include(context, url[, newAlias])
+    // includes a remote script
+    include: function(context, url, newAlias)
+    {
+        var reNotAlias = /[\.\/]/;
+        var urlIsAlias = url !== null && !reNotAlias.test(url);
+        var returnValue = Firebug.Console.getDefaultReturnValue(context.window);
+
+        // checking arguments:
+        if ((newAlias !== undefined && typeof newAlias !== "string") || newAlias === "")
+        {
+            this.log("invalidAliasArgumentType", [], [context, "error"]);
+            return returnValue;
+        }
+
+        if (url !== null && typeof url !== "string" || !url && !newAlias)
+        {
+            this.log("invalidUrlArgumentType", [], [context, "error"]);
+            return returnValue;
+        }
+
+        if (newAlias !== undefined)
+            newAlias = newAlias.toLowerCase();
+
+        if ((urlIsAlias && url.length > 30) || (newAlias && newAlias.length > 30))
+        {
+            this.log("tooLongAliasName", [newAlias || url], [context, "error"]);
+            return returnValue;
+        }
+
+        if (newAlias !== undefined && reNotAlias.test(newAlias))
+        {
+            this.log("invalidAliasName", [newAlias], [context, "error"]);
+            return returnValue;
+        }
+
+        if (urlIsAlias)
+        {
+            var store = this.getStore();
+            var aliasName = url.toLowerCase();
+            url = store.getItem(aliasName);
+            if (url === undefined)
+            {
+                this.log("aliasNotFound", [aliasName], [context, "error"]);
+                return returnValue;
+            }
+        }
+
+        // if the URL is null, we delete the alias
+        if (newAlias !== undefined && url === null)
+        {
+            var store = this.getStore();
+            if (store.getItem(newAlias) === undefined)
+            {
+                this.log("aliasNotFound", [newAlias], [context, "error"]);
+                return returnValue;
+            }
+
+            store.removeItem(newAlias);
+            this.log("aliasRemoved", [newAlias], [context, "info"]);
+            return returnValue;
+        }
+        var loadingMsgRow = this.log("Loading", [], [context, "loading", true], true);
+        var onSuccess = this.onSuccess.bind(this, newAlias, context, loadingMsgRow);
+        var onError = Obj.bindFixed(this.onError, this, context, url, loadingMsgRow);
+        this.evaluateRemoteScript(url, context, onSuccess, onError, loadingMsgRow);
+
+        return returnValue;
+    },
+
+    evaluateRemoteScript: function(url, context, successFunction, errorFunction, loadingMsgRow)
+    {
+        var xhr = new XMLHttpRequest({ mozAnon: true, timeout:30});
+        var acceptedSchemes = ["http", "https"];
+        var absoluteURL = context.browser.currentURI.resolve(url);
+
+        xhr.onload = function()
+        {
+            if (xhr.status !== 200)
+                return errorFunction.apply(this, arguments);
+            var codeToEval = xhr.responseText;
+            Firebug.CommandLine.evaluateInWebPage(codeToEval, context);
+            if (successFunction)
+                successFunction(xhr);
+        }
+
+        if (errorFunction)
+        {
+            xhr.ontimeout = xhr.onerror = errorFunction;
+        }
+
+        try
+        {
+            xhr.open("GET", absoluteURL, true);
+        }
+        catch(ex)
+        {
+            this.clearLoadingMessage(loadingMsgRow);
+            if (ex.name === "NS_ERROR_UNKNOWN_PROTOCOL")
+            {
+                this.log("invalidRequestProtocol", [], [context, "error"]);
+                return;
+            }
+            throw ex;
+        }
+
+        if (!~acceptedSchemes.indexOf(xhr.channel.URI.scheme))
+        {
+            this.log("invalidRequestProtocol", [], [context, "error"]);
+            this.clearLoadingMessage(loadingMsgRow);
+            return;
+        }
+
+        xhr.send(null);
+
+        // xxxFlorent: TODO show XHR progress
+    }
+};
+
+// ********************************************************************************************* //
+// Command Handler
+
+function onCommand(context, args)
+{
+    if (args.length === 0)
+        return CommandLineIncludeRep.displayAliases(context);
+
+    var self = CommandLineInclude;
+    Array.unshift(args, context);
+    return CommandLineInclude.include.apply(self, args);
+}
+
+// ********************************************************************************************* //
+// Local Helpers
+
+function IncludeEditor(doc)
+{
+    Firebug.InlineEditor.call(this, doc);
+}
+
+IncludeEditor.prototype = domplate(Firebug.InlineEditor.prototype,
+{
+    endEditing: function(target, value, cancel)
+    {
+        if (cancel)
+            return;
+
+        var context = Firebug.currentContext;
+        if (Css.hasClass(target, "aliasName"))
+            this.updateAliasName(target, value, context);
+        else if (Css.hasClass(target, "url"))
+            this.updateURL(target, value, context);
+    },
+
+    updateURL: function(target, value, context)
+    {
+        var tr = Dom.getAncestorByTagName(target, "tr");
+        var aliasName = tr.querySelector(".aliasName").textContent;
+        CommandLineInclude.include(context, value, aliasName, {"onlyUpdate":true});
+        target.textContent = value;
+    },
+
+    updateAliasName: function(target, value, context)
+    {
+        var oldAliasName = target.textContent;
+        var store = CommandLineInclude.getStore();
+        var url = store.getItem(oldAliasName);
+        store.removeItem(oldAliasName);
+        store.setItem(value, url);
+        target.dataset.aliasname = value;
+        target.textContent = value;
+    }
+});
+
+// ********************************************************************************************* //
+// Registration
+
+Firebug.registerCommand("include", {
+    handler: onCommand,
+    description: Locale.$STR("console.cmd.help.include"),
+    helpUrl: "http://getfirebug.com/wiki/index.php/include"
+});
+
+Firebug.registerRep(CommandLineIncludeRep);
+
+return CommandLineInclude;
+
+// ********************************************************************************************* //
+}});
diff --git a/trace/FBTrace/chrome/firebug/content/console/commandLinePopup.js b/trace/FBTrace/chrome/firebug/content/console/commandLinePopup.js
index baf80b6..ab7d556 100644
--- a/trace/FBTrace/chrome/firebug/content/console/commandLinePopup.js
+++ b/trace/FBTrace/chrome/firebug/content/console/commandLinePopup.js
@@ -158,7 +158,7 @@ Firebug.CommandLine.Popup = Obj.extend(Firebug.Module,
 
         // If all the visual parts are already visible then bail out.
         if (visible && !Dom.isCollapsed(popup) && !Dom.isCollapsed(splitter) &&
-            !Dom.isCollapsed(cmdbox) && !Dom.isCollapsed(toggle))
+            !Dom.isCollapsed(cmdbox) && Dom.isCollapsed(toggle))
             return;
 
         Dom.collapse(popup, !visible);
diff --git a/trace/FBTrace/chrome/firebug/content/console/console.js b/trace/FBTrace/chrome/firebug/content/console/console.js
index cc47a06..6d42589 100644
--- a/trace/FBTrace/chrome/firebug/content/console/console.js
+++ b/trace/FBTrace/chrome/firebug/content/console/console.js
@@ -13,6 +13,8 @@ define([
     "firebug/chrome/searchBox",
     "firebug/console/consolePanel",
     "firebug/console/commandEditor",
+    "firebug/console/functionMonitor",
+    "firebug/console/performanceTiming",
 ],
 function(Obj, Firebug, Firefox, Events, Win, Search, Xml, Options) {
 
@@ -39,17 +41,20 @@ Firebug.ConsoleBase =
     logFormatted: function(objects, context, className, noThrottle, sourceLink)
     {
         Events.dispatch(this.fbListeners,"logFormatted",[context, objects, className, sourceLink]);
-        return this.logRow(appendFormatted, objects, context, className, null, sourceLink, noThrottle);
+        return this.logRow(appendFormatted, objects, context, className, null, sourceLink,
+            noThrottle);
     },
 
     openGroup: function(objects, context, className, rep, noThrottle, sourceLink, noPush)
     {
-        return this.logRow(appendOpenGroup, objects, context, className, rep, sourceLink, noThrottle);
+        return this.logRow(appendOpenGroup, objects, context, className, rep, sourceLink,
+            noThrottle);
     },
 
     openCollapsedGroup: function(objects, context, className, rep, noThrottle, sourceLink, noPush)
     {
-        return this.logRow(appendCollapsedGroup, objects, context, className, rep, sourceLink, noThrottle);
+        return this.logRow(appendCollapsedGroup, objects, context, className, rep, sourceLink,
+            noThrottle);
     },
 
     closeGroup: function(context, noThrottle)
@@ -405,22 +410,6 @@ Firebug.Console = Obj.extend(ActivableConsole,
     },
 
     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-    // Firebug.Debugger listener
-
-    onMonitorScript: function(context, frame)
-    {
-        Firebug.Console.log(frame, context);
-    },
-
-    onFunctionCall: function(context, frame, depth, calling)
-    {
-        if (calling)
-            Firebug.Console.openGroup([frame, "depth:"+depth], context);
-        else
-            Firebug.Console.closeGroup(context);
-    },
-
-    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
     // BTI
 
     /**
diff --git a/trace/FBTrace/chrome/firebug/content/console/consolePanel.js b/trace/FBTrace/chrome/firebug/content/console/consolePanel.js
index 5189047..20778b8 100644
--- a/trace/FBTrace/chrome/firebug/content/console/consolePanel.js
+++ b/trace/FBTrace/chrome/firebug/content/console/consolePanel.js
@@ -155,12 +155,12 @@ Firebug.ConsolePanel.prototype = Obj.extend(Firebug.ActivablePanel,
         if (state)
             wasScrolledToBottom = state.wasScrolledToBottom;
 
-        if (typeof(wasScrolledToBottom) == "boolean")
+        if (typeof wasScrolledToBottom == "boolean")
         {
             this.wasScrolledToBottom = wasScrolledToBottom;
             delete state.wasScrolledToBottom;
         }
-        else
+        else if (typeof this.wasScrolledToBottom != "boolean")
         {
             // If the previous state doesn't says where to scroll,
             // scroll to the bottom by default.
@@ -250,8 +250,8 @@ Firebug.ConsolePanel.prototype = Obj.extend(Firebug.ActivablePanel,
                 "console.option.tip.Show_JavaScript_Warnings"),
             Menu.optionMenu("ShowCSSErrors", "showCSSErrors",
                 "console.option.tip.Show_CSS_Errors"),
-            Menu.optionMenu("ShowXMLErrors", "showXMLErrors",
-                "console.option.tip.Show_XML_Errors"),
+            Menu.optionMenu("ShowXMLHTMLErrors", "showXMLErrors",
+                "console.option.tip.Show_XML_HTML_Errors"),
             Menu.optionMenu("ShowXMLHttpRequests", "showXMLHttpRequests",
                 "console.option.tip.Show_XMLHttpRequests"),
             Menu.optionMenu("ShowChromeErrors", "showChromeErrors",
@@ -294,8 +294,11 @@ Firebug.ConsolePanel.prototype = Obj.extend(Firebug.ActivablePanel,
             type: "checkbox",
             checked: strictValue,
             tooltiptext: "console.option.tip.Show_Strict_Warnings",
-            command: Obj.bindFixed(Options.setPref, Options,
-                strictDomain, strictName, !strictValue)
+            command: function()
+            {
+                var checked = this.hasAttribute("checked");
+                Options.setPref(strictDomain, strictName, checked);
+            }
         };
     },
 
@@ -497,9 +500,11 @@ Firebug.ConsolePanel.prototype = Obj.extend(Firebug.ActivablePanel,
     {
         function logText(text, row)
         {
-            Css.setClass(row, "logRowHint");
+            var nodeSpan = row.ownerDocument.createElement("span");
+            Css.setClass(nodeSpan, "logRowHint");
             var node = row.ownerDocument.createTextNode(text);
-            row.appendChild(node);
+            row.appendChild(nodeSpan);
+            nodeSpan.appendChild(node);
         }
 
         function logTextNode(text, row)
@@ -563,23 +568,35 @@ Firebug.ConsolePanel.prototype = Obj.extend(Firebug.ActivablePanel,
             }
         }
 
+        // Last CSS style defined using "%c" that should be applied on
+        // created log-row parts (elements). See issue 6064.
+        // Example: console.log('%cred-text %cgreen-text', 'color:red', 'color:green');
+        var lastStyle;
+
         for (var i = 0; i < parts.length; ++i)
         {
+            var node;
             var part = parts[i];
             if (part && typeof(part) == "object")
             {
                 var object = objects[objIndex++];
                 if (part.type == "%c")
-                    row.setAttribute("style", object.toString());
+                    lastStyle = object.toString();
                 else if (typeof(object) != "undefined")
-                    this.appendObject(object, row, part.rep);
+                    node = this.appendObject(object, row, part.rep);
                 else
-                    this.appendObject(part.type, row, FirebugReps.Text);
+                    node = this.appendObject(part.type, row, FirebugReps.Text);
             }
             else
             {
-                FirebugReps.Text.tag.append({object: part}, row);
+                node = FirebugReps.Text.tag.append({object: part}, row);
             }
+
+            // Apply custom style if available.
+            if (lastStyle && node)
+                node.setAttribute("style", lastStyle);
+
+            node = null;
         }
 
         for (var i = objIndex; i < objects.length; ++i)
@@ -748,6 +765,16 @@ Firebug.ConsolePanel.prototype = Obj.extend(Firebug.ActivablePanel,
         if (this.wasScrolledToBottom)
             Dom.scrollToBottom(this.panelNode);
     },
+
+    showInfoTip: function(infoTip, target, x, y)
+    {
+        var object = Firebug.getRepObject(target);
+        var rep = Firebug.getRep(object, this.context);
+        if (!rep)
+            return false;
+
+        return rep.showInfoTip(infoTip, target, x, y);
+    }
 });
 
 // ********************************************************************************************* //
diff --git a/trace/FBTrace/chrome/firebug/content/console/errors.js b/trace/FBTrace/chrome/firebug/content/console/errors.js
index 7f3c440..93a33d3 100644
--- a/trace/FBTrace/chrome/firebug/content/console/errors.js
+++ b/trace/FBTrace/chrome/firebug/content/console/errors.js
@@ -146,6 +146,9 @@ var Errors = Firebug.Errors = Obj.extend(Firebug.Module,
 
     startObserving: function()
     {
+        if (this.isObserving)
+            return;
+
         if (FBTrace.DBG_ERRORLOG)
             FBTrace.sysout("Errors.startObserving");
 
@@ -157,6 +160,9 @@ var Errors = Firebug.Errors = Obj.extend(Firebug.Module,
 
     stopObserving: function()
     {
+        if (!this.isObserving)
+            return;
+
         if (FBTrace.DBG_ERRORLOG)
             FBTrace.sysout("Errors.stopObserving");
 
@@ -371,8 +377,12 @@ var Errors = Firebug.Errors = Obj.extend(Firebug.Module,
             correctLineNumbersOnExceptions(object, error);
         }
 
-        if (Firebug.showStackTrace && Firebug.errorStackTrace)
+        if (Firebug.errorStackTrace)
+        {
             error.correctWithStackTrace(Firebug.errorStackTrace);
+            if (!Firebug.showStackTrace)
+                error.trace = null;
+        }
 
         var msgId = lessTalkMoreAction(context, object, isWarning);
         if (!msgId)
@@ -666,6 +676,7 @@ const categoryMap =
     "DOM": "js",
     "Events": "js",
     "CSS": "css",
+    "HTML": "xml",
     "XML": "xml",
     "malformed-xml": "xml"
 };
@@ -704,9 +715,10 @@ function whyNotShown(url, categoryList, isWarning)
         {
             return "showCSSErrors";
         }
-        else if ((category == "XML" || category == "malformed-xml" ) && !Firebug.showXMLErrors)
+        else if ((category == "HTML" || category == "XML" || category == "malformed-xml" ) &&
+            !Firebug.showXMLErrors)
         {
-            return "showXMLErors";
+            return "showXMLErrors";
         }
         else if ((category == "javascript" || category == "JavaScript" || category == "DOM")
                 && !isWarning && !Firebug.showJSErrors)
diff --git a/trace/FBTrace/chrome/firebug/content/console/eventMonitor.js b/trace/FBTrace/chrome/firebug/content/console/eventMonitor.js
index e5ba4bd..42e6d4d 100644
--- a/trace/FBTrace/chrome/firebug/content/console/eventMonitor.js
+++ b/trace/FBTrace/chrome/firebug/content/console/eventMonitor.js
@@ -5,13 +5,14 @@ define([
     "firebug/firebug",
     "firebug/lib/trace",
     "firebug/lib/events",
+    "firebug/lib/locale",
 ],
-function(Obj, Firebug, FBTrace, Events) {
+function(Obj, Firebug, FBTrace, Events, Locale) {
 
 // ********************************************************************************************* //
 // EventMonitor Module
 
-Firebug.EventMonitor = Obj.extend(Firebug.Module,
+var EventMonitor = Obj.extend(Firebug.Module,
 {
     dispatchName: "eventMonitor",
 
@@ -52,7 +53,12 @@ Firebug.EventMonitor = Obj.extend(Firebug.Module,
         if (object && object.addEventListener)
         {
             if (!context.onMonitorEvent)
-                context.onMonitorEvent = function(event) { Firebug.Console.log(event, context); };
+            {
+                var self = this;
+                context.onMonitorEvent = function(event) {
+                    self.onMonitorEvent(event, context);
+                };
+            }
 
             if (!context.eventsMonitored)
                 context.eventsMonitored = [];
@@ -88,7 +94,7 @@ Firebug.EventMonitor = Obj.extend(Firebug.Module,
                 if (eventsMonitored[j].object == object && eventsMonitored[j].type == eventTypes[i])
                 {
                     eventsMonitored.splice(j, 1);
-    
+
                     Events.removeEventListener(object, eventTypes[i], context.onMonitorEvent, false);
                     break;
                 }
@@ -127,22 +133,44 @@ Firebug.EventMonitor = Obj.extend(Firebug.Module,
             if (!monitored)
             {
                 if (FBTrace.DBG_EVENTS)
-                    FBTrace.sysout("EventMonitor.areEventsMonitored - Events not monitored for '"+eventTypes[i]+"'");
-                
+                {
+                    FBTrace.sysout("EventMonitor.areEventsMonitored - Events not monitored for '" +
+                        eventTypes[i] + "'");
+                }
+
                 return false;
             }
             else
             {
                 if (FBTrace.DBG_EVENTS)
-                    FBTrace.sysout("EventMonitor.areEventsMonitored - Events monitored for '"+eventTypes[i]+"'");
+                {
+                    FBTrace.sysout("EventMonitor.areEventsMonitored - Events monitored for '" +
+                        eventTypes[i] + "'");
+                }
             }
         }
 
         return true;
+    },
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+    // Logging
+
+    onMonitorEvent: function(event, context)
+    {
+        var obj = new EventMonitor.EventLog(event);
+        Firebug.Console.log(obj, context);
     }
 });
 
-//********************************************************************************************* //
+// ********************************************************************************************* //
+
+EventMonitor.EventLog = function(event)
+{
+    this.event = event;
+}
+
+// ********************************************************************************************* //
 // Helpers
 
 function getMonitoredEventTypes(types)
@@ -180,11 +208,44 @@ function getMonitoredEventTypes(types)
 }
 
 // ********************************************************************************************* //
-// Registration & Export
+// CommandLine Support
+
+function monitorEvents(context, args)
+{
+    var object = args[0];
+    var types = args[1];
+
+    EventMonitor.monitorEvents(object, types, context);
+    return Firebug.Console.getDefaultReturnValue(context.window);
+}
+
+function unmonitorEvents(context, args)
+{
+    var object = args[0];
+    var types = args[1];
+
+    EventMonitor.unmonitorEvents(object, types, context);
+    return Firebug.Console.getDefaultReturnValue(context.window);
+}
+
+// ********************************************************************************************* //
+// Registration
+
+Firebug.registerModule(EventMonitor);
+
+Firebug.registerCommand("monitorEvents", {
+    handler: monitorEvents.bind(this),
+    helpUrl: "http://getfirebug.com/wiki/index.php/monitorEvents",
+    description: Locale.$STR("console.cmd.help.monitorEvents")
+})
 
-Firebug.registerModule(Firebug.EventMonitor);
+Firebug.registerCommand("unmonitorEvents", {
+    handler: unmonitorEvents.bind(this),
+    helpUrl: "http://getfirebug.com/wiki/index.php/unmonitorEvents",
+    description: Locale.$STR("console.cmd.help.unmonitorEvents")
+})
 
-return Firebug.EventMonitor;
+return EventMonitor;
 
 // ********************************************************************************************* //
 });
diff --git a/trace/FBTrace/chrome/firebug/content/console/functionMonitor.js b/trace/FBTrace/chrome/firebug/content/console/functionMonitor.js
new file mode 100644
index 0000000..9957856
--- /dev/null
+++ b/trace/FBTrace/chrome/firebug/content/console/functionMonitor.js
@@ -0,0 +1,191 @@
+/* See license.txt for terms of usage */
+
+define([
+    "firebug/lib/trace",
+    "firebug/lib/object",
+    "firebug/lib/domplate",
+    "firebug/chrome/reps",
+    "firebug/js/stackFrame",
+    "firebug/lib/events",
+    "firebug/lib/css",
+    "firebug/lib/dom",
+    "firebug/lib/url",
+],
+function(FBTrace, Obj, Domplate, Reps, StackFrame, Events, Css, Dom, Url) { with (Domplate) {
+
+// ********************************************************************************************* //
+// Function Monitor
+
+var FunctionMonitor = Obj.extend(Firebug.Module,
+{
+    dispatchName: "functionMonitor",
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+    // Module
+
+    initialize: function()
+    {
+        Firebug.Module.initialize.apply(this, arguments);
+        Firebug.connection.addListener(this);
+    },
+
+    shutdown: function()
+    {
+        Firebug.connection.removeListener(this);
+        Firebug.Module.shutdown.apply(this, arguments);
+    },
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+    // Firebug.Debugger listener
+
+    onMonitorScript: function(context, frame)
+    {
+        var stackTrace = StackFrame.buildStackTrace(frame);
+        Firebug.Console.log(new FunctionLog(frame, stackTrace), context);
+    },
+
+    onFunctionCall: function(context, frame, depth, calling)
+    {
+        //var url = Url.normalizeURL(frame.script.fileName);
+        //var sourceFile = context.sourceFileMap[url];
+        // Firebug.errorStackTrace = StackFrame.getCorrectedStackTrace(frame, context);
+        //var sourceFile = Firebug.SourceFile.getSourceFileByScript(context, frame.script);
+        if (Url.isSystemURL(Url.normalizeURL(frame.script.fileName)))
+            return;
+
+        // xxxHonza: traceCall and traceCallAll need to be fixed yet.
+        FBTrace.sysout("functionMonitor.onFunctionCall; ", sourceFile);
+
+        if (calling)
+            Firebug.Console.openGroup([frame, "depth:" + depth], context);
+        else
+            Firebug.Console.closeGroup(context);
+    },
+});
+
+// ********************************************************************************************* //
+// Rep Object
+
+function FunctionLog(frame, stackTrace)
+{
+    this.frame = frame;
+    this.stackTrace = stackTrace;
+}
+
+// ********************************************************************************************* //
+// Function Monitor Rep
+
+var FunctionMonitorRep = domplate(Firebug.Rep,
+{
+    className: "functionCall",
+
+    tag:
+        Reps.OBJECTBLOCK({$hasTwisty: "$object|hasStackTrace", _repObject: "$object",
+            onclick: "$onToggleStackTrace"},
+            A({"class": "objectLink functionCallTitle a11yFocus", _repObject: "$object"},
+                "$object|getCallName"
+            ),
+            SPAN("("),
+            SPAN({"class": "arguments"},
+                FOR("arg", "$object|argIterator",
+                    SPAN({"class": "argName"}, "$arg.name"),
+                    SPAN("="),
+                    TAG("$arg.tag", {object: "$arg.value"}),
+                    SPAN({"class": "arrayComma"}, "$arg.delim")
+                )
+            ),
+            SPAN(")"),
+            SPAN({"class": "objectLink-sourceLink objectLink a11yFocus",
+                _repObject: "$object|getSourceLink",
+                role: "link"},
+                "$object|getSourceLinkTitle"),
+            DIV({"class": "stackTrace"})
+        ),
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+    hasStackTrace: function(object)
+    {
+        return true;
+    },
+
+    getTitle: function(object)
+    {
+        return object.frame.getFunctionName();
+    },
+
+    getCallName: function(object)
+    {
+        return this.getTitle(object);
+    },
+
+    getSourceLink: function(object)
+    {
+        return Reps.StackFrame.getSourceLink(object.frame);
+    },
+
+    getSourceLinkTitle: function(object)
+    {
+        return Reps.StackFrame.getSourceLinkTitle(object.frame);
+    },
+
+    argIterator: function(object)
+    {
+        return Reps.StackFrame.argIterator(object.frame);
+    },
+
+    onToggleStackTrace: function(event)
+    {
+        var target = event.originalTarget;
+
+        // Only clicking on the expand button or the function title actually expands
+        // the function call log. All other clicks keep default behavior
+        if (!(Css.hasClass(target, "objectBox-functionCall") ||
+            Css.hasClass(target, "functionCallTitle")))
+        {
+            return;
+        }
+
+        var objectBox = Dom.getAncestorByClass(target, "objectBox-functionCall");
+        if (!objectBox)
+            return;
+
+        var traceBox = objectBox.getElementsByClassName("stackTrace").item(0);
+        Css.toggleClass(traceBox, "opened");
+
+        if (Css.hasClass(traceBox, "opened"))
+        {
+            var functionCall = objectBox.repObject;
+            Reps.StackTrace.tag.append({object: functionCall.stackTrace}, traceBox);
+        }
+        else
+        {
+            Dom.clearNode(traceBox);
+        }
+
+        Events.cancelEvent(event);
+    },
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+    supportsObject: function(object, type)
+    {
+        return object instanceof FunctionLog;
+    },
+
+    getRealObject: function(object)
+    {
+        return object.frame;
+    },
+});
+
+// ********************************************************************************************* //
+// Registration
+
+Firebug.registerModule(FunctionMonitor);
+Firebug.registerRep(FunctionMonitorRep);
+
+return FunctionMonitor;
+
+// ********************************************************************************************* //
+}});
diff --git a/trace/FBTrace/chrome/firebug/content/console/performanceTiming.js b/trace/FBTrace/chrome/firebug/content/console/performanceTiming.js
new file mode 100644
index 0000000..b601e27
--- /dev/null
+++ b/trace/FBTrace/chrome/firebug/content/console/performanceTiming.js
@@ -0,0 +1,630 @@
+/* See license.txt for terms of usage */
+
+define([
+    "firebug/firebug",
+    "firebug/lib/trace",
+    "firebug/lib/domplate",
+    "firebug/lib/object",
+    "firebug/lib/locale",
+    "firebug/lib/dom",
+    "firebug/lib/events",
+    "firebug/lib/string",
+    "firebug/lib/wrapper",
+    "firebug/lib/css",
+],
+function(Firebug, FBTrace, Domplate, Obj, Locale, Dom, Events, Str, Wrapper, Css) {
+with (Domplate) {
+
+// ********************************************************************************************* //
+// Docs
+
+// See http://www.w3.org/TR/navigation-timing/
+
+// ********************************************************************************************* //
+// Constants
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+// List of timing properties in performance.timing structure.
+var timingProps = [
+    "connectEnd",
+    "connectStart",
+    "domComplete",
+    "domContentLoadedEventEnd",
+    "domContentLoadedEventStart",
+    "domInteractive",
+    "domLoading",
+    "domainLookupEnd",
+    "domainLookupStart",
+    "fetchStart",
+    "loadEventEnd",
+    "loadEventStart",
+    "navigationStart",
+    "redirectCount",
+    "redirectEnd",
+    "redirectStart",
+    "requestStart",
+    "responseEnd",
+    "responseStart",
+    "unloadEventEnd",
+    "unloadEventStart",
+];
+
+// ********************************************************************************************* //
+// Module
+
+var PerformanceTimingModule = Obj.extend(Firebug.Module,
+{
+    initialize: function(prefDomain, prefNames)
+    {
+        Firebug.Module.initialize.apply(this, arguments);
+        Firebug.Console.addListener(ConsoleListener);
+    },
+
+    shutdown: function()
+    {
+        Firebug.Module.shutdown.apply(this, arguments);
+        Firebug.Console.removeListener(ConsoleListener);
+    },
+});
+
+// ********************************************************************************************* //
+// Domplate
+
+/**
+ * This template is used to render the timing waterfall graph.
+ */
+var PerformanceTimingRep = domplate(Firebug.Rep,
+/** @lends PerformanceTimingRep */
+{
+    className: "perfTiming",
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+    tag:
+        TABLE({"class": "perfTimingTable", cellspacing: 0, cellpadding: 0, width: "100%",
+            "role": "grid", _repObject: "$object"},
+            TBODY({"class": "perfTimingTbody", "role": "presentation"},
+                FOR("bar", "$object.bars",
+                    TR(
+                        TD(
+                            DIV({"class": "perfTimingBox"},
+                                DIV({"class": "perfTimingBar $bar.className",
+                                    style: "left: $bar.left%; width: $bar.width%"},
+                                    SPAN({"class": "perfTimingBarLabel"}, "$bar.label")
+                                ),
+                                DIV({"class": "perfTimingEvent domLoading",
+                                    style: "left: $bar.domLoading%;"}
+                                ),
+                                DIV({"class": "perfTimingEvent domInteractive",
+                                    style: "left: $bar.domInteractive%;"}
+                                ),
+                                DIV({"class": "perfTimingEvent domContentLoaded",
+                                    style: "left: $bar.domContentLoaded%;"}
+                                ),
+                                DIV({"class": "perfTimingEvent onLoad",
+                                    style: "left: $bar.onLoad%;"}
+                                ),
+                                DIV({"class": "perfTimingEvent cursor"})
+                            )
+                        )
+                    )
+                )
+            )
+        ),
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+    getRealObject: function(object)
+    {
+        return Wrapper.unwrapObject(object.timing);
+    },
+
+    supportsObject: function(object, type)
+    {
+        return (object instanceof PerfTimingObj);
+    },
+
+    getContextMenuItems: function(object, target, context)
+    {
+        return [];
+    },
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+    showInfoTip: function(infoTip, target, x, y)
+    {
+        var table = Dom.getAncestorByClass(target, "perfTimingTable");
+        if (!table)
+            return false;
+
+        var timingObj = table.repObject;
+        return PerfInfoTip.render(timingObj.timing, infoTip);
+    }
+});
+
+// ********************************************************************************************* //
+// InfoTip
+
+/**
+ * Hovering mouse over the waterfall graph shows an infotip. This template is responsible
+ * for rendering its content.
+ */
+var PerfInfoTip = domplate(Firebug.Rep,
+/** @lends PerfInfoTip */
+{
+    tableTag:
+        TABLE({"class": "timeInfoTip", "id": "fbPerfTimingInfoTip"},
+            TBODY()
+        ),
+
+    timingsTag:
+        FOR("bar", "$bars",
+            TR({"class": "timeInfoTipRow", $collapsed: "$bar|hideBar"},
+                TD({"class": "timeInfoTipBar $bar|getClassName"}),
+                TD({"class": "timeInfoTipCell startTime"},
+                    "$bar.start|formatStartTime"
+                ),
+                TD({"class": "timeInfoTipCell elapsedTime"},
+                    "$bar.elapsed|formatTime"
+                ),
+                TD("$bar|getLabel")
+            )
+        ),
+
+    separatorTag:
+        TR(
+            TD({"class": "timeInfoTipSeparator", "colspan": 4, "height": "10px"},
+                SPAN("$label")
+            )
+        ),
+
+    eventsTag:
+        FOR("event", "$events",
+            TR({"class": "timeInfoTipEventRow"},
+                TD({"class": "timeInfoTipBar", align: "center"},
+                    DIV({"class": "$event|getClassName timeInfoTipEventBar"})
+                ),
+                TD("$event.start|formatStartTime"),
+                TD({"class": "timeInfotTipEventName", "colspan": 2},
+                    "$event|getTimeStampLabel"
+                )
+            )
+        ),
+
+    hideBar: function(obj)
+    {
+        return !obj.elapsed && obj.className == "redirect";
+    },
+
+    getClassName: function(obj)
+    {
+        return obj.className;
+    },
+
+    formatTime: function(time)
+    {
+        return Str.formatTime(time);
+    },
+
+    formatStartTime: function(time)
+    {
+        var label = Str.formatTime(time);
+        if (!time)
+            return label;
+
+        return (time > 0 ? "+" : "") + label;
+    },
+
+    getLabel: function(obj)
+    {
+        return Locale.$STR("perftiming." + obj.label);
+    },
+
+    getTimeStampLabel: function(obj)
+    {
+        return obj.name;
+    },
+
+    render: function(timing, parentNode)
+    {
+        var infoTip = Firebug.NetMonitor.TimeInfoTip.tableTag.replace({}, parentNode);
+
+        // Insert top description.
+        this.separatorTag.insertRows({label: Locale.$STR("perftiming.bars.label")},
+            infoTip.firstChild);
+
+        // Insert request timing info.
+        var bars = calculateBars(timing);
+        this.timingsTag.insertRows({bars: bars}, infoTip.firstChild);
+
+        var t = timing;
+
+        var events = [];
+        events.push({
+            name: "DOM Loading",
+            className: "domLoading",
+            start: t.domLoading - t.navigationStart
+        });
+
+        events.push({
+            name: "DOM Interactive",
+            className: "domInteractive",
+            start: t.domInteractive - t.navigationStart,
+        });
+
+        events.push({
+            name: "DOMContentLoaded",
+            className: "domContentLoaded",
+            start: t.domContentLoadedEventStart - t.navigationStart,
+        });
+
+        events.push({
+            name: "load",
+            className: "onLoad",
+            start: t.loadEventStart - t.navigationStart,
+        })
+
+        // Insert separator.
+        this.separatorTag.insertRows({label: Locale.$STR("requestinfo.timings.label")},
+            infoTip.firstChild);
+
+        this.eventsTag.insertRows({events: events}, infoTip.firstChild);
+
+        return true;
+    }
+});
+
+// ********************************************************************************************* //
+// Rep Object
+
+function PerfTimingObj(bars, timing)
+{
+    this.bars = bars;
+    this.timing = timing;
+}
+
+// ********************************************************************************************* //
+
+/**
+ * Console listener is responsible for rendering the Performance visualization every time
+ * the user logs 'performance.timing' on the command line.
+ */
+var ConsoleListener =
+/** @lends ConsoleListener */
+{
+    tag:
+        DIV({_repObject: "$object"},
+            DIV({"class": "documentCookieBody"})
+        ),
+
+    log: function(context, object, className, sourceLink)
+    {
+        if (!context || !object)
+            return;
+
+        var type = Object.prototype.toString.call(object);
+        if (type === "[object PerformanceTiming]")
+            performanceTiming(context, object);
+    },
+
+    logFormatted: function(context, objects, className, sourceLink)
+    {
+    }
+};
+
+// ********************************************************************************************* //
+// Console Logging
+
+/**
+ * This function is responsible for inserting the waterfall graph into the Console panel.
+ */
+function performanceTiming(context, timing)
+{
+    var t = timing;
+    var elapsed = t.loadEventEnd - t.navigationStart;
+
+    var objects = [];
+    var rep = PerformanceTimingRep;
+    var bars = calculateBars(t);
+
+    var result = []
+    for (var i=0; i<bars.length; i++)
+    {
+        var bar = bars[i];
+
+        // Filter our empty bars.
+        if (!bar.elapsed)
+            continue;
+
+        bar.left = calculatePos(bar.start, elapsed);
+        bar.width = calculatePos(bar.elapsed, elapsed);
+        bar.label = bar.label + " " + Str.formatTime(bar.elapsed);
+
+        result.push(bar);
+    }
+
+    // Events
+    var domLoading = calculatePos(t.domLoading - t.navigationStart, elapsed);
+    var domInteractive = calculatePos(t.domInteractive - t.navigationStart, elapsed);
+    var domContentLoaded = calculatePos(t.domContentLoadedEventStart - t.navigationStart, elapsed);
+    var onLoad = calculatePos(t.loadEventStart - t.navigationStart, elapsed);
+
+    for (var i=0; i<result.length; i++)
+    {
+        var bar = result[i];
+        bar.domLoading = domLoading;
+        bar.domInteractive = domInteractive;
+        bar.domContentLoaded = domContentLoaded;
+        bar.onLoad = onLoad;
+    }
+
+    var input = new PerfTimingObj(result, t);
+    Firebug.Console.log(input, context, "perfTiming", rep, true);
+
+    // Details
+    var row = Firebug.Console.openCollapsedGroup("perfTimingDetails", context, "perfTimingDetails",
+        DetailsCaption, true, null, true);
+    Firebug.Console.closeGroup(context, true);
+
+    var logGroupBody = row.lastChild;
+    var table = DetailsTable.tag.replace({object: t}, logGroupBody);
+    var tBody = table.lastChild;
+
+    // Iterate only known properties (these are also localized).
+    var timings = [];
+    for (var i=0; i<timingProps.length; i++)
+    {
+        var name = timingProps[i];
+        var value = t[name];
+        var startTime = value ? (value - t.navigationStart) : 0;
+        var timing = {
+            name: name,
+            timeLabel: startTime ? "+" + Str.formatTime(startTime) : 0,
+            desc: Locale.$STR("perftiming." + name),
+            time: startTime,
+        }
+        timings.push(timing);
+    }
+
+    timings.sort(function(a, b) {
+        return a.time > b.time ? 1 : -1;
+    })
+
+    DetailsEntry.tag.insertRows({timings: timings}, tBody);
+
+    return Firebug.Console.getDefaultReturnValue(context.window);
+}
+
+// ********************************************************************************************* //
+// Detailed Log
+
+/**
+ * A capation for detailed performance timing info.
+ */
+var DetailsCaption = domplate(
+/** @lends DetailsCaption */
+{
+    tag:
+        SPAN({"class": "timingTitle"},
+            SPAN({"class": "timingCaption"},
+                Locale.$STR("perftiming.details_title")
+            ),
+            SPAN({"class": "timingCaptionDesc"},
+                Locale.$STR("perftiming.details_title_desc")
+            )
+        )
+});
+
+// ********************************************************************************************* //
+
+/**
+ * This template represents a table with detailed timing info.
+ */
+var DetailsTable = domplate(
+/** @lends DetailsTable */
+{
+    tag:
+        TABLE({"class": "timingTable", cellspacing: 0, cellpadding: 0, width: "100%",
+            "role": "grid", _repObject: "$object"},
+            THEAD({"class": "timingThead", "role": "presentation"},
+                TR({"class": "headerRow focusRow timingRow subFocusRow", "role": "row"},
+                    TH({"class": "headerCell a11yFocus", "role": "columnheader", width: "10%"},
+                        DIV({"class": "headerCellBox"},
+                            Locale.$STR("Name")
+                        )
+                    ),
+                    TH({"class": "headerCell a11yFocus", "role": "columnheader", width: "10%"},
+                        DIV({"class": "headerCellBox"},
+                            Locale.$STR("Time")
+                        )
+                    ),
+                    TH({"class": "headerCell a11yFocus", "role": "columnheader", width: "70%"},
+                        DIV({"class": "headerCellBox"},
+                            Locale.$STR("Description")
+                        )
+                    )
+                )
+            ),
+            TBODY({"class": "perfTimingTbody", "role": "presentation"}
+            )
+        ),
+});
+
+// ********************************************************************************************* //
+
+/**
+ * A row within detailed performance timing info.
+ */
+var DetailsEntry = domplate(
+/** @lends DetailsEntry */
+{
+    tag:
+        FOR("timing", "$timings",
+            TR({"class": "focusRow timingRow subFocusRow", "role": "row", _repObject: "$timing",
+                onmousemove: "$onMouseMove", onmouseout: "$onMouseOut"},
+                TD({"class": "a11yFocus timingCell timingName", "role": "gridcell"},
+                    "$timing.name"
+                ),
+                TD({"class": "a11yFocus timingCell timingTime", "role": "gridcell"},
+                    "$timing.timeLabel"
+                ),
+                TD({"class": "a11yFocus timingCell timingDesc", "role": "gridcell"},
+                    "$timing.desc"
+                )
+            )
+        ),
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+    onMouseMove: function(event)
+    {
+        var row = Dom.getAncestorByClass(event.target, "timingRow");
+        if (!row)
+            return;
+
+        var log = Dom.getAncestorByClass(row, "logRow-perfTimingDetails");
+        var graph = log.previousSibling;
+        if (!Css.hasClass(graph, "logRow-perfTiming"))
+            return;
+
+        var table = Dom.getAncestorByClass(row, "timingTable");
+        var timing = table.repObject;
+
+        var elapsed = timing.loadEventEnd - timing.navigationStart;
+        var startTime = row.repObject.time;
+
+        var tBody = graph.getElementsByClassName("perfTimingTbody")[0];
+        var rows = tBody.getElementsByTagName("tr");
+        for (var i=0; i<rows.length; i++)
+        {
+            var row = rows[i];
+            var cursor = row.getElementsByClassName("cursor")[0];
+
+            Dom.hide(cursor, false);
+            cursor.style.left = calculatePos(startTime, elapsed) + "%";
+        }
+    },
+
+    onMouseOut: function(event)
+    {
+        var row = Dom.getAncestorByClass(event.target, "timingRow");
+        if (!row)
+            return;
+
+        var log = Dom.getAncestorByClass(row, "logRow-perfTimingDetails");
+        var graph = log.previousSibling;
+        if (!Css.hasClass(graph, "logRow-perfTiming"))
+            return;
+
+        var tBody = graph.getElementsByClassName("perfTimingTbody")[0];
+        var rows = tBody.getElementsByTagName("tr");
+        for (var i=0; i<rows.length; i++)
+        {
+            var row = rows[i];
+            var cursor = row.getElementsByClassName("cursor")[0];
+            Dom.hide(cursor, true);
+        }
+    }
+});
+
+// ********************************************************************************************* //
+// Helpers
+
+function calculatePos(time, elapsed)
+{
+    return Math.round((time / elapsed) * 100);
+}
+
+function calculateBars(timing)
+{
+    var result = [];
+    var t = timing;
+
+    // Page Load bar
+    result.push({
+        className: "pageLoad",
+        start: 0,
+        elapsed: t.loadEventEnd - t.navigationStart,
+        label: Locale.$STR("Page Load"),
+    });
+
+    // Redirect
+    result.push({
+        className: "redirect",
+        start: t.redirectStart ? t.redirectStart - t.navigationStart : 0,
+        elapsed: t.redirectStart ? t.redirectEnd - t.redirectStart : 0,
+        label: Locale.$STR("Redirect"),
+    });
+
+    // DNS
+    var dns = t.domainLookupEnd - t.domainLookupStart;
+    result.push({
+        className: "dns",
+        start: t.domainLookupStart - t.navigationStart,
+        elapsed: t.domainLookupEnd - t.domainLookupStart,
+        label: Locale.$STR("DNS"),
+    });
+
+    // Connect bar
+    result.push({
+        className: "connecting",
+        start: t.connectStart - t.navigationStart,
+        elapsed: t.connectEnd - t.connectStart,
+        label: Locale.$STR("Connecting"),
+    });
+
+    // Waiting bar
+    result.push({
+        className: "waiting",
+        start: t.requestStart - t.navigationStart,
+        elapsed: t.responseStart - t.requestStart,
+        label: Locale.$STR("Waiting"),
+    });
+
+    // Response bar
+    result.push({
+        className: "response",
+        start: t.responseStart - t.navigationStart,
+        elapsed: t.responseEnd - t.responseStart,
+        label: Locale.$STR("Receiving"),
+    });
+
+    // Processing bar
+    result.push({
+        className: "processing",
+        start: t.responseEnd - t.navigationStart,
+        elapsed: t.loadEventStart - t.responseEnd,
+        label: Locale.$STR("DOM Processing"),
+    });
+
+    // DOMContentLoaded
+    result.push({
+        className: "DOMContentLoaded",
+        start: t.domContentLoadedEventStart - t.navigationStart,
+        elapsed: t.domContentLoadedEventEnd - t.domContentLoadedEventStart,
+        label: Locale.$STR("DOMContentLoaded"),
+    });
+
+    // onLoad
+    result.push({
+        className: "onLoad",
+        start: t.loadEventStart - t.navigationStart,
+        elapsed: t.loadEventEnd - t.loadEventStart,
+        label: Locale.$STR("onLoad"),
+    });
+
+    return result;
+}
+
+// ********************************************************************************************* //
+// Registration
+
+Firebug.registerRep(PerformanceTimingRep);
+Firebug.registerModule(PerformanceTimingModule);
+
+return PerformanceTimingModule;
+
+// ********************************************************************************************* //
+}});
diff --git a/trace/FBTrace/chrome/firebug/content/console/profiler.js b/trace/FBTrace/chrome/firebug/content/console/profiler.js
index c6c4e12..387caab 100644
--- a/trace/FBTrace/chrome/firebug/content/console/profiler.js
+++ b/trace/FBTrace/chrome/firebug/content/console/profiler.js
@@ -172,7 +172,7 @@ Firebug.Profiler = Obj.extend(Firebug.Module,
         var sourceFileMap = context.sourceFileMap;
         if (FBTrace.DBG_PROFILER)
         {
-            for (url in sourceFileMap)
+            for (var url in sourceFileMap)
                 FBTrace.sysout("logProfileReport: "+sourceFileMap[url]+"\n");
         }
 
@@ -513,11 +513,39 @@ function ProfileCall(script, context, callCount, totalTime, totalOwnTime, minTim
 }
 
 // ********************************************************************************************* //
+// CommandLine Support
+
+function profile(context, args)
+{
+    var title = args[0];
+    Firebug.Profiler.startProfiling(context, title);
+    return Firebug.Console.getDefaultReturnValue(context.window);
+};
+
+function profileEnd(context)
+{
+    Firebug.Profiler.stopProfiling(context);
+    return Firebug.Console.getDefaultReturnValue(context.window);
+};
+
+// ********************************************************************************************* //
 // Registration
 
 Firebug.registerModule(Firebug.Profiler);
 Firebug.registerRep(Firebug.Profiler.ProfileCall);
 
+Firebug.registerCommand("profile", {
+    handler: profile.bind(this),
+    helpUrl: "http://getfirebug.com/wiki/index.php/profile",
+    description: Locale.$STR("console.cmd.help.profile")
+})
+
+Firebug.registerCommand("profileEnd", {
+    handler: profileEnd.bind(this),
+    helpUrl: "http://getfirebug.com/wiki/index.php/profileEnd",
+    description: Locale.$STR("console.cmd.help.profileEnd")
+})
+
 return Firebug.Profiler;
 
 // ********************************************************************************************* //
diff --git a/trace/FBTrace/chrome/firebug/content/cookies/cookie.js b/trace/FBTrace/chrome/firebug/content/cookies/cookie.js
index ada86f4..be7248b 100644
--- a/trace/FBTrace/chrome/firebug/content/cookies/cookie.js
+++ b/trace/FBTrace/chrome/firebug/content/cookies/cookie.js
@@ -3,6 +3,7 @@
 define([
     "firebug/lib/xpcom",
     "firebug/lib/json",
+    "firebug/lib/string",
 ],
 function(Xpcom, Json) {
 
@@ -140,7 +141,17 @@ Cookie.prototype =
         }
 
         return null;
-    }
+    },
+
+    getSize: function()
+    {
+        return this.cookie.name.length + this.cookie.value.length;
+    },
+
+    getRawSize: function()
+    {
+        return this.cookie.name.length + this.cookie.rawValue.length
+    },
 };
 
 // ********************************************************************************************* //
diff --git a/trace/FBTrace/chrome/firebug/content/cookies/cookieClipboard.js b/trace/FBTrace/chrome/firebug/content/cookies/cookieClipboard.js
index 01ed2e4..e389f33 100644
--- a/trace/FBTrace/chrome/firebug/content/cookies/cookieClipboard.js
+++ b/trace/FBTrace/chrome/firebug/content/cookies/cookieClipboard.js
@@ -100,6 +100,10 @@ var CookieClipboard = Obj.extend(Object,
     {
         var trans = Xpcom.CCIN("@mozilla.org/widget/transferable;1", "nsITransferable");
 
+        // See https://bugzilla.mozilla.org/show_bug.cgi?id=722872
+        if (typeof(trans.init) == "function")
+            trans.init(null);
+
         var json = cookie.toJSON();
         var wrapper1 = Xpcom.CCIN("@mozilla.org/supports-string;1", "nsISupportsString");
         wrapper1.data = json;
@@ -124,6 +128,11 @@ var CookieClipboard = Obj.extend(Object,
     getTransferData: function()
     {
         var trans = Xpcom.CCIN("@mozilla.org/widget/transferable;1", "nsITransferable");
+
+        // See https://bugzilla.mozilla.org/show_bug.cgi?id=722872
+        if (typeof(trans.init) == "function")
+            trans.init(null);
+
         trans.addDataFlavor(this.cookieFlavour);
 
         clipboard.getData(trans, Ci.nsIClipboard.kGlobalClipboard);
diff --git a/trace/FBTrace/chrome/firebug/content/cookies/cookieModule.js b/trace/FBTrace/chrome/firebug/content/cookies/cookieModule.js
index 0015b05..9b1e6a0 100644
--- a/trace/FBTrace/chrome/firebug/content/cookies/cookieModule.js
+++ b/trace/FBTrace/chrome/firebug/content/cookies/cookieModule.js
@@ -64,7 +64,7 @@ const prompts = Xpcom.CCSV("@mozilla.org/embedcomp/prompt-service;1", "nsIPrompt
 // Preferences
 const PrefService = Cc["@mozilla.org/preferences-service;1"];
 const prefService = PrefService.getService(Ci.nsIPrefService);
-const prefs = PrefService.getService(Ci.nsIPrefBranch2);
+const prefs = PrefService.getService(Ci.nsIPrefBranch);
 
 // Cookie panel ID.
 const panelName = "cookies";
@@ -676,45 +676,30 @@ Firebug.CookieModule = Obj.extend(Firebug.ActivableModule,
         return true;
     },
 
-    onRemoveAllShared: function(context, sessionOnly)
+    /**
+     * Removes cookies defined for a website
+     * @param {Object} context context, in which the cookies are defined
+     * @param {Object} [filter] filter to define, which cookies should be removed
+     *   (format: {session: true/false, host: string})
+     */
+    removeCookies: function(context, filter)
     {
         var panel = context.getPanel(panelName, true);
         if (!panel)
             return;
 
-        var cookies = [];
-
-        // Remove all cookies in the list. Notice that the list can be further
-        // filtered by the search-box (the right side of Firebug's tab bar)
-        // So, make sure in case of searching-on, only visible (matched)
-        // cookies are removed.
-        var searching = Css.hasClass(panel.panelNode, "searching");
-        var row = Dom.getElementByClass(panel.panelNode, "cookieRow");
-        while (row)
+        for (var host in context.cookies.activeHosts)
         {
-            if (!searching || Css.hasClass(row, "matched"))
+            var cookieEnumerator = cookieManager.getCookiesFromHost(host);
+
+            while (cookieEnumerator.hasMoreElements())
             {
-                var cookie = row.repObject;
+                var cookie = cookieEnumerator.getNext().QueryInterface(Ci.nsICookie2);
 
-                // Some entries within the Cookies panel don't represent a cookie.
-                if (cookie)
-                {
-                    // If sessionOnly flag is true, only session cookies will be removed.
-                    if (sessionOnly)
-                    {
-                        if (!cookie.cookie.expires)
-                            cookies.push(cookie);
-                    }
-                    else
-                        cookies.push(cookie);
-                }
+                if (!filter || ((!filter.session || cookie.isSession) && (!filter.host || filter.host == cookie.host)))
+                    cookieManager.remove(cookie.host, cookie.name, cookie.path, false);
             }
-
-            row = row.nextSibling;
         }
-
-        for (var i=0; i<cookies.length; i++)
-            CookieReps.CookieRow.onRemove(cookies[i]);
     },
 
     onRemoveAll: function(context)
@@ -723,11 +708,11 @@ Firebug.CookieModule = Obj.extend(Firebug.ActivableModule,
         {
             var check = {value: false};
             var flags = prompts.BUTTON_POS_0 * prompts.BUTTON_TITLE_YES +  
-                prompts.BUTTON_POS_1 * prompts.BUTTON_TITLE_NO;  
+            prompts.BUTTON_POS_1 * prompts.BUTTON_TITLE_NO;  
 
             if (!prompts.confirmEx(context.chrome.window, Locale.$STR("Firebug"),
                 Locale.$STR("cookies.confirm.removeall"), flags, "", "", "",
-                Locale.$STR("cookies.msg.Do_not_show_this_message_again"), check) == 0)
+                Locale.$STR("Do_not_show_this_message_again"), check) == 0)
             {
                 return;
             }
@@ -737,9 +722,9 @@ Firebug.CookieModule = Obj.extend(Firebug.ActivableModule,
             Options.set(removeConfirmation, !check.value);
         }
 
-        Firebug.CookieModule.onRemoveAllShared(context, false);
+        Firebug.CookieModule.removeCookies(context);
     },
-
+    
     onRemoveAllSession: function(context)
     {
         if (Options.get(removeSessionConfirmation))
@@ -750,7 +735,7 @@ Firebug.CookieModule = Obj.extend(Firebug.ActivableModule,
 
             if (!prompts.confirmEx(context.chrome.window, Locale.$STR("Firebug"),
                 Locale.$STR("cookies.confirm.removeallsession"), flags, "", "", "",
-                Locale.$STR("cookies.msg.Do_not_show_this_message_again"), check) == 0)
+                Locale.$STR("Do_not_show_this_message_again"), check) == 0)
             {
                 return;
             }
@@ -760,7 +745,30 @@ Firebug.CookieModule = Obj.extend(Firebug.ActivableModule,
             Options.set(removeSessionConfirmation, !check.value)
         }
 
-        Firebug.CookieModule.onRemoveAllShared(context, true);
+        Firebug.CookieModule.removeCookies(context, {session: true});
+    },
+
+    onRemoveAllFromHost: function(context, host)
+    {
+        if (Options.get(removeConfirmation))
+        {
+            var check = {value: false};
+            var flags = prompts.BUTTON_POS_0 * prompts.BUTTON_TITLE_YES +  
+                prompts.BUTTON_POS_1 * prompts.BUTTON_TITLE_NO;  
+
+            if (!prompts.confirmEx(context.chrome.window, Locale.$STR("Firebug"),
+                Locale.$STRF("cookies.confirm.Remove_All_From_Host", [host]), flags, "", "", "",
+                Locale.$STR("Do_not_show_this_message_again"), check) == 0)
+            {
+                return;
+            }
+
+            // Update 'Remove Cookies' confirmation option according to the value
+            // of the dialog's "do not show again" checkbox.
+            Options.set(removeConfirmation, !check.value);
+        }
+
+        Firebug.CookieModule.removeCookies(context, {host: host});
     },
 
     onCreateCookieShowTooltip: function(tooltip, context)
diff --git a/trace/FBTrace/chrome/firebug/content/cookies/cookieObserver.js b/trace/FBTrace/chrome/firebug/content/cookies/cookieObserver.js
index d2f92cb..345b363 100644
--- a/trace/FBTrace/chrome/firebug/content/cookies/cookieObserver.js
+++ b/trace/FBTrace/chrome/firebug/content/cookies/cookieObserver.js
@@ -34,6 +34,8 @@ const filterByPath = "cookies.filterByPath";
 
 const panelName = "cookies";
 
+const idnService = Xpcom.CCSV("@mozilla.org/network/idn-service;1", "nsIIDNService");
+
 // ********************************************************************************************* //
 // Cookie observer
 
@@ -126,21 +128,27 @@ var CookieObserver = Obj.extend(BaseObserver,
     {
         var pathFilter = Options.get(filterByPath);
 
-        // Get directory path (without the file name)
-        var queryStringPos = activeUri.path.lastIndexOf("?");
-        var activePath = queryStringPos != -1 ?
-            activeUri.path.substr(0, queryStringPos) : activeUri.path;
-
-        // Remove slash at the end of the active path according to step 4 of RFC 6265 section 5.1.4
-        var lastChar = activePath.charAt(activePath.length - 1);
-        if (lastChar == "/")
-            activePath = activePath.substr(0, activePath.length - 1);
+        // Compute the default path of the cookie according to the algorithm
+        // defined in RFC 6265 section 5.1.4
+        //
+        // Steps 2 and 3 (output "/" in case the cookie path is empty, its first
+        // character is "/" or there is no more than one "/")
+        if (cookiePath.length == 0 || cookiePath.charAt(0) != "/" ||
+            cookiePath.lastIndexOf("/") == 0)
+        {
+            cookiePath = "/";
+        }
+        else
+        {
+            // Step 4 (remove slash at the end of the active path according to)
+            cookiePath = cookiePath.substr(0, cookiePath.lastIndexOf("/"));
+        }
 
         // If the path filter is on, only cookies that match given path
         // according to RFC 6265 section 5.1.4 will be displayed.
-        if (pathFilter && (activePath != cookiePath && !(Str.hasPrefix(activePath, cookiePath) &&
-            (cookiePath.charAt(cookiePath.length - 1) == "/" ||
-                activePath.substr(cookiePath.length, 1) == "/"))))
+        var requestPath = activeUri.path;
+        if (pathFilter && (cookiePath != requestPath && !(Str.hasPrefix(requestPath, cookiePath) &&
+            (Str.endsWith(cookiePath, "/") || requestPath.substr(cookiePath.length, 1) == "/"))))
         {
             return false;
         }
@@ -165,6 +173,15 @@ var CookieObserver = Obj.extend(BaseObserver,
     isHostFromContext: function(context, host, path)
     {
         var location;
+        try
+        {
+            host = idnService.convertACEtoUTF8(host);
+        }
+        catch(exc)
+        {
+            if (FBTrace.DBG_ERRORS || FBTrace.DBG_COOKIES)
+                FBTrace.sysout("Host could not be converted to UTF-8", exc);
+        }
 
         // Invalid in Chromebug.
         try
diff --git a/trace/FBTrace/chrome/firebug/content/cookies/cookiePanel.js b/trace/FBTrace/chrome/firebug/content/cookies/cookiePanel.js
index 306f640..57bf681 100644
--- a/trace/FBTrace/chrome/firebug/content/cookies/cookiePanel.js
+++ b/trace/FBTrace/chrome/firebug/content/cookies/cookiePanel.js
@@ -481,6 +481,34 @@ CookiePanel.prototype = Obj.extend(Firebug.ActivablePanel,
             Firebug.Console.removeListener(Firebug.CookieModule.ConsoleListener);
         }
     },
+
+    // Support for info tips.
+    showInfoTip: function(infoTip, target, x, y)
+    {
+        var row = Dom.getAncestorByClass(target, "cookieRow");
+        if (row && row.repObject)
+        {
+            if (Dom.getAncestorByClass(target, "cookieSizeCol"))
+            {
+                var infoTipCookieId = "cookiesize-"+row.repObject.name;
+                if (infoTipCookieId == this.infoTipCookieId && row.repObject == this.infoTipCookie)
+                    return true;
+
+                this.infoTipCookieId = infoTipCookieId;
+                this.infoTipCookie = row.repObject;
+                return this.populateSizeInfoTip(infoTip, row.repObject);
+            }
+        }
+
+        delete this.infoTipCookieId;
+        return false;
+    },
+    
+    populateSizeInfoTip: function(infoTip, cookie)
+    {
+        CookieReps.SizeInfoTip.render(cookie, infoTip);
+        return true;
+    },
 }); 
 
 // ********************************************************************************************* //
diff --git a/trace/FBTrace/chrome/firebug/content/cookies/cookiePermissions.js b/trace/FBTrace/chrome/firebug/content/cookies/cookiePermissions.js
index 9c111ae..6f6df0e 100644
--- a/trace/FBTrace/chrome/firebug/content/cookies/cookiePermissions.js
+++ b/trace/FBTrace/chrome/firebug/content/cookies/cookiePermissions.js
@@ -154,7 +154,7 @@ var CookiePermissions = Obj.extend(Object,
 
             case "default-deny":
                 if (Options.get("cookies.clearWhenDeny"))
-                    Firebug.CookieModule.onRemoveAll(context);
+                    Firebug.CookieModule.onRemoveAllFromHost(context, location.host);
                 break;
         }
 
diff --git a/trace/FBTrace/chrome/firebug/content/cookies/cookieReps.js b/trace/FBTrace/chrome/firebug/content/cookies/cookieReps.js
index 69c5edd..e1a842a 100644
--- a/trace/FBTrace/chrome/firebug/content/cookies/cookieReps.js
+++ b/trace/FBTrace/chrome/firebug/content/cookies/cookieReps.js
@@ -236,19 +236,7 @@ CookieReps.CookieRow = domplate(CookieReps.Rep,
     getSize: function(cookie)
     {
         var size = cookie.cookie.name.length + cookie.cookie.value.length;
-        return this.formatSize(size);
-    },
-
-    formatSize: function(bytes)
-    {
-        if (bytes == -1 || bytes == undefined)
-            return "?";
-        else if (bytes < 1024)
-            return bytes + " B";
-        else if (bytes < 1024*1024)
-            return Math.ceil(bytes/1024) + " KB";
-        else
-            return (Math.ceil(bytes/1024)/1024) + " MB";    // OK, this is probable not necessary ;-)
+        return Str.formatSize(size);
     },
 
     getPath: function(cookie)
@@ -940,6 +928,50 @@ CookieReps.CookieCleared = domplate(CookieReps.Rep,
     }
 });
 
+
+CookieReps.SizeInfoTip = domplate(Firebug.Rep,
+{
+    tag:
+        TABLE({"class": "sizeInfoTip", "id": "cookiesSizeInfoTip", role:"presentation"},
+            TBODY(
+                FOR("size", "$sizeInfo",
+                    TAG("$size|sizeTag", {size: "$size"})
+                )
+            )
+        ),
+
+    sizeTag:
+        TR({"class": "sizeInfoRow"},
+            TD({"class": "sizeInfoLabelCol"}, "$size.label"),
+            TD({"class": "sizeInfoSizeCol"}, "$size|formatSize"),
+            TD({"class": "sizeInfoDetailCol"}, "$size|formatNumber")
+        ),
+
+    formatSize: function(size)
+    {
+        return Str.formatSize(size.size);
+    },
+
+    formatNumber: function(size)
+    {
+        return size.size && size.size >= 1024 ? "(" + Str.formatNumber(size.size) + " B)" : "";
+    },
+
+    render: function(cookie, parentNode)
+    {
+        var size = cookie.getSize();
+        var rawSize = cookie.getRawSize();
+        var sizeInfo = [];
+
+        sizeInfo.push({label: Locale.$STR("cookie.sizeinfo.Size"), size: size});
+
+        if (size != rawSize)
+            sizeInfo.push({label: Locale.$STR("cookie.sizeinfo.Raw_Size"), size: rawSize});
+
+        this.tag.replace({sizeInfo: sizeInfo}, parentNode);
+    },
+});
+
 // ********************************************************************************************* //
 // Header Template (domplate)
 
diff --git a/trace/FBTrace/chrome/firebug/content/cookies/cookieUtils.js b/trace/FBTrace/chrome/firebug/content/cookies/cookieUtils.js
index 9a2ed28..57fa879 100644
--- a/trace/FBTrace/chrome/firebug/content/cookies/cookieUtils.js
+++ b/trace/FBTrace/chrome/firebug/content/cookies/cookieUtils.js
@@ -36,9 +36,17 @@ var CookieUtils =
         if (value)
             value = value.replace(/\+/g, " ");
 
+        value = unescape(value);
+
+        try
+        {
+            value = Str.convertToUnicode(value);
+        }
+        catch (exc) { }
+
         var c = {
             name        : cookie.name,
-            value       : Str.convertToUnicode(unescape(value)),
+            value       : value,
             isDomain    : cookie.isDomain,
             host        : cookie.host,
             path        : cookie.path,
diff --git a/trace/FBTrace/chrome/firebug/content/cookies/menuUtils.js b/trace/FBTrace/chrome/firebug/content/cookies/menuUtils.js
index 4b1d7c2..d708ffe 100644
--- a/trace/FBTrace/chrome/firebug/content/cookies/menuUtils.js
+++ b/trace/FBTrace/chrome/firebug/content/cookies/menuUtils.js
@@ -13,13 +13,17 @@ var MenuUtils =
 {
     optionMenu: function(context, label, tooltiptext, domain, option)
     {
-        var value = Options.getPref(domain, option);
+        var value = Options.getPref(domain, option), self = this;
         return {
             label: label,
             tooltiptext: tooltiptext,
             type: "checkbox",
             checked: value,
-            command: Obj.bindFixed(this.setPref, this, domain, option, !value)
+            command: function()
+            {
+                var checked = this.hasAttribute("checked");
+                self.setPref(domain, option, checked);
+            }
         };
     },
 
diff --git a/trace/FBTrace/chrome/firebug/content/css/computedPanel.js b/trace/FBTrace/chrome/firebug/content/css/computedPanel.js
index a992248..c7cc75a 100644
--- a/trace/FBTrace/chrome/firebug/content/css/computedPanel.js
+++ b/trace/FBTrace/chrome/firebug/content/css/computedPanel.js
@@ -97,7 +97,7 @@ CSSComputedPanel.prototype = Obj.extend(Firebug.Panel,
                                 _repObject: "$selector"},
                             TD({"class": "selectorName", role: "presentation"},
                                 "$selector.selector.text"),
-                            TD({role: "presentation"},
+                            TD({"class": "propValue", role: "presentation"},
                                 SPAN({"class": "stylePropValue"}, "$selector.value|formatValue")),
                             TD({"class": "styleSourceLink", role: "presentation"},
                                 TAG(FirebugReps.SourceLink.tag, {object: "$selector|getSourceLink"})
@@ -142,6 +142,10 @@ CSSComputedPanel.prototype = Obj.extend(Firebug.Panel,
             else if (Options.get("colorDisplay") == "hsl")
                 value = Css.rgbToHSL(value);
 
+            var limit = Options.get("stringCropLength");
+            if (limit > 0)
+                value = Str.cropString(value, limit);
+
             // Add a zero-width space after a comma to allow line breaking
             return value.replace(/,/g, ",\u200B");
         }
@@ -670,6 +674,7 @@ CSSComputedPanel.prototype = Obj.extend(Firebug.Panel,
 
                         return CSSInfoTip.populateImageInfoTip(infoTip, absURL, repeat);
                     }
+                    break;
 
                 case "fontFamily":
                     return CSSInfoTip.populateFontFamilyInfoTip(infoTip, cssValue.value);
@@ -678,6 +683,8 @@ CSSComputedPanel.prototype = Obj.extend(Firebug.Panel,
             delete this.infoTipType;
             delete this.infoTipValue;
             delete this.infoTipObject;
+
+            return false;
         }
     },
 
@@ -840,8 +847,8 @@ const styleGroups =
         "overflow-x",  // http://www.w3.org/TR/2002/WD-css3-box-20021024/#overflow
         "overflow-y",
         "overflow-clip",
-        "-moz-transform",
-        "-moz-transform-origin",
+        "transform",
+        "transform-origin",
         "white-space",
         "clip",
         "float",
diff --git a/trace/FBTrace/chrome/firebug/content/css/cssModule.js b/trace/FBTrace/chrome/firebug/content/css/cssModule.js
index 7e7dca5..3339fe4 100644
--- a/trace/FBTrace/chrome/firebug/content/css/cssModule.js
+++ b/trace/FBTrace/chrome/firebug/content/css/cssModule.js
@@ -10,9 +10,10 @@ define([
     "firebug/chrome/window",
     "firebug/lib/xml",
     "firebug/lib/options",
-    "firebug/lib/array"
+    "firebug/lib/array",
+    "firebug/editor/editorSelector"
 ],
-function(Obj, Firebug, Xpcom, Events, Url, Css, Win, Xml, Options, Arr) {
+function(Obj, Firebug, Xpcom, Events, Url, Css, Win, Xml, Options, Arr, EditorSelector) {
 
 // ********************************************************************************************* //
 // Constants
@@ -27,7 +28,7 @@ const reRepeat = /no-repeat|repeat-x|repeat-y|repeat/;
 // ********************************************************************************************* //
 // CSS Module
 
-Firebug.CSSModule = Obj.extend(Obj.extend(Firebug.Module, Firebug.EditorSelector),
+Firebug.CSSModule = Obj.extend(Firebug.Module, Firebug.EditorSelector,
 {
     dispatchName: "cssModule",
 
@@ -87,15 +88,34 @@ Firebug.CSSModule = Obj.extend(Obj.extend(Firebug.Module, Firebug.EditorSelector
         return insertIndex;
     },
 
-    deleteRule: function(styleSheet, ruleIndex)
+    deleteRule: function(src, ruleIndex)
     {
+        var inlineStyle = (src instanceof window.Element);
         if (FBTrace.DBG_CSS)
-            FBTrace.sysout("deleteRule: " + ruleIndex + " " + styleSheet.cssRules.length,
-                styleSheet.cssRules);
+        {
+            if (inlineStyle)
+            {
+                FBTrace.sysout("deleteRule: element.style", src);
+            }
+            else
+            {
+                FBTrace.sysout("deleteRule: " + ruleIndex + " " + src.cssRules.length,
+                    src.cssRules);
+            }
+        }
 
-        Events.dispatch(this.fbListeners, "onCSSDeleteRule", [styleSheet, ruleIndex]);
+        var rule = (inlineStyle ? src : src.cssRules[ruleIndex]);
+        var afterParams = [src, rule.style.cssText];
+        afterParams.push(inlineStyle ? "" : rule.selectorText);
 
-        styleSheet.deleteRule(ruleIndex);
+        Events.dispatch(this.fbListeners, "onCSSDeleteRule", [src, ruleIndex]);
+
+        if (src instanceof window.Element)
+            src.removeAttribute("style");
+        else
+            src.deleteRule(ruleIndex);
+
+        Events.dispatch(this.fbListeners, "onAfterCSSDeleteRule", afterParams);
     },
 
     setProperty: function(rule, propName, propValue, propPriority)
@@ -192,7 +212,7 @@ Firebug.CSSModule = Obj.extend(Obj.extend(Firebug.Module, Firebug.EditorSelector
     cleanupSheets: function(doc, context)
     {
         if (!context)
-            return;
+            return false;
 
         // Due to the manner in which the layout engine handles multiple
         // references to the same sheet we need to kick it a little bit.
@@ -206,7 +226,7 @@ Firebug.CSSModule = Obj.extend(Obj.extend(Firebug.Module, Firebug.EditorSelector
         /*if (!Xml.isXMLPrettyPrint(context))
         {
             var style = Css.createStyleSheet(doc);
-            style.innerHTML = "#fbIgnoreStyleDO_NOT_USE {}";
+            style.textContent = "#fbIgnoreStyleDO_NOT_USE {}";
             Css.addStyleSheet(doc, style);
 
             if (style.parentNode)
@@ -220,6 +240,8 @@ Firebug.CSSModule = Obj.extend(Obj.extend(Firebug.Module, Firebug.EditorSelector
             }
         }*/
 
+        var result = true;
+
         // https://bugzilla.mozilla.org/show_bug.cgi?id=500365
         // This voodoo touches each style sheet to force some Firefox internal change
         // to allow edits.
@@ -238,11 +260,17 @@ Firebug.CSSModule = Obj.extend(Obj.extend(Firebug.Module, Firebug.EditorSelector
             }
             catch(e)
             {
+                result = false;
+
                 if (FBTrace.DBG_ERRORS)
-                    FBTrace.sysout("css.show: sheet.cssRules FAILS for "+
-                        (styleSheets[i]?styleSheets[i].href:"null sheet")+e, e);
+                    FBTrace.sysout("css.show: sheet.cssRules FAILS for " +
+                        (styleSheets[i] ? styleSheets[i].href : "null sheet") + e, e);
             }
         }
+
+        // Return true only if all stylesheets are fully loaded and there is no
+        // excpetion when accessing them.
+        return result;
     },
 
     cleanupSheetHandler: function(event, context)
diff --git a/trace/FBTrace/chrome/firebug/content/css/cssPanel.js b/trace/FBTrace/chrome/firebug/content/css/cssPanel.js
index 814f58f..89e1f29 100644
--- a/trace/FBTrace/chrome/firebug/content/css/cssPanel.js
+++ b/trace/FBTrace/chrome/firebug/content/css/cssPanel.js
@@ -23,12 +23,14 @@ define([
     "firebug/lib/options",
     "firebug/css/cssModule",
     "firebug/css/cssReps",
+    "firebug/css/selectorEditor",
     "firebug/editor/editor",
     "firebug/editor/editorSelector",
     "firebug/chrome/searchBox"
 ],
 function(Obj, Firebug, Domplate, FirebugReps, Locale, Events, Url, SourceLink, Css, Dom, Win,
-    Search, Str, Arr, Fonts, Xml, Persist, System, Menu, Options, CSSModule, CSSInfoTip) {
+    Search, Str, Arr, Fonts, Xml, Persist, System, Menu, Options, CSSModule, CSSInfoTip,
+    SelectorEditor) {
 
 with (Domplate) {
 
@@ -50,6 +52,18 @@ var CSSDomplateBase =
     isSelectorEditable: function(rule)
     {
         return rule.isSelectorEditable && this.isEditable(rule);
+    },
+
+    getPropertyValue: function(prop)
+    {
+        // Disabled, see http://code.google.com/p/fbug/issues/detail?id=5880
+        /*
+        var limit = Options.get("stringCropLength");
+        */
+        var limit = 0;
+        if (limit > 0)
+            return Str.cropString(prop.value, limit);
+        return prop.value;
     }
 };
 
@@ -69,12 +83,11 @@ var CSSPropTag = domplate(CSSDomplateBase,
 
             // Use a space here, so that "copy to clipboard" has it (issue 3266).
             SPAN({"class": "cssColon"}, ": "),
-            SPAN({"class": "cssPropValue", $editable: "$rule|isEditable"},
-                "$prop.value$prop.important"
+            SPAN({"class": "cssPropValue", $editable: "$rule|isEditable",
+                _repObject: "$prop.value$prop.important"}, "$prop|getPropertyValue$prop.important"
             ),
-            SPAN({"class": "cssSemi"}, ";"
+            SPAN({"class": "cssSemi"}, ";")
         )
-    )
 });
 
 var CSSRuleTag =
@@ -159,12 +172,12 @@ var CSSStyleRuleTag = domplate(CSSDomplateBase,
             $insertInto: "$rule|isEditable",
             $editGroup: "$rule|isSelectorEditable",
             _repObject: "$rule.rule",
-            "ruleId": "$rule.id", role: "presentation"},
+            role: "presentation"},
             DIV({"class": "cssHead focusRow", role: "listitem"},
                 SPAN({"class": "cssSelector", $editable: "$rule|isSelectorEditable"},
                     "$rule.selector"),
-                    " {"
-                ),
+                " {"
+            ),
             DIV({role: "group"},
                 DIV({"class": "cssPropertyListBox", _rule: "$rule", role: "listbox"},
                     FOR("prop", "$rule.props",
@@ -186,7 +199,6 @@ Firebug.CSSStyleRuleTag = CSSStyleRuleTag;
 const reSplitCSS = /(url\("?[^"\)]+?"?\))|(rgba?\([^)]*\)?)|(hsla?\([^)]*\)?)|(#[\dA-Fa-f]+)|(-?\d+(\.\d+)?(%|[a-z]{1,4})?)|"([^"]*)"?|'([^']*)'?|([^,\s\/!\(\)]+)|(!(.*)?)/;
 const reURL = /url\("?([^"\)]+)?"?\)/;
 const reRepeat = /no-repeat|repeat-x|repeat-y|repeat/;
-const reSelectorChar = /[-_0-9a-zA-Z]/;
 
 // ********************************************************************************************* //
 // CSS Module
@@ -385,7 +397,7 @@ Firebug.CSSStyleSheetPanel.prototype = Obj.extend(Firebug.Panel,
         var rules = [];
         var appendRules = function(cssRules)
         {
-            var i, props, ruleId;
+            var i, props;
 
             if (!cssRules)
                 return;
@@ -396,14 +408,10 @@ Firebug.CSSStyleSheetPanel.prototype = Obj.extend(Firebug.Panel,
                 if (rule instanceof window.CSSStyleRule)
                 {
                     props = this.getRuleProperties(context, rule);
-                    ruleId = this.getRuleId(rule);
                     rules.push({
                         tag: CSSStyleRuleTag.tag,
                         rule: rule,
-                        id: ruleId,
-                        // Show universal selectors with pseudo-class
-                        // (http://code.google.com/p/fbug/issues/detail?id=3683)
-                        selector: rule.selectorText.replace(/ :/g, " *:"),
+                        selector: rule.selectorText.replace(/ :/g, " *:"), // (issue 3683)
                         props: props,
                         isSystemSheet: isSystemSheet,
                         isSelectorEditable: true
@@ -510,21 +518,34 @@ Firebug.CSSStyleSheetPanel.prototype = Obj.extend(Firebug.Panel,
     {
         var props = this.parseCSSProps(rule.style, inheritMode);
 
-        var ruleId = this.getRuleId(rule);
-        this.addOldProperties(context, ruleId, inheritMode, props);
+        this.addDisabledProperties(context, rule, inheritMode, props);
         this.sortProperties(props);
 
         return props;
     },
 
-    addOldProperties: function(context, ruleId, inheritMode, props)
+    addDisabledProperties: function(context, rule, inheritMode, props)
     {
-        if (context.selectorMap && context.selectorMap.hasOwnProperty(ruleId) )
+        var disabledMap = this.getDisabledMap(context);
+        var moreProps = disabledMap.get(rule);
+        if (moreProps)
         {
-            var moreProps = context.selectorMap[ruleId];
+            var propMap = {};
+            for (var i = 0; i < props.length; ++i)
+                propMap[props[i].name] = true;
+
             for (var i = 0; i < moreProps.length; ++i)
             {
                 var prop = moreProps[i];
+                if (propMap.hasOwnProperty(prop.name))
+                {
+                    // A (probably enabled) property with the same name as this
+                    // disabled one has appeared - remove this one entirely.
+                    moreProps.splice(i, 1);
+                    --i;
+                    continue;
+                }
+                propMap[prop.name] = true;
                 this.addProperty(prop.name, prop.value, prop.important, true, inheritMode, props);
             }
         }
@@ -532,17 +553,13 @@ Firebug.CSSStyleSheetPanel.prototype = Obj.extend(Firebug.Panel,
 
     addProperty: function(name, value, important, disabled, inheritMode, props)
     {
-        if (inheritMode && !Css.inheritedStyleNames[name])
+        if (inheritMode && !Dom.domUtils.isInheritedProperty(name))
             return;
 
         name = this.translateName(name, value);
         if (name)
         {
-            if (Options.get("colorDisplay") == "hex")
-                value = Css.rgbToHex(value);
-            else if (Options.get("colorDisplay") == "hsl")
-                value = Css.rgbToHSL(value);
-            value = Css.stripUnits(value);
+            value = Css.stripUnits(formatColor(value));
             important = important ? " !important" : "";
 
             var prop = {name: name, value: value, important: important, disabled: disabled};
@@ -588,6 +605,22 @@ Firebug.CSSStyleSheetPanel.prototype = Obj.extend(Firebug.Panel,
 
     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+    getDisabledMap: function(context)
+    {
+        // Ideally, we'd use a WeakMap here, but WeakMaps don't allow CSS rules
+        // as keys before Firefox 17. A Map is used instead. (cf. bug 777373.)
+        if (!context.cssDisabledMap)
+            context.cssDisabledMap = new Map();
+        return context.cssDisabledMap;
+    },
+
+    remapRule: function(context, oldRule, newRule)
+    {
+        var map = this.getDisabledMap(context);
+        if (map.has(oldRule))
+            map.set(newRule, map.get(oldRule));
+    },
+
     editElementStyle: function()
     {
         var rulesBox = this.panelNode.getElementsByClassName("cssElementRuleContainer")[0];
@@ -721,22 +754,13 @@ Firebug.CSSStyleSheetPanel.prototype = Obj.extend(Firebug.Panel,
     {
         var rule = Firebug.getRepObject(row);
         var propName = Dom.getChildByClass(row, "cssPropName").textContent;
-        CSSModule.deleteProperty(rule, propName, this.context);
 
-        // Remove the property from the selector map, if it was disabled
-        var ruleId = Firebug.getRepNode(row).getAttribute("ruleId");
-        if ( this.context.selectorMap && this.context.selectorMap.hasOwnProperty(ruleId) )
-        {
-            var map = this.context.selectorMap[ruleId];
-            for (var i = 0; i < map.length; ++i)
-            {
-                if (map[i].name == propName)
-                {
-                    map.splice(i, 1);
-                    break;
-                }
-            }
-        }
+        // Try removing the property from the "disabled" map.
+        var wasDisabled = this.removeDisabledProperty(rule, propName);
+
+        // If that fails, remove the actual property instead.
+        if (!wasDisabled)
+            CSSModule.deleteProperty(rule, propName, this.context);
 
         if (this.name == "stylesheet")
             Events.dispatch(this.fbListeners, "onInlineEditorClose", [this, row.firstChild, true]);
@@ -745,6 +769,23 @@ Firebug.CSSStyleSheetPanel.prototype = Obj.extend(Firebug.Panel,
         this.markChange(this.name == "stylesheet");
     },
 
+    removeDisabledProperty: function(rule, propName)
+    {
+        var disabledMap = this.getDisabledMap(this.context);
+        var map = disabledMap.get(rule);
+        if (!map)
+            return false;
+        for (var i = 0; i < map.length; ++i)
+        {
+            if (map[i].name === propName)
+            {
+                map.splice(i, 1);
+                return true;
+            }
+        }
+        return false;
+    },
+
     disablePropertyRow: function(row)
     {
         Css.toggleClass(row, "disabledStyle");
@@ -752,16 +793,12 @@ Firebug.CSSStyleSheetPanel.prototype = Obj.extend(Firebug.Panel,
         var rule = Firebug.getRepObject(row);
         var propName = Dom.getChildByClass(row, "cssPropName").textContent;
 
-        if (!this.context.selectorMap)
-            this.context.selectorMap = {};
+        var disabledMap = this.getDisabledMap(this.context);
+        if (!disabledMap.has(rule))
+            disabledMap.set(rule, []);
+        var map = disabledMap.get(rule);
 
-        // XXXjoe Generate unique key for elements too
-        var ruleId = Firebug.getRepNode(row).getAttribute("ruleId");
-        if (!(this.context.selectorMap.hasOwnProperty(ruleId)))
-            this.context.selectorMap[ruleId] = [];
-
-        var map = this.context.selectorMap[ruleId];
-        var propValue = Dom.getChildByClass(row, "cssPropValue").textContent;
+        var propValue = Firebug.getRepObject(Dom.getChildByClass(row, "cssPropValue"));
         var parsedValue = parsePriority(propValue);
 
         CSSModule.disableProperty(Css.hasClass(row, "disabledStyle"), rule,
@@ -1114,30 +1151,34 @@ Firebug.CSSStyleSheetPanel.prototype = Obj.extend(Firebug.Panel,
             );
         }
 
-        if (this.infoTipType == "color")
-        {
-            items.push(
-                {
-                    label: "CopyColor",
-                    tooltiptext: "css.tip.Copy_Color",
-                    command: Obj.bindFixed(System.copyToClipboard, System, this.infoTipObject)
-                }
-            );
-        }
-        else if (this.infoTipType == "image")
+        var propValue = Dom.getAncestorByClass(target, "cssPropValue");
+        if (propValue)
         {
-            items.push(
-                {
-                    label: "CopyImageLocation",
-                    tooltiptext: "css.tip.Copy_Image_Location",
-                    command: Obj.bindFixed(System.copyToClipboard, System, this.infoTipObject)
-                },
-                {
-                    label: "OpenImageInNewTab",
-                    tooltiptext: "css.tip.Open_Image_In_New_Tab",
-                    command: Obj.bindFixed(Win.openNewTab, Win, this.infoTipObject)
-                }
-            );
+            if (this.infoTipType == "color")
+            {
+                items.push(
+                    {
+                        label: "CopyColor",
+                        tooltiptext: "css.tip.Copy_Color",
+                        command: Obj.bindFixed(System.copyToClipboard, System, this.infoTipObject)
+                    }
+                );
+            }
+            else if (this.infoTipType == "image")
+            {
+                items.push(
+                    {
+                        label: "CopyImageLocation",
+                        tooltiptext: "css.tip.Copy_Image_Location",
+                        command: Obj.bindFixed(System.copyToClipboard, System, this.infoTipObject)
+                    },
+                    {
+                        label: "OpenImageInNewTab",
+                        tooltiptext: "css.tip.Open_Image_In_New_Tab",
+                        command: Obj.bindFixed(Win.openNewTab, Win, this.infoTipObject)
+                    }
+                );
+            }
         }
 
         if (!Url.isSystemStyleSheet(this.selection))
@@ -1198,10 +1239,12 @@ Firebug.CSSStyleSheetPanel.prototype = Obj.extend(Firebug.Panel,
                         {
                             label: Locale.$STRF("DeleteProp", [propName]),
                             tooltiptext: Locale.$STRF("css.tip.Delete_Prop", [propName]),
+                            id: "fbDeleteCSSProp",
                             nol10n: true,
                             command: Obj.bindFixed(this.deletePropertyRow, this, propRow)
                         },
                         {
+                            id: "fbDisableCSSProp",
                             label: Locale.$STRF("DisableProp", [propName]),
                             tooltiptext: Locale.$STRF("css.tip.Disable_Prop", [propName]),
                             nol10n: true,
@@ -1229,6 +1272,7 @@ Firebug.CSSStyleSheetPanel.prototype = Obj.extend(Firebug.Panel,
         items.push(
             "-",
             {
+                id: "fbRefresh",
                 label: "Refresh",
                 command: Obj.bind(this.refresh, this),
                 tooltiptext: "panel.tip.Refresh"
@@ -1252,10 +1296,35 @@ Firebug.CSSStyleSheetPanel.prototype = Obj.extend(Firebug.Panel,
         var propValue = Dom.getAncestorByClass(target, "cssPropValue");
         if (propValue)
         {
-            var text = propValue.textContent;
             var prop = Dom.getAncestorByClass(target, "cssProp");
+            var styleRule = Firebug.getRepObject(prop);
             var propNameNode = prop.getElementsByClassName("cssPropName").item(0);
             var propName = propNameNode.textContent.toLowerCase();
+            var priority = styleRule.style.getPropertyPriority(propName);
+            var text = styleRule.style.getPropertyValue(propName) +
+                (priority ? " !" + priority : "");
+
+            if (text != "")
+            {
+                text = formatColor(text);
+            }
+            else
+            {
+                var disabledMap = this.getDisabledMap(this.context);
+                var disabledProps = disabledMap.get(styleRule);
+                if (disabledProps)
+                {
+                    for (var i = 0, len = disabledProps.length; i < len; ++i)
+                    {
+                        if (disabledProps[i].name == propName)
+                        {
+                            priority = disabledProps[i].important;
+                            text = disabledProps[i].value + (priority ? " !" + priority : "");
+                            break;
+                        }
+                    }
+                }
+            }
             var cssValue;
 
             if (propName == "font" || propName == "font-family")
@@ -1292,7 +1361,8 @@ Firebug.CSSStyleSheetPanel.prototype = Obj.extend(Firebug.Panel,
                     if (Css.isImageRule(Xml.getElementSimpleType(Firebug.getRepObject(target)),
                         propNameNode.textContent))
                     {
-                        var rule = Firebug.getRepObject(target);
+                        var prop = Dom.getAncestorByClass(target, "cssProp");
+                        var rule = Firebug.getRepObject(prop);
                         var baseURL = this.getStylesheetURL(rule, true);
                         var relURL = CSSModule.parseURLValue(cssValue.value);
                         var absURL = Url.isDataURL(relURL) ? relURL : Url.absoluteURL(relURL, baseURL);
@@ -1303,6 +1373,7 @@ Firebug.CSSStyleSheetPanel.prototype = Obj.extend(Firebug.Panel,
 
                         return CSSInfoTip.populateImageInfoTip(infoTip, absURL, repeat);
                     }
+                    break;
 
                 case "fontFamily":
                     return CSSInfoTip.populateFontFamilyInfoTip(infoTip, cssValue.value);
@@ -1311,6 +1382,8 @@ Firebug.CSSStyleSheetPanel.prototype = Obj.extend(Firebug.Panel,
             delete this.infoTipType;
             delete this.infoTipValue;
             delete this.infoTipObject;
+
+            return false;
         }
     },
 
@@ -1536,17 +1609,21 @@ Firebug.CSSStyleSheetPanel.prototype = Obj.extend(Firebug.Panel,
     getStyleDeclaration: function(cssSelector)
     {
         var cssRule = Dom.getAncestorByClass(cssSelector, "cssRule");
-        var cssRules = cssRule.getElementsByClassName("cssPropertyListBox")[0].rule;
-        var props = [];
+        var propRows = cssRule.getElementsByClassName("cssProp");
 
-        for (var p in cssRules.props)
+        var lines = [];
+        for (var i = 0; i < propRows.length; ++i)
         {
-            var prop = cssRules.props[p];
-            if (!(prop.disabled || prop.overridden))
-                props.push(prop.name + ": " + prop.value + prop.important + ";");
+            var row = propRows[i];
+            if (row.classList.contains("disabledStyle"))
+                continue;
+
+            var name = Dom.getChildByClass(row, "cssPropName").textContent;
+            var value = Firebug.getRepObject(Dom.getChildByClass(row, "cssPropValue"));
+            lines.push(name + ": " + value + ";");
         }
 
-        return props;
+        return lines;
     },
 
     copyRuleDeclaration: function(cssSelector)
@@ -1575,33 +1652,15 @@ Firebug.CSSStyleSheetPanel.prototype = Obj.extend(Firebug.Panel,
 
         CSSModule.deleteRule(styleSheet, ruleIndex);
 
-        if (this.context.panelName == "stylesheet")
-        {
-            var rule = Dom.getAncestorByClass(cssSelector, "cssRule");
-            if (rule)
-                rule.parentNode.removeChild(rule);
-        }
-        else
-        {
-            var sidePanel = Firebug.chrome.getSelectedSidePanel();
-            sidePanel.refresh();
-        }
+        var rule = Dom.getAncestorByClass(cssSelector, "cssRule");
+        if (rule)
+            rule.parentNode.removeChild(rule);
     },
 
     copyStyleDeclaration: function(cssSelector)
     {
         var props = this.getStyleDeclaration(cssSelector);
         System.copyToClipboard(props.join(Str.lineBreak()));
-    },
-
-    getRuleId: function(rule)
-    {
-        var line = Dom.domUtils.getRuleLine(rule);
-
-        // xxxjjb I hope % is invalid in selectortext
-        const reQuotes = /['"]/g;
-        var ruleId = rule.selectorText.replace(reQuotes,"%")+"/"+line;
-        return ruleId;
     }
 });
 
@@ -1638,103 +1697,86 @@ CSSEditor.prototype = domplate(Firebug.InlineEditor.prototype,
         if (FBTrace.DBG_CSS)
             FBTrace.sysout("CSSEditor.saveEdit", arguments);
 
-        var propValue, parsedValue, propName;
-
-        target.innerHTML = Str.escapeForCss(value);
-
-        var row = Dom.getAncestorByClass(target, "cssProp");
-        if (Css.hasClass(row, "disabledStyle"))
-            Css.toggleClass(row, "disabledStyle");
-
-        var rule = Firebug.getRepObject(target);
+        var cssRule = Dom.getAncestorByClass(target, "cssRule");
+        var rule = Firebug.getRepObject(cssRule);
 
         if (rule instanceof window.CSSStyleRule || rule instanceof window.Element)
         {
-            if (Css.hasClass(target, "cssPropName"))
-            {
-  
-                if (value && previousValue != value)  // name of property has changed.
-                {
-                    // Record the original CSS text for the inline case so we can reconstruct at a later
-                    // point for diffing purposes
-                    var baseText = rule.style ? rule.style.cssText : rule.cssText;
-  
-                    propValue = Dom.getChildByClass(row, "cssPropValue").textContent;
-                    parsedValue = parsePriority(propValue);
-  
-                    if (FBTrace.DBG_CSS)
-                        FBTrace.sysout("CSSEditor.saveEdit : " + previousValue + "->" + value +
-                            " = " + propValue);
-  
-                    if (propValue && propValue != "undefined")
-                    {
-                        if (FBTrace.DBG_CSS)
-                            FBTrace.sysout("CSSEditor.saveEdit : " + previousValue + "->" + value +
-                                " = " + propValue);
-  
-                        if (previousValue)
-                            CSSModule.removeProperty(rule, previousValue);
-  
-                        CSSModule.setProperty(rule, value, parsedValue.value,
-                            parsedValue.priority);
-                    }
-  
-                    Events.dispatch(CSSModule.fbListeners, "onCSSPropertyNameChanged", [rule, value,
-                        previousValue, baseText]);
-                }
-                else if (!value)
-                {
-                    // name of the property has been deleted, so remove the property.
-                    CSSModule.removeProperty(rule, previousValue);
-                }
-            }
-            else if (Dom.getAncestorByClass(target, "cssPropValue"))
+            var prop = Dom.getAncestorByClass(target, "cssProp");
+
+            if (prop)
             {
-                propName = Dom.getChildByClass(row, "cssPropName").textContent;
-                propValue = Dom.getChildByClass(row, "cssPropValue").textContent;
-  
-                if (FBTrace.DBG_CSS)
+                var propName = Dom.getChildByClass(prop, "cssPropName").textContent;
+                // If the property was previously disabled, remove it from the "disabled"
+                // map. (We will then proceed to enable the property.)
+                if (prop && prop.classList.contains("disabledStyle"))
                 {
-                    FBTrace.sysout("CSSEditor.saveEdit propName=propValue: "+propName +
-                        " = "+propValue+"\n");
-                   // FBTrace.sysout("CSSEditor.saveEdit BEFORE style:",style);
+                    prop.classList.remove("disabledStyle");
+    
+                    this.panel.removeDisabledProperty(rule, propName);
                 }
-  
-                if (value && value != "null")
+    
+                if (Css.hasClass(target, "cssPropName"))
                 {
-                    parsedValue = parsePriority(value);
-                    CSSModule.setProperty(rule, propName, parsedValue.value,
-                        parsedValue.priority);
+                    // Actual saving is done in endEditing, see the comment there.
+                    target.textContent = value;
                 }
-                else if (previousValue && previousValue != "null")
+                else if (Dom.getAncestorByClass(target, "cssPropValue"))
                 {
-                    CSSModule.removeProperty(rule, propName);
+                    target.textContent = CSSDomplateBase.getPropertyValue({value: value});
+    
+                    propName = Dom.getChildByClass(prop, "cssPropName").textContent;
+    
+                    if (FBTrace.DBG_CSS)
+                    {
+                        FBTrace.sysout("CSSEditor.saveEdit \"" + propName + "\" = \"" + value + "\"");
+                       // FBTrace.sysout("CSSEditor.saveEdit BEFORE style:",style);
+                    }
+    
+                    if (value && value != "null")
+                    {
+                        var parsedValue = parsePriority(value);
+                        CSSModule.setProperty(rule, propName, parsedValue.value,
+                            parsedValue.priority);
+                        // Save in rep object.
+                        Dom.getAncestorByClass(target, "cssPropValue").repObject = value;
+                    }
+                    else if (previousValue && previousValue != "null")
+                    {
+                        CSSModule.removeProperty(rule, propName);
+                    }
                 }
-            }
-  
-            if (value)
-            {
-                var saveSuccess = !!rule.style.getPropertyValue(propName || value);
-                if(!saveSuccess && !propName)
+    
+                if (value)
                 {
-                    propName = value.replace(/-./g, function(match)
+                    var saveSuccess = false;
+                    if (Css.hasClass(target, "cssPropName"))
                     {
-                        return match[1].toUpperCase()
-                    });
+                        var propName = value.replace(/-./g, function(match)
+                        {
+                            return match[1].toUpperCase();
+                        });
     
-                    if (propName in rule.style || propName == "float")
-                        saveSuccess = "almost";
-                }
+                        if (propName in rule.style || propName == "float")
+                            saveSuccess = "almost";
+                    }
+                    else
+                    {
+                        saveSuccess = !!rule.style.getPropertyValue(propName);
+                    }
     
-                this.box.setAttribute("saveSuccess", saveSuccess);
-            }
-            else
-            {
-                this.box.removeAttribute("saveSuccess");
+                    this.box.setAttribute("saveSuccess", saveSuccess);
+                }
+                else
+                {
+                    this.box.removeAttribute("saveSuccess");
+                }
             }
         }
         else if (rule instanceof window.CSSImportRule && Css.hasClass(target, "cssMediaQuery"))
         {
+            target.textContent = value;
+
             if (FBTrace.DBG_CSS)
             {
                 FBTrace.sysout("CSSEditor.saveEdit: @import media query: " +
@@ -1747,12 +1789,17 @@ CSSEditor.prototype = domplate(Firebug.InlineEditor.prototype,
             rule.parentStyleSheet.disabled = true;
             rule.parentStyleSheet.disabled = false;
 
-            row = Dom.getAncestorByClass(target, "importRule");
-            row.getElementsByClassName("separator").item(0).innerHTML = 
-                value == "" ? "" : " ";
+            var row = Dom.getAncestorByClass(target, "importRule");
+            row.getElementsByClassName("separator").item(0).textContent = 
+                value == "" ? "" : String.fromCharCode(160);
+
+            var saveSuccess = rule.media.mediaText != "not all" || value == "not all";
+            this.box.setAttribute("saveSuccess", saveSuccess);
         }
         else if (rule instanceof window.CSSCharsetRule)
         {
+            target.textContent = value;
+
             if (FBTrace.DBG_CSS)
                 FBTrace.sysout("CSSEditor.saveEdit: @charset: " + previousValue + "->" + value);
 
@@ -1767,6 +1814,57 @@ CSSEditor.prototype = domplate(Firebug.InlineEditor.prototype,
             FBTrace.sysout("CSSEditor.saveEdit (ending) " + this.panel.name, value);
     },
 
+    beginEditing: function(target, value)
+    {
+        var row = Dom.getAncestorByClass(target, "cssProp");
+        this.initialValue = value;
+        this.initiallyDisabled = (row && row.classList.contains("disabledStyle"));
+    },
+
+    endEditing: function(target, value, cancel)
+    {
+        if (!cancel && target.classList.contains("cssPropName"))
+        {
+            // Save changed property names here instead of in saveEdit, because otherwise
+            // unrelated properties might get discarded (see issue 5204).
+            var previous = this.initialValue;
+            if (FBTrace.DBG_CSS)
+            {
+                FBTrace.sysout("CSSEditor.endEditing: renaming property " + previous + " -> " + value);
+            }
+
+            var cssRule = Dom.getAncestorByClass(target, "cssRule");
+            var rule = Firebug.getRepObject(cssRule);
+            var baseText = rule.style ? rule.style.cssText : rule.cssText;
+            var prop = Dom.getAncestorByClass(target, "cssProp");
+            var propValue = Firebug.getRepObject(Dom.getChildByClass(prop, "cssPropValue"));
+            var parsedValue = parsePriority(propValue);
+
+            if (previous)
+                CSSModule.removeProperty(rule, previous);
+            if (propValue)
+                CSSModule.setProperty(rule, value, parsedValue.value, parsedValue.priority);
+
+            Events.dispatch(CSSModule.fbListeners, "onCSSPropertyNameChanged", [rule, value,
+                    previous, baseText]);
+
+            Firebug.Inspector.repaint();
+            this.panel.markChange(this.panel.name == "stylesheet");
+        }
+        return true;
+    },
+
+    cancelEditing: function(target, value)
+    {
+        if (this.initiallyDisabled)
+        {
+            // Disable the property again.
+            var row = Dom.getAncestorByClass(target, "cssProp");
+            if (row && !row.classList.contains("disabledStyle"))
+                this.panel.disablePropertyRow(row);
+        }
+    },
+
     advanceToNext: function(target, charCode)
     {
         if (charCode == 58 /*":"*/ && Css.hasClass(target, "cssPropName"))
@@ -1783,6 +1881,20 @@ CSSEditor.prototype = domplate(Firebug.InlineEditor.prototype,
         }
     },
 
+    getInitialValue: function(target, value)
+    {
+        if (value == "")
+            return value;
+
+        var propValue = Dom.getAncestorByClass(target, "cssPropValue");
+        if (propValue)
+        {
+            var row = Dom.getAncestorByClass(target, "cssProp");
+            value = Firebug.getRepObject(propValue);
+        }
+        return value;
+    },
+
     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
     getAutoCompleteRange: function(value, offset)
@@ -1912,19 +2024,8 @@ CSSEditor.prototype = domplate(Firebug.InlineEditor.prototype,
                 keywords = Css.getCSSKeywordsByProperty(nodeType, propName, avoid);
             }
 
-            // Don't complete minus signs into -moz-calc (issue 5603). (Unless we
-            // have other specialized values as completions, like '-moz-available',
-            // in which case completion is still interesting.)
-            var isMoz = function(x)
-            {
-                return (x.charAt(0) === "-");
-            };
-            if (expr === "-" && keywords.filter(isMoz).join(",") === "-moz-calc()")
-            {
-                keywords = [];
-            }
-
             // Add the magic inherit property, if it's sufficiently alone.
+            // XXX Firefox 19 also has "initial"
             if (!preExpr)
                 keywords = keywords.concat(["inherit"]);
 
@@ -1942,7 +2043,7 @@ CSSEditor.prototype = domplate(Firebug.InlineEditor.prototype,
                 }
             }
 
-            return stripCompletedParens(keywords, postExpr);
+            return SelectorEditor.stripCompletedParens(keywords, postExpr);
         }
     },
 
@@ -2156,8 +2257,7 @@ function CSSRuleEditor(doc)
     this.initializeInline(doc);
 }
 
-CSSRuleEditor.uniquifier = 0;
-CSSRuleEditor.prototype = domplate(Firebug.InlineEditor.prototype,
+CSSRuleEditor.prototype = domplate(SelectorEditor.prototype,
 {
     insertNewRow: function(target, insertWhere)
     {
@@ -2176,18 +2276,19 @@ CSSRuleEditor.prototype = domplate(Firebug.InlineEditor.prototype,
 
     saveEdit: function(target, value, previousValue)
     {
+        var context = this.panel.context;
+
         if (FBTrace.DBG_CSS)
             FBTrace.sysout("CSSRuleEditor.saveEdit: '" + value + "'  '" + previousValue +
                 "'", target);
 
         target.innerHTML = Str.escapeForCss(value);
-
         if (value === previousValue)
             return;
 
         var row = Dom.getAncestorByClass(target, "cssRule");
-
         var rule = Firebug.getRepObject(target);
+
         var searchRule = rule || Firebug.getRepObject(row.nextSibling);
         var oldRule, ruleIndex;
 
@@ -2217,7 +2318,7 @@ CSSRuleEditor.prototype = domplate(Firebug.InlineEditor.prototype,
                 styleSheet = this.panel.location;
                 if (!styleSheet)
                 {
-                    var doc = this.panel.context.window.document;
+                    var doc = context.window.document;
                     this.panel.location = styleSheet =
                         CSSModule.getDefaultStyleSheet(doc);
                 }
@@ -2243,6 +2344,8 @@ CSSRuleEditor.prototype = domplate(Firebug.InlineEditor.prototype,
             CSSModule.deleteRule(styleSheet, ruleIndex);
         }
 
+        var doMarkChange = true;
+
         // Firefox does not follow the spec for the update selector text case.
         // When attempting to update the value, firefox will silently fail.
         // See https://bugzilla.mozilla.org/show_bug.cgi?id=37468 for the quite
@@ -2255,23 +2358,25 @@ CSSRuleEditor.prototype = domplate(Firebug.InlineEditor.prototype,
             var props = row.getElementsByClassName("cssProp");
             for (var i = 0; i < props.length; i++)
             {
+
                 var propEl = props[i];
                 if (!Css.hasClass(propEl, "disabledStyle"))
                 {
-                    cssText.push(Dom.getChildByClass(propEl, "cssPropName").textContent);
-                    cssText.push(":");
-                    cssText.push(Dom.getChildByClass(propEl, "cssPropValue").textContent);
-                    cssText.push(";");
+                    var propName = Dom.getChildByClass(propEl, "cssPropName").textContent;
+                    var propValue = Dom.getChildByClass(propEl, "cssPropValue").repObject;
+                    cssText.push(propName + ":" + propValue + ";");
                 }
             }
 
             cssText.push("}");
             cssText = cssText.join("");
-
+            
             try
             {
                 var insertLoc = CSSModule.insertRule(styleSheet, cssText, ruleIndex);
+
                 rule = cssRules[insertLoc];
+
                 ruleIndex++;
 
                 var saveSuccess = (this.panel.name != "css");
@@ -2296,237 +2401,43 @@ CSSRuleEditor.prototype = domplate(Firebug.InlineEditor.prototype,
 
                 this.box.setAttribute('saveSuccess', false);
 
-                row.repObject = rule;
-                return;
+                doMarkChange = false;
             }
         }
         else
         {
+            // XXX There is currently no way to re-add the rule after this happens.
             rule = undefined;
         }
 
         // Update the rep object
         row.repObject = rule;
-        if (!oldRule)
-        {
-            // Who knows what the domutils will return for rule line
-            // for a recently created rule. To be safe we just generate
-            // a unique value as this is only used as an internal key.
-            var ruleId = "new/"+value+"/"+(++CSSRuleEditor.uniquifier);
-            row.setAttribute("ruleId", ruleId);
-        }
+        if (oldRule && rule)
+            this.panel.remapRule(context, oldRule, rule);
 
-        this.panel.markChange(this.panel.name == "stylesheet");
+        if (doMarkChange)
+            this.panel.markChange(this.panel.name == "stylesheet");
     },
 
     getAutoCompleteRange: function(value, offset)
     {
         if (!Css.hasClass(this.target, "cssSelector"))
             return;
-
-        // Find the word part of an identifier.
-        var reIdent = /[-_a-zA-Z0-9]*/;
-        var rbefore = Str.reverseString(value.substr(0, offset));
-        var after = value.substr(offset);
-        var start = offset - reIdent.exec(rbefore)[0].length;
-        var end = offset + reIdent.exec(after)[0].length;
-
-        // Expand it to include '.', '#', ':', or '::'.
-        if (start > 0 && ".#:".indexOf(value.charAt(start-1)) !== -1)
-        {
-            --start;
-            if (start > 0 && value.substr(start-1, 2) === "::")
-                --start;
-        }
-        return {start: start, end: end};
+        return SelectorEditor.prototype.getAutoCompleteRange.apply(this, arguments);
     },
 
     getAutoCompleteList: function(preExpr, expr, postExpr, range, cycle, context, out)
     {
         if (!Css.hasClass(this.target, "cssSelector"))
             return [];
-
-        // Don't support attribute selectors, for now.
-        if (preExpr.lastIndexOf("[") > preExpr.lastIndexOf("]"))
-            return [];
-
-        if (preExpr.lastIndexOf("(") > preExpr.lastIndexOf(")"))
-        {
-            // We are in an parenthesized expression, where we can only complete
-            // for a few particular pseudo-classes that take selector-like arguments.
-            var par = preExpr.lastIndexOf("("), colon = preExpr.lastIndexOf(":", par);
-            if (colon === -1)
-                return;
-            var allowed = ["-moz-any", "not", "-moz-empty-except-children-with-localname"];
-            var name = preExpr.substring(colon+1, par);
-            if (allowed.indexOf(name) === -1)
-                return [];
-        }
-
-        var includeTagNames = true;
-        var includeIds = true;
-        var includeClasses = true;
-        var includePseudoClasses = true;
-        var includePseudoElements = true;
-
-        if (expr.length > 0)
-        {
-            includeTagNames = includeClasses = includeIds =
-                includePseudoClasses = includePseudoElements = false;
-            if (Str.hasPrefix(expr, "::"))
-                includePseudoElements = true;
-            else if (expr.charAt(0) === ":")
-                includePseudoClasses = true;
-            else if (expr.charAt(0) === "#")
-                includeIds = true;
-            else if (expr.charAt(0) === ".")
-                includeClasses = true;
-            else
-                includeTagNames = true;
-        }
-        if (preExpr.length > 0 && reSelectorChar.test(preExpr.slice(-1)))
-            includeTagNames = false;
-
-        var ret = [];
-
-        if (includeTagNames || includeIds || includeClasses)
-        {
-            // Traverse the DOM to get the used ids/classes/tag names that
-            // are relevant as continuations.
-            // (Tag names could be hard-coded, but finding which ones are
-            // actually used hides annoying things like 'b'/'i' when they
-            // are not used, and works in other contexts than HTML.)
-            // This isn't actually that bad, performance-wise.
-            var doc = context.window.document, els;
-            if (preExpr && " >+~".indexOf(preExpr.slice(-1)) === -1)
-            {
-                try
-                {
-                    var preSelector = preExpr.split(",").reverse()[0];
-                    els = doc.querySelectorAll(preSelector);
-                }
-                catch (exc)
-                {
-                    if (FBTrace.DBG_CSS)
-                        FBTrace.sysout("Invalid previous selector part \"" + preSelector + "\"", exc);
-                }
-            }
-            if (!els)
-                els = doc.getElementsByTagName("*");
-            els = [].slice.call(els);
-
-            if (includeTagNames)
-            {
-                var tagMap = {};
-                els.forEach(function(e)
-                {
-                    tagMap[e.localName] = 1;
-                });
-                ret.push.apply(ret, Object.keys(tagMap));
-            }
-
-            if (includeIds)
-            {
-                var ids = [];
-                els.forEach(function(e)
-                {
-                    if (e.id)
-                        ids.push(e.id);
-                });
-                ids = Arr.sortUnique(ids);
-                ret.push.apply(ret, ids.map(function(cl)
-                {
-                    return "#" + cl;
-                }));
-            }
-
-            if (includeClasses)
-            {
-                var clCombinationMap = {}, classes = [];
-                els.forEach(function(e)
-                {
-                    var cl = e.className;
-                    if (cl && !((","+cl) in clCombinationMap))
-                    {
-                        clCombinationMap[","+cl] = 1;
-                        classes.push.apply(classes, e.classList);
-                    }
-                });
-                classes = Arr.sortUnique(classes);
-                ret.push.apply(ret, classes.map(function(cl)
-                {
-                    return "." + cl;
-                }));
-            }
-        }
-
-        if (includePseudoClasses)
-        {
-            // Add the pseudo-class-looking :before, :after.
-            ret.push(
-                ":after",
-                ":before"
-            );
-
-            ret.push.apply(ret, stripCompletedParens(Css.pseudoClasses, postExpr));
-        }
-
-        if (includePseudoElements)
-        {
-            ret.push.apply(ret, Css.pseudoElements);
-        }
-
-        // Don't suggest things that are already included (by way of totally-
-        // incorrect-but-probably-good-enough logic).
-        var rev = Str.reverseString(preExpr);
-        var partInd = rev.search(/[, >+~]/);
-        var lastPart = (partInd === -1 ? rev : rev.substr(0, partInd));
-        lastPart = Str.reverseString(lastPart);
-        if (lastPart !== "")
-        {
-            ret = ret.filter(function(str)
-            {
-                var ind = lastPart.indexOf(str);
-                if (ind === -1)
-                    return true;
-                var before = ind-1, after = ind+str.length;
-                var re = reSelectorChar;
-                if (before >= 0 && re.test(str.charAt(0)) && re.test(lastPart.charAt(before)))
-                    return true;
-                if (after < lastPart.length && re.test(lastPart.charAt(after)))
-                    return true;
-                return false;
-            });
-        }
-
-        // Don't suggest internal Firebug things.
-        var reInternal = /^[.#]firebug[A-Z]/;
-        ret = ret.filter(function(str)
-        {
-            return !reInternal.test(str);
-        });
-
-        if (ret.indexOf(":hover") !== -1)
-            out.suggestion = ":hover";
-
-        return ret.sort();
+        return SelectorEditor.prototype.getAutoCompleteList.apply(this, arguments);
     },
 
     getAutoCompletePropSeparator: function(range, expr, prefixOf)
     {
         if (!Css.hasClass(this.target, "cssSelector"))
             return null;
-
-        // For e.g. 'd|span', expand to a descendant selector; otherwise assume
-        // that this is part of the same selector part.
-        return (reSelectorChar.test(prefixOf.charAt(0)) ? " " : "");
-    },
-
-    autoCompleteAdjustSelection: function(value, offset)
-    {
-        if (offset >= 2 && value.substr(offset-2, 2) === "()")
-            return offset-1;
-        return offset;
+        return SelectorEditor.prototype.getAutoCompletePropSeparator.apply(this, arguments);
     },
 
     advanceToNext: function(target, charCode)
@@ -2542,7 +2453,7 @@ CSSRuleEditor.prototype = domplate(Firebug.InlineEditor.prototype,
 // StyleSheetEditor
 
 /**
- * StyleSheetEditor represents an inline editor and is used when editing CSS
+ * StyleSheetEditor represents the full-sized editor used for Source/Live Edit
  * within the CSS panel.
  */
 function StyleSheetEditor(doc)
@@ -2700,23 +2611,6 @@ Firebug.CSSDirtyListener.prototype =
 // ********************************************************************************************* //
 // Local Helpers
 
-// Transform completions so that they don't add additional parentheses when
-// ones already exist.
-function stripCompletedParens(list, postExpr)
-{
-    var c = postExpr.charAt(0), rem = 0;
-    if (c === "(")
-        rem = 2;
-    else if (c === ")")
-        rem = 1;
-    else
-        return list;
-    return list.map(function(cl)
-    {
-        return (cl.slice(-2) === "()" ? cl.slice(0, -rem) : cl);
-    });
-}
-
 function parsePriority(value)
 {
     var rePriority = /(.*?)\s*(!important)?$/;
@@ -2726,6 +2620,23 @@ function parsePriority(value)
     return {value: propValue, priority: priority};
 }
 
+function formatColor(color)
+{
+    var colorDisplay = Options.get("colorDisplay");
+
+    switch (colorDisplay)
+    {
+        case "hex":
+            return Css.rgbToHex(color);
+
+        case "hsl":
+            return Css.rgbToHSL(color);
+            
+        default:
+            return color;
+    }
+}
+
 function getRuleLine(rule)
 {
     // TODO return closest guess if rule isn't CSSStyleRule
diff --git a/trace/FBTrace/chrome/firebug/content/css/cssReps.js b/trace/FBTrace/chrome/firebug/content/css/cssReps.js
index 0aa34a8..81ef9c9 100644
--- a/trace/FBTrace/chrome/firebug/content/css/cssReps.js
+++ b/trace/FBTrace/chrome/firebug/content/css/cssReps.js
@@ -115,7 +115,7 @@ var CSSInfoTip = Obj.extend(InfoTip,
                 }
             }
 
-            caption.innerHTML = Locale.$STRF("Dimensions", [w, h]);
+            caption.textContent = Locale.$STRF("Dimensions", [w, h]);
 
             Css.removeClass(innerBox, "infoTipLoading");
         },
@@ -131,9 +131,9 @@ var CSSInfoTip = Obj.extend(InfoTip,
 
             // Display an error in the caption (instead of dimensions).
             if (Str.hasPrefix(img.src, "moz-filedata"))
-                caption.innerHTML = Locale.$STR("firebug.failedToPreviewObjectURL");
+                caption.textContent = Locale.$STR("firebug.failedToPreviewObjectURL");
             else
-                caption.innerHTML = Locale.$STR("firebug.failedToPreviewImageURL");
+                caption.textContent = Locale.$STR("firebug.failedToPreviewImageURL");
 
             var innerBox = img.parentNode;
             Css.removeClass(innerBox, "infoTipLoading");
@@ -162,7 +162,7 @@ var CSSInfoTip = Obj.extend(InfoTip,
             fontObject: fontObject}, infoTip);
         var styleNode = node.getElementsByClassName("infoTipFontFamilyStyle").item(0);
 
-        styleNode.innerHTML = getFontFaceCSS(fontObject ? fontObject : fontName);
+        styleNode.textContent = getFontFaceCSS(fontObject ? fontObject : fontName);
         return true;
     },
 
diff --git a/trace/FBTrace/chrome/firebug/content/css/selectorEditor.js b/trace/FBTrace/chrome/firebug/content/css/selectorEditor.js
new file mode 100644
index 0000000..27fc5c1
--- /dev/null
+++ b/trace/FBTrace/chrome/firebug/content/css/selectorEditor.js
@@ -0,0 +1,252 @@
+/* See license.txt for terms of usage */
+
+define([
+    "firebug/firebug",
+    "firebug/lib/domplate",
+    "firebug/lib/locale",
+    "firebug/lib/css",
+    "firebug/lib/string",
+    "firebug/lib/array",
+],
+function(Firebug, Domplate, Locale, Css, Str, Arr) {
+with (Domplate) {
+
+// ********************************************************************************************* //
+// Constants
+
+const reSelectorChar = /[-_0-9a-zA-Z]/;
+
+// ********************************************************************************************* //
+// CSS Selector Editor
+
+function SelectorEditor() {}
+
+SelectorEditor.prototype = domplate(Firebug.InlineEditor.prototype,
+{
+    getAutoCompleteRange: function(value, offset)
+    {
+        // Find the word part of an identifier.
+        var reIdent = /[-_a-zA-Z0-9]*/;
+        var rbefore = Str.reverseString(value.substr(0, offset));
+        var after = value.substr(offset);
+        var start = offset - reIdent.exec(rbefore)[0].length;
+        var end = offset + reIdent.exec(after)[0].length;
+
+        // Expand it to include '.', '#', ':', or '::'.
+        if (start > 0 && ".#:".indexOf(value.charAt(start-1)) !== -1)
+        {
+            --start;
+            if (start > 0 && value.substr(start-1, 2) === "::")
+                --start;
+        }
+        return {start: start, end: end};
+    },
+
+    getAutoCompleteList: function(preExpr, expr, postExpr, range, cycle, context, out)
+    {
+        // Don't support attribute selectors, for now.
+        if (preExpr.lastIndexOf("[") > preExpr.lastIndexOf("]"))
+            return [];
+
+        if (preExpr.lastIndexOf("(") > preExpr.lastIndexOf(")"))
+        {
+            // We are in an parenthesized expression, where we can only complete
+            // for a few particular pseudo-classes that take selector-like arguments.
+            var par = preExpr.lastIndexOf("("), colon = preExpr.lastIndexOf(":", par);
+            if (colon === -1)
+                return;
+            var allowed = ["-moz-any", "not", "-moz-empty-except-children-with-localname"];
+            var name = preExpr.substring(colon+1, par);
+            if (allowed.indexOf(name) === -1)
+                return [];
+        }
+
+        var includeTagNames = true;
+        var includeIds = true;
+        var includeClasses = true;
+        var includePseudoClasses = true;
+        var includePseudoElements = true;
+
+        if (expr.length > 0)
+        {
+            includeTagNames = includeClasses = includeIds =
+                includePseudoClasses = includePseudoElements = false;
+            if (Str.hasPrefix(expr, "::"))
+                includePseudoElements = true;
+            else if (expr.charAt(0) === ":")
+                includePseudoClasses = true;
+            else if (expr.charAt(0) === "#")
+                includeIds = true;
+            else if (expr.charAt(0) === ".")
+                includeClasses = true;
+            else
+                includeTagNames = true;
+        }
+        if (preExpr.length > 0 && reSelectorChar.test(preExpr.slice(-1)))
+            includeTagNames = false;
+
+        var ret = [];
+
+        if (includeTagNames || includeIds || includeClasses)
+        {
+            // Traverse the DOM to get the used ids/classes/tag names that
+            // are relevant as continuations.
+            // (Tag names could be hard-coded, but finding which ones are
+            // actually used hides annoying things like 'b'/'i' when they
+            // are not used, and works in other contexts than HTML.)
+            // This isn't actually that bad, performance-wise.
+            var doc = context.window.document, els;
+            if (preExpr && " >+~".indexOf(preExpr.slice(-1)) === -1)
+            {
+                try
+                {
+                    var preSelector = preExpr.split(",").reverse()[0];
+                    els = doc.querySelectorAll(preSelector);
+                }
+                catch (exc)
+                {
+                    if (FBTrace.DBG_CSS)
+                        FBTrace.sysout("Invalid previous selector part \"" + preSelector + "\"", exc);
+                }
+            }
+            if (!els)
+                els = doc.getElementsByTagName("*");
+            els = [].slice.call(els);
+
+            if (includeTagNames)
+            {
+                var tagMap = {};
+                els.forEach(function(e)
+                {
+                    tagMap[e.localName] = 1;
+                });
+                ret.push.apply(ret, Object.keys(tagMap));
+            }
+
+            if (includeIds)
+            {
+                var ids = [];
+                els.forEach(function(e)
+                {
+                    if (e.id)
+                        ids.push(e.id);
+                });
+                ids = Arr.sortUnique(ids);
+                ret.push.apply(ret, ids.map(function(cl)
+                {
+                    return "#" + cl;
+                }));
+            }
+
+            if (includeClasses)
+            {
+                var clCombinationMap = Object.create(null), classes = [];
+                els.forEach(function(e)
+                {
+                    var cl = e.className;
+                    if (cl && !(cl in clCombinationMap))
+                    {
+                        clCombinationMap[cl] = 1;
+                        classes.push.apply(classes, e.classList);
+                    }
+                });
+                classes = Arr.sortUnique(classes);
+                ret.push.apply(ret, classes.map(function(cl)
+                {
+                    return "." + cl;
+                }));
+            }
+        }
+
+        if (includePseudoClasses)
+        {
+            // Add the pseudo-class-looking :before, :after.
+            ret.push(
+                ":after",
+                ":before"
+            );
+
+            ret.push.apply(ret, SelectorEditor.stripCompletedParens(Css.pseudoClasses, postExpr));
+        }
+
+        if (includePseudoElements)
+        {
+            ret.push.apply(ret, Css.pseudoElements);
+        }
+
+        // Don't suggest things that are already included (by way of totally-
+        // incorrect-but-probably-good-enough logic).
+        var rev = Str.reverseString(preExpr);
+        var partInd = rev.search(/[, >+~]/);
+        var lastPart = (partInd === -1 ? rev : rev.substr(0, partInd));
+        lastPart = Str.reverseString(lastPart);
+        if (lastPart !== "")
+        {
+            ret = ret.filter(function(str)
+            {
+                var ind = lastPart.indexOf(str);
+                if (ind === -1)
+                    return true;
+                var before = ind-1, after = ind+str.length;
+                var re = reSelectorChar;
+                if (before >= 0 && re.test(str.charAt(0)) && re.test(lastPart.charAt(before)))
+                    return true;
+                if (after < lastPart.length && re.test(lastPart.charAt(after)))
+                    return true;
+                return false;
+            });
+        }
+
+        // Don't suggest internal Firebug things.
+        var reInternal = /^[.#]firebug[A-Z]/;
+        ret = ret.filter(function(str)
+        {
+            return !reInternal.test(str);
+        });
+
+        if (ret.indexOf(":hover") !== -1)
+            out.suggestion = ":hover";
+
+        return ret.sort();
+    },
+
+    getAutoCompletePropSeparator: function(range, expr, prefixOf)
+    {
+        // For e.g. 'd|span', expand to a descendant selector; otherwise assume
+        // that this is part of the same selector part.
+        return (reSelectorChar.test(prefixOf.charAt(0)) ? " " : "");
+    },
+
+    autoCompleteAdjustSelection: function(value, offset)
+    {
+        if (offset >= 2 && value.substr(offset-2, 2) === "()")
+            return offset-1;
+        return offset;
+    }
+});
+
+
+// Transform completions so that they don't add additional parentheses when
+// ones already exist.
+SelectorEditor.stripCompletedParens = function(list, postExpr)
+{
+    var c = postExpr.charAt(0), rem = 0;
+    if (c === "(")
+        rem = 2;
+    else if (c === ")")
+        rem = 1;
+    else
+        return list;
+    return list.map(function(cl)
+    {
+        return (cl.slice(-2) === "()" ? cl.slice(0, -rem) : cl);
+    });
+};
+
+// ********************************************************************************************* //
+// Registration
+
+return SelectorEditor;
+
+// ********************************************************************************************* //
+}});
diff --git a/trace/FBTrace/chrome/firebug/content/css/selectorModule.js b/trace/FBTrace/chrome/firebug/content/css/selectorModule.js
new file mode 100644
index 0000000..f238322
--- /dev/null
+++ b/trace/FBTrace/chrome/firebug/content/css/selectorModule.js
@@ -0,0 +1,74 @@
+/* See license.txt for terms of usage */
+
+define([
+    "firebug/firebug",
+    "firebug/lib/trace",
+    "firebug/lib/object",
+    "firebug/lib/dom",
+    "firebug/lib/locale",
+    "firebug/chrome/menu"
+],
+function(Firebug, FBTrace, Obj, Dom, Locale, Menu) {
+
+// ********************************************************************************************* //
+// Model implementation
+
+var SelectorModule = Obj.extend(Firebug.Module,
+{
+    dispatchName: "selectorModule",
+
+    initialize: function()
+    {
+        Firebug.NetMonitor.NetInfoBody.addListener(this);
+        Firebug.registerUIListener(this);
+    },
+
+    shutdown: function()
+    {
+        Firebug.NetMonitor.NetInfoBody.removeListener(this);
+        Firebug.unregisterUIListener(this);
+    },
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+    // Context Menu
+
+    onContextMenu: function(items, object, target, context, panel, popup)
+    {
+        if (panel.name != "stylesheet")
+            return;
+
+        var cssRule = Dom.getAncestorByClass(target, "cssRule");
+        if (!cssRule)
+            return;
+
+        var rule = cssRule.repObject;
+        if (!rule)
+            return;
+
+        var panel = context.getPanel("selector");
+        if (!panel)
+            return;
+
+        var item = {
+           id: "fbGetMatchingElements",
+           nol10n: true,
+           label: Locale.$STR("css.selector.cmd.getMatchingElements"),
+           command: Obj.bindFixed(panel.getMatchingElements, panel, rule)
+        };
+
+        var refreshMenuItem = popup.querySelector("#fbRefresh");
+        Menu.createMenuItem(popup, item, refreshMenuItem);
+
+        return [];
+    },
+});
+
+// ********************************************************************************************* //
+// Registration
+
+Firebug.registerModule(SelectorModule);
+
+return SelectorModule;
+
+// ********************************************************************************************* //
+});
diff --git a/trace/FBTrace/chrome/firebug/content/css/selectorPanel.js b/trace/FBTrace/chrome/firebug/content/css/selectorPanel.js
new file mode 100644
index 0000000..56182e2
--- /dev/null
+++ b/trace/FBTrace/chrome/firebug/content/css/selectorPanel.js
@@ -0,0 +1,460 @@
+/* See license.txt for terms of usage */
+
+define([
+    "firebug/firebug",
+    "firebug/lib/object",
+    "firebug/lib/locale",
+    "firebug/lib/events",
+    "firebug/lib/dom",
+    "firebug/lib/domplate",
+    "firebug/chrome/menu",
+    "firebug/css/selectorEditor",
+    "firebug/css/selectorModule",
+],
+function(Firebug, Obj, Locale, Events, Dom, Domplate, Menu, SelectorEditor) {
+with (Domplate) {
+
+// ********************************************************************************************* //
+// Constants
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+const prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
+
+// ********************************************************************************************* //
+// CSS Selector Panel
+
+/**
+ * @panel Selector side panel displaying HTML elements for the current selector,
+ * either from the CSS main panel or user entry
+ */
+function SelectorPanel() {}
+SelectorPanel.prototype = Obj.extend(Firebug.Panel,
+/** @lends SelectorPanel */
+{
+    name: "selector",
+    parentPanel: "stylesheet",
+    title: Locale.$STR("css.selector.Selection"),
+    editable: true,
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+    // Initialization
+
+    initialize: function(context, doc)
+    {
+        Firebug.Panel.initialize.apply(this, arguments);
+    },
+
+    shutdown: function(context, doc)
+    {
+        Firebug.Panel.shutdown.apply(this, arguments);
+    },
+
+    initializeNode: function(oldPanelNode)
+    {
+        Firebug.Panel.initializeNode.apply(this, arguments);
+
+        this.setSelection = Obj.bind(this.setSelection, this);
+        this.clearSelection = Obj.bind(this.clearSelection, this);
+        this.lockSelection = Obj.bind(this.lockSelection, this);
+
+        var panelNode = this.mainPanel.panelNode;
+        // See: http://code.google.com/p/fbug/issues/detail?id=5931
+        //Events.addEventListener(panelNode, "mouseover", this.setSelection, false);
+        //Events.addEventListener(panelNode, "mouseout", this.clearSelection, false);
+        //Events.addEventListener(panelNode, "mousedown", this.lockSelection, false);
+    },
+
+    destroyNode: function()
+    {
+        var panelNode = this.mainPanel.panelNode;
+        //Events.removeEventListener(panelNode, "mouseover", this.setSelection, false);
+        //Events.removeEventListener(panelNode, "mouseout", this.clearSelection, false);
+        //Events.removeEventListener(panelNode, "mousedown", this.lockSelection, false);
+
+        Firebug.Panel.destroyNode.apply(this, arguments);
+    },
+
+    show: function(state)
+    {
+        Firebug.Panel.show.apply(this, arguments);
+
+        this.refresh();
+    },
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+    getCSSStyleRule: function(event)
+    {
+        var object = Firebug.getRepObject(event.target);
+
+        if (object && (object instanceof window.CSSStyleRule))
+            return object;
+    },
+
+    getCSSRuleElement: function(element)
+    {
+        while (element && !element.classList.contains("cssRule"))
+            element = element.parentNode;
+
+        return element;
+    },
+
+    getMatchingElements: function(rule)
+    {
+        this.trialSelector = rule.selectorText;
+        this.selection = rule;
+        this.rebuild();
+    },
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+    // Selection
+
+    setSelection: function(event)
+    {
+        var rule = this.getCSSStyleRule(event);
+
+        if (rule)
+        {
+            // then we have entered a rule element
+            var ruleElement = this.getCSSRuleElement(event.target);
+            if (ruleElement && ruleElement !== this.lockedElement)
+                ruleElement.classList.add("selectedSelectorRule");
+
+            this.selection = rule;
+            this.rebuild();
+        }
+    },
+
+    clearSelection: function(event)
+    {
+        if (this.selection !== this.lockedSelection)
+        {
+            this.selection = this.lockedSelection;
+            this.rebuild();
+        }
+
+        var rule = this.getCSSStyleRule(event);
+        if (rule)
+        {
+            // then we are leaving a rule element that we may have highlighted.
+            var ruleElement = this.getCSSRuleElement(event.target);
+            if (ruleElement)
+                ruleElement.classList.remove("selectedSelectorRule");
+        }
+    },
+
+    lockSelection: function(event)
+    {
+        var rule = this.getCSSStyleRule(event);
+        if (rule)
+        {
+            if (this.lockedElement)
+                this.lockedElement.classList.remove("lockedSelectorRule");
+
+            this.lockedElement = this.getCSSRuleElement(event.target);
+
+            if (this.lockedElement)
+            {
+                this.lockedElement.classList.add("lockedSelectorRule");
+                this.lockedElement.classList.remove("selectedSelectorRule");
+            }
+
+            this.lockedSelection = rule;
+        }
+    },
+
+    hide: function()
+    {
+        Firebug.Panel.hide.apply(this, arguments);
+    },
+
+    refresh: function()
+    {
+        var root = this.context.window.document.documentElement;
+        this.selection = this.mainPanel.selection;
+
+        // Use trial selector if there is no selection in the CSS panel.
+        if (!this.selection)
+            this.selection = this.trialSelector;
+
+        this.rebuild(true);
+    },
+
+    /**
+     * returns an array of Elements matched from selector
+     */
+    getSelectedElements: function(selectorText)
+    {
+        var elements = [];
+
+        // Execute the query also in all iframes (see issue 5962)
+        var windows = this.context.windows;
+        for (var i=0; i<windows.length; i++)
+        {
+            var win = windows[i];
+            var selections = win.document.querySelectorAll(selectorText);
+
+            // For some reason the return value of querySelectorAll()
+            // is not recognized as a NodeList anymore since Firefox 10.0.
+            // See issue 5442.
+            // But since there can be more iframes we need to collect all matching
+            // elements in an extra array anyway.
+            if (selections)
+            {
+                for (var j=0; j<selections.length; j++)
+                    elements.push(selections[j]);
+            }
+            else
+            {
+                throw new Error("Selection Failed: " + selections);
+            }
+        }
+
+        return elements;
+    },
+
+    /**
+     * Build content of the panel. The basic layout of the panel is generated by
+     * {@link SelectorTemplate} template.
+     */
+    rebuild: function()
+    {
+        if (this.selection)
+        {
+            try
+            {
+                var selectorText;
+
+                if (this.selection instanceof window.CSSStyleRule)
+                    selectorText = this.selection.selectorText;
+                else
+                    selectorText = this.selection;
+
+                var elements = this.getSelectedElements(selectorText);
+                if (elements && elements.length != 0)
+                {
+                    SelectorTemplate.tag.replace({object: elements}, this.panelNode);
+                    this.showTrialSelector(this.trialSelector);
+                    return;
+                }
+            }
+            catch (e)
+            {
+                var table = SelectorTemplate.tag.replace({object: []}, this.panelNode);
+                var tbody = table.lastChild;
+
+                WarningTemplate.selectErrorTag.insertRows({object: e}, tbody.lastChild);
+                WarningTemplate.selectErrorTextTag.insertRows({object: e}, tbody.lastChild);
+
+                this.showTrialSelector(this.trialSelector);
+                return;
+            }
+        }
+
+        var table = SelectorTemplate.tag.replace({object: []}, this.panelNode);
+        var tbody = table.lastChild;
+
+        if (this.trialSelector)
+        {
+            WarningTemplate.noSelectionResultsTag.insertRows(
+                {object: this.selection}, tbody.lastChild)
+        }
+        else
+        {
+            WarningTemplate.noSelectionTag.insertRows(
+                {object: this.selection}, tbody.lastChild);
+        }
+
+        this.showTrialSelector(this.trialSelector);
+    },
+
+    getObjectPath: function(object)
+    {
+        if (FBTrace.DBG_SELECTOR)
+            FBTrace.sysout("css.selector.getObjectPath NOOP", object);
+    },
+
+    supportsObject: function(object)
+    {
+        return 0;
+    },
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+    tryASelector: function(element)
+    {
+        if (!this.trialSelector)
+            this.trialSelector = this.selection ? this.selection.selectorText : "";
+
+        this.editProperty(element, this.trialSelector);
+    },
+
+    editProperty: function(row, editValue)
+    {
+        Firebug.Editor.startEditing(row, editValue);
+    },
+
+    getEditor: function(target, value)
+    {
+        if (!this.editor)
+            this.editor = new SelectorPanelEditor(this.document);
+
+        return this.editor;
+    },
+
+    setTrialSelector: function(target, value)
+    {
+        if (this.lockedElement)
+            this.lockedElement.classList.remove("lockedSelectorRule");
+
+        this.trialSelector = value;
+        this.selection = this.trialSelector;
+        this.lockedElement = target;
+        this.lockedSelection = this.selection;
+        this.rebuild();
+    },
+
+    showTrialSelector: function(trialSelector)
+    {
+        var show = trialSelector ? true : false;
+        Dom.collapse(this.document.getElementById("trialHint"), show);
+
+        var trialSelectorDiv = this.document.getElementById("trialSelector");
+        trialSelectorDiv.textContent = trialSelector;
+        Dom.collapse(trialSelectorDiv, !show);
+    },
+});
+
+function SelectorPanelEditor(doc)
+{
+    this.box = this.tag.replace({}, doc, this);
+    this.input = this.box;
+
+    Firebug.InlineEditor.prototype.initialize.call(this);
+    this.tabNavigation = false;
+    this.fixedWidth = true;
+}
+
+SelectorPanelEditor.prototype = domplate(SelectorEditor.prototype,
+{
+    tag:
+        INPUT({"class": "fixedWidthEditor a11yFocusNoTab",
+            type: "text",
+            title: Locale.$STR("Selector"),
+            oninput: "$onInput",
+            onkeypress: "$onKeyPress"}
+        ),
+
+    endEditing: function(target, value, cancel)
+    {
+        if (cancel)
+            return;
+
+        this.panel.setTrialSelector(target, value);
+    }
+});
+
+// ********************************************************************************************* //
+
+var BaseRep = domplate(Firebug.Rep,
+{
+    // xxxHonza: shouldn't this be in Firebug.Rep?
+    getNaturalTag: function(value)
+    {
+        var rep = Firebug.getRep(value);
+        var tag = rep.shortTag ? rep.shortTag : rep.tag;
+        return tag;
+    }
+});
+
+// ********************************************************************************************* //
+
+var TrialRow =
+    TR({"class": "watchNewRow", level: 0, onclick: "$onClickEditor"},
+        TD({"class": "watchEditCell", colspan: 3},
+            DIV({"class": "watchEditBox a11yFocusNoTab", "id": "trialHint",
+                role: "button", "tabindex" : "0",
+                "aria-label": Locale.$STR("a11y.labels.press enter to add new selector")},
+                Locale.$STR("css.selector.TryASelector")
+            ),
+            DIV({"class": "trialSelector", "id": "trialSelector"}, "")
+        )
+    );
+
+// ********************************************************************************************* //
+
+/**
+ * @domplate: Template for basic layout of the {@link SelectorPanel} panel.
+ */
+var SelectorTemplate = domplate(BaseRep,
+{
+    // object will be array of elements CSSStyleRule
+    tag:
+        TABLE({"class": "cssSelectionTable", cellpadding: 0, cellspacing: 0},
+            TBODY({"class": "cssSelectionTBody"},
+                TrialRow,
+                FOR("element", "$object",
+                    TR({"class": "selectionElementRow", _repObject: "$element"},
+                        TD({"class": "selectionElement"},
+                            TAG( "$element|getNaturalTag", {object: "$element"})
+                        )
+                    )
+                )
+            )
+        ),
+
+    onClickEditor: function(event)
+    {
+        var tr = event.currentTarget;
+        var panel = Firebug.getElementPanel(tr);
+        panel.tryASelector(tr);
+    },
+});
+
+// ********************************************************************************************* //
+
+var WarningTemplate = domplate(Firebug.Rep,
+{
+    noSelectionTag:
+        TR({"class": "selectorWarning"},
+            TD({"class": "selectionElement"}, Locale.$STR("css.selector.noSelection"))
+        ),
+
+    noSelectionResultsTag:
+        TR({"class": "selectorWarning"},
+            TD({"class": "selectionElement"}, Locale.$STR("css.selector.noSelectionResults"))
+        ),
+
+    selectErrorTag:
+        TR({"class": "selectorWarning"},
+            TD({"class": "selectionElement"}, Locale.$STR("css.selector.selectorError"))
+        ),
+
+    selectErrorTextTag:
+        TR({"class": "selectorWarning"},
+            TD({"class": "selectionErrorText selectionElement"},
+                SPAN("$object|getErrorMessage")
+            )
+        ),
+
+    getErrorMessage: function(object)
+    {
+        if (object.message)
+            return object.message;
+
+        return Locale.$STR("css.selector.unknownErrorMessage");
+    }
+});
+
+// ********************************************************************************************* //
+// Registration
+
+Firebug.registerStylesheet("chrome://firebug/skin/selector.css");
+Firebug.registerPanel(SelectorPanel);
+
+return SelectorPanel;
+
+// ********************************************************************************************* //
+}});
diff --git a/trace/FBTrace/chrome/firebug/content/css/stylePanel.js b/trace/FBTrace/chrome/firebug/content/css/stylePanel.js
index 6f5ef01..f18b80d 100644
--- a/trace/FBTrace/chrome/firebug/content/css/stylePanel.js
+++ b/trace/FBTrace/chrome/firebug/content/css/stylePanel.js
@@ -15,7 +15,6 @@ define([
     "firebug/lib/dom",
     "firebug/lib/css",
     "firebug/lib/xpath",
-    "firebug/lib/array",
     "firebug/lib/fonts",
     "firebug/lib/options",
     "firebug/css/cssModule",
@@ -23,7 +22,7 @@ define([
     "firebug/chrome/menu"
 ],
 function(Obj, Firebug, Firefox, Domplate, FirebugReps, Xpcom, Locale, Events, Url, Arr,
-    SourceLink, Dom, Css, Xpath, Arr, Fonts, Options, CSSModule, CSSStyleSheetPanel, Menu) {
+    SourceLink, Dom, Css, Xpath, Fonts, Options, CSSModule, CSSStyleSheetPanel, Menu) {
 
 with (Domplate) {
 
@@ -95,12 +94,12 @@ CSSStylePanel.prototype = Obj.extend(CSSStyleSheetPanel.prototype,
 
         getSeparator: function(part)
         {
-            if (part.type == "otherProps")
-                return " ";
-
             if (part.lastFont || part.type == "important")
                 return "";
 
+            if (part.type == "otherProps")
+                return " ";
+
             return ",";
         },
 
@@ -257,11 +256,9 @@ CSSStylePanel.prototype = Obj.extend(CSSStyleSheetPanel.prototype,
                 if (!isPseudoElementSheet)
                     this.markOverriddenProps(element, props, usedProps, inheritMode);
 
-                var ruleId = this.getRuleId(rule);
-                rules.unshift({rule: rule, id: ruleId,
-                    // Show universal selectors with pseudo-class
-                    // (http://code.google.com/p/fbug/issues/detail?id=3683)
-                    selector: rule.selectorText.replace(/ :/g, " *:"),
+                rules.unshift({
+                    rule: rule,
+                    selector: rule.selectorText.replace(/ :/g, " *:"), // (issue 3683)
                     sourceLink: sourceLink,
                     props: props, inherited: inheritMode,
                     isSystemSheet: isSystemSheet,
@@ -443,7 +440,7 @@ CSSStylePanel.prototype = Obj.extend(CSSStyleSheetPanel.prototype,
     getStyleProperties: function(element, rules, usedProps, inheritMode)
     {
         var props = this.parseCSSProps(element.style, inheritMode);
-        this.addOldProperties(this.context, Xpath.getElementXPath(element), inheritMode, props);
+        this.addDisabledProperties(this.context, element, inheritMode, props);
 
         this.sortProperties(props);
 
@@ -451,8 +448,8 @@ CSSStylePanel.prototype = Obj.extend(CSSStyleSheetPanel.prototype,
 
         if (props.length)
         {
-            rules.unshift({rule: element, id: Xpath.getElementXPath(element),
-                    selector: "element.style", props: props, inherited: inheritMode});
+            rules.unshift({rule: element, selector: "element.style",
+                props: props, inherited: inheritMode});
         }
     },
 
@@ -511,8 +508,18 @@ CSSStylePanel.prototype = Obj.extend(CSSStyleSheetPanel.prototype,
 
     updateView: function(element)
     {
-        CSSModule.cleanupSheets(element.ownerDocument, Firebug.currentContext);
+        var result = CSSModule.cleanupSheets(element.ownerDocument, Firebug.currentContext);
 
+        // If cleanupSheets returns false there was an exception thrown when accessing
+        // a styleshet (probably since it isn't fully loaded yet). So, delay the panel
+        // update and try it again a bit later (issue 5654).
+        if (!result)
+        {
+            this.context.setTimeout(Obj.bindFixed(this.updateView, this, element), 200);
+            return;
+        }
+
+        // All stylesheets should be ready now, update the view.
         this.updateCascadeView(element);
 
         if (Dom.domUtils)
@@ -531,7 +538,7 @@ CSSStylePanel.prototype = Obj.extend(CSSStyleSheetPanel.prototype,
         if (sothinkInstalled)
         {
             var div = FirebugReps.Warning.tag.replace({object: "SothinkWarning"}, this.panelNode);
-            div.innerHTML = Locale.$STR("SothinkWarning");
+            div.textContent = Locale.$STR("SothinkWarning");
             return;
         }
 
@@ -591,6 +598,7 @@ CSSStylePanel.prototype = Obj.extend(CSSStyleSheetPanel.prototype,
                     }
                 }
             );
+
             if (Dom.domUtils.hasPseudoClassLock)
             {
                 items.push(
@@ -633,7 +641,7 @@ CSSStylePanel.prototype = Obj.extend(CSSStyleSheetPanel.prototype,
         },
         {
             label: "AddRule",
-            tooltiptext: "style.tip.Add_Rule",
+            tooltiptext: "css.tip.AddRule",
             command: Obj.bindFixed(this.addRelatedRule, this)
         });
 
@@ -658,7 +666,7 @@ CSSStylePanel.prototype = Obj.extend(CSSStyleSheetPanel.prototype,
         var prop = Dom.getAncestorByClass(target, "cssProp");
         if (prop)
             var propNameNode = prop.getElementsByClassName("cssPropName").item(0);
-  
+
         if (propNameNode && (propNameNode.textContent.toLowerCase() == "font" ||
             propNameNode.textContent.toLowerCase() == "font-family"))
         {
@@ -670,9 +678,27 @@ CSSStylePanel.prototype = Obj.extend(CSSStyleSheetPanel.prototype,
             }
         }
 
-        return CSSStyleSheetPanel.prototype.showInfoTip.call(this, infoTip, target, x, y, rangeParent, rangeOffset);
+        return CSSStyleSheetPanel.prototype.showInfoTip.call(
+            this, infoTip, target, x, y, rangeParent, rangeOffset);
+    },
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+    // Extends stylesheet (CSS Panel)
+
+    deleteRuleDeclaration: function(cssSelector)
+    {
+        var repObject = Firebug.getRepObject(cssSelector);
+
+        if (repObject instanceof window.Element)
+            CSSModule.deleteRule(repObject);
+        else
+            CSSStyleSheetPanel.prototype.deleteRuleDeclaration(cssSelector);
+
+        this.refresh();
     },
 
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
     hasPseudoClassLock: function(pseudoClass)
     {
         if (Dom.domUtils.hasPseudoClassLock)
@@ -813,7 +839,7 @@ function getFontPropValueParts(element, value, propName)
         "monospace": 1,
     };
 
-    var parts = [];
+    var parts = [], origValue = value;
 
     // (Mirroring CSSModule.parseCSSFontFamilyValue)
     if (propName === "font")
@@ -827,7 +853,11 @@ function getFontPropValueParts(element, value, propName)
         );
         var matches = rePreFont.exec(value);
         if (!matches)
-            return;
+        {
+            // Non-simple font value, like "inherit", "status-bar" or
+            // "calc(12px) Arial" - just return the whole text.
+            return [{type: "otherProps", value: value, lastFont: true}];
+        }
         var preProps = matches[0].slice(0, -1);
         parts.push({type: "otherProps", value: preProps});
         value = value.substr(matches[0].length);
@@ -836,13 +866,23 @@ function getFontPropValueParts(element, value, propName)
     var matches = /^(.*?)( !important)?$/.exec(value);
     var fonts = matches[1].split(",");
 
-    // Clone the element to just get the fonts used in it and not its descendants
-    var clonedElement = element.cloneNode(false);
-    clonedElement.textContent = element.textContent;
-    Firebug.setIgnored(clonedElement);
-    element.parentNode.appendChild(clonedElement);
-    var usedFonts = Fonts.getFonts(clonedElement).slice();
-    clonedElement.parentNode.removeChild(clonedElement);
+    // What we want to know is what the specified "font-family" property means
+    // for the selected element's text, not what the element actually uses (that
+    // depends on font styles of its descendants). Thus, we just check the direct
+    // child text nodes of the element.
+    // Do not create a temporary element for testing to avoid problems like in
+    // issue 5905 and 6048
+    var usedFonts = [];
+    var child = element.firstChild;
+    do
+    {
+        if (!child)
+            break;
+
+        if (child.nodeType == Node.TEXT_NODE)
+            usedFonts = Arr.extendArray(usedFonts, Fonts.getFonts(child));
+    }
+    while (child = child.nextSibling);
 
     var genericFontUsed = false;
     for (var i = 0; i < fonts.length; ++i)
diff --git a/trace/FBTrace/chrome/firebug/content/dom/domPanel.js b/trace/FBTrace/chrome/firebug/content/dom/domPanel.js
index 7e642c8..d9eee6f 100644
--- a/trace/FBTrace/chrome/firebug/content/dom/domPanel.js
+++ b/trace/FBTrace/chrome/firebug/content/dom/domPanel.js
@@ -126,9 +126,9 @@ const DirTablePlate = domplate(Firebug.Rep,
             TAG("$memberRowTag", {member: "$member"})
         ),
 
-    memberIterator: function(object, level)
+    memberIterator: function(object)
     {
-        var members = Firebug.DOMBasePanel.prototype.getMembers(object, level, this.context);
+        var members = Firebug.DOMBasePanel.prototype.getMembers(object, 0, null);
         if (members.length)
             return members;
 
@@ -422,16 +422,23 @@ Firebug.DOMBasePanel.prototype = Obj.extend(Firebug.Panel,
     /**
      * @param object a user-level object wrapped in security blanket
      * @param level for a.b.c, level is 2
-     * @param context
+     * @param optional context
      */
     getMembers: function(object, level, context)
     {
         if (!level)
             level = 0;
 
-        var ordinals = [], userProps = [], userClasses = [], userFuncs = [],
-            domProps = [], domFuncs = [], domConstants = [], proto = [],
-            domHandlers = [];
+        var ordinals = [];
+        var userProps = [];
+        var userClasses = [];
+        var userFuncs = [];
+        var domProps = [];
+        var domClasses = [];
+        var domFuncs = [];
+        var domConstants = [];
+        var proto = [];
+        var domHandlers = [];
 
         try
         {
@@ -439,12 +446,6 @@ Firebug.DOMBasePanel.prototype = Obj.extend(Firebug.Panel,
             if (isArguments(object))
                 object = Arr.cloneArray(object);
 
-            if ("StorageList" in window && object instanceof window.StorageList)
-            {
-                var domain = context.window.location.hostname;
-                object = object.namedItem(domain);
-            }
-
             try
             {
                 var contentView = this.getObjectView(object);
@@ -537,13 +538,24 @@ Firebug.DOMBasePanel.prototype = Obj.extend(Firebug.Panel,
                 else if (typeof(val) == "function")
                 {
                     if (isClassFunction(val))
-                        this.addMember(object, "userClass", userClasses, name, val, level, 0, context);
+                    {
+                        if (Dom.isDOMMember(object, name))
+                            this.addMember(object, "domClass", domClasses, name, val, level, domMembers[name], context);
+                        else
+                            this.addMember(object, "userClass", userClasses, name, val, level, 0, context);
+                    }
                     else if (Dom.isDOMMember(object, name))
+                    {
                         this.addMember(object, "domFunction", domFuncs, name, val, level, domMembers[name], context);
+                    }
                     else if (!Firebug.showUserFuncs && Firebug.showInlineEventHandlers)
+                    {
                         this.addMember(object, "userFunction", domHandlers, name, val, level, 0, context);
+                    }
                     else
+                    {
                         this.addMember(object, "userFunction", userFuncs, name, val, level, 0, context);
+                    }
                 }
                 else
                 {
@@ -600,6 +612,9 @@ Firebug.DOMBasePanel.prototype = Obj.extend(Firebug.Panel,
 
         if (Firebug.showDOMFuncs)
         {
+            domClasses.sort(sortName);
+            members.push.apply(members, domClasses);
+
             domFuncs.sort(sortName);
             members.push.apply(members, domFuncs);
         }
@@ -682,12 +697,6 @@ Firebug.DOMBasePanel.prototype = Obj.extend(Firebug.Panel,
             }
         }
 
-        if ("StorageList" in window && value instanceof window.StorageList)
-        {
-            var domain = context.window.location.hostname;
-            hasChildren = value.namedItem(domain).length > 0;
-        }
-
         var member = {
             object: object,
             name: name,
@@ -1589,6 +1598,7 @@ Firebug.DOMBasePanel.prototype = Obj.extend(Firebug.Panel,
                 items.push(
                     {
                         label: isWatch ? "DeleteWatch" : "DeleteProperty",
+                        id: "DeleteProperty",
                         tooltiptext: isWatch ? "watch.tip.Delete_Watch" :
                             "dom.tip.Delete_Property",
                         command: Obj.bindFixed(this.deleteProperty, this, row)
diff --git a/trace/FBTrace/chrome/firebug/content/editor/editor.js b/trace/FBTrace/chrome/firebug/content/editor/editor.js
index 0fd9cb8..9e08249 100644
--- a/trace/FBTrace/chrome/firebug/content/editor/editor.js
+++ b/trace/FBTrace/chrome/firebug/content/editor/editor.js
@@ -164,6 +164,8 @@ Firebug.Editor = Obj.extend(Firebug.Module,
                 if (value != originalValue)
                     this.saveEditAndNotifyListeners(currentTarget, originalValue, previousValue);
 
+                currentEditor.cancelEditing(currentTarget, originalValue);
+
                 if (removeGroup && !originalValue && currentGroup)
                     currentGroup.parentNode.removeChild(currentGroup);
             }
@@ -548,6 +550,10 @@ Firebug.BaseEditor = Obj.extend(Firebug.MeasureBox,
         return true;
     },
 
+    cancelEditing: function(target, value)
+    {
+    },
+
     insertNewRow: function(target, insertWhere)
     {
     },
@@ -924,8 +930,9 @@ Firebug.InlineEditor.prototype = domplate(Firebug.BaseEditor,
             Events.cancelEvent(event);
         }
         else if (this.numeric && event.charCode &&
-            (event.charCode < KeyEvent.DOM_VK_0 || event.charCode > KeyEvent.DOM_VK_9) &&
-            event.charCode != KeyEvent.DOM_VK_INSERT && event.charCode != KeyEvent.DOM_VK_DELETE)
+            !(event.ctrlKey || event.metaKey || event.altKey) &&
+            !(KeyEvent.DOM_VK_0 <= event.charCode && event.charCode <= KeyEvent.DOM_VK_9) &&
+            event.charCode !== KeyEvent.DOM_VK_INSERT && event.charCode !== KeyEvent.DOM_VK_DELETE)
         {
             Events.cancelEvent(event);
         }
@@ -965,12 +972,9 @@ Firebug.InlineEditor.prototype = domplate(Firebug.BaseEditor,
         Dom.eraseNode(popup);
 
         var target = event.target;
-        var menu = this.getContextMenuItems(target);
-        if (menu)
-        {
-            for (var i = 0; i < menu.length; ++i)
-                Menu.createMenuItem(popup, menu[i]);
-        }
+        var items = this.getContextMenuItems(target);
+        if (items)
+            Menu.createMenuItems(popup, items);
 
         if (!popup.firstChild)
             return false;
@@ -1028,7 +1032,7 @@ Firebug.InlineEditor.prototype = domplate(Firebug.BaseEditor,
 
             if(this.wrapped)
             {
-                var fixupL = clR[1].left - clR[0].left,
+                var fixupL = clR[1].left - clR[0].left;
                     fixupT = clR[1].top - clR[0].top;
             }
             else
diff --git a/trace/FBTrace/chrome/firebug/content/firebug.css b/trace/FBTrace/chrome/firebug/content/firebug.css
index 5c134bb..296d49b 100644
--- a/trace/FBTrace/chrome/firebug/content/firebug.css
+++ b/trace/FBTrace/chrome/firebug/content/firebug.css
@@ -19,7 +19,7 @@ window[chromehidden~="toolbar"] #fbToolbar {
 /* Firebug Splitter */
 
 #fbContentSplitter[dir=reverse]{
-    -moz-transform: scale(-1, -1);
+    transform: scale(-1, -1);
 }
 
 #fbContentSplitter[orient=vertical] {
@@ -79,6 +79,7 @@ textbox#fbCommandEditor {
 
 .completionText {
     color: #666666;
+    margin-right: 1px;
 }
 [selected="true"] > .completionText {
     background-color: highlight;
@@ -261,7 +262,8 @@ panelTab > panelTabMenu .menuPopup:-moz-locale-dir(rtl) {
     height: 20px;
 }
 
-#fbLocationList.noTabStop> menupopup > arrowscrollbox> scrollbox {
+#fbLocationList.noTabStop > menupopup > arrowscrollbox > scrollbox,
+#fbCommandHistory > arrowscrollbox > scrollbox {
     overflow-y: auto;
 }
 
@@ -345,7 +347,7 @@ panelTab > panelTabMenu .menuPopup:-moz-locale-dir(rtl) {
 
 panelTab[breakOnNextArmed="true"] > .panelTab-text {
     text-shadow: 1px 1px 2px darkGray, 0 0 1em orange, 0 0 0.2em orange !important;
-    /* -moz-animation: armedBlinking 0.8s ease-out infinite alternate; see issue 5618 */
+    /* animation: armedBlinking 0.8s ease-out infinite alternate; see issue 5618 */
 }
 
 /* see issue 5618
diff --git a/trace/FBTrace/chrome/firebug/content/firebug.js b/trace/FBTrace/chrome/firebug/content/firebug.js
index df69413..e1d93e2 100644
--- a/trace/FBTrace/chrome/firebug/content/firebug.js
+++ b/trace/FBTrace/chrome/firebug/content/firebug.js
@@ -21,11 +21,11 @@ define([
     "firebug/lib/array",
     "firebug/lib/dom",
     "firebug/lib/http",
-    "firebug/js/fbs",
     "firebug/trace/traceListener",
+    "firebug/console/commandLineExposed",
 ],
 function(FBL, Obj, Firefox, ChromeFactory, Domplate, Options, Locale, Events,
-    Wrapper, Url, Css, Win, Str, Arr, Dom, Http, FBS, TraceListener) {
+    Wrapper, Url, Css, Win, Str, Arr, Dom, Http, TraceListener, CommandLineExposed) {
 
 // ********************************************************************************************* //
 // Constants
@@ -65,6 +65,7 @@ var panelTypeMap = {};
 
 // ********************************************************************************************* //
 
+//xxxHonza: we should use the existing Firebug object.
 if (window.Firebug)
 {
     // Stow the pre-load properties, add them back at the end
@@ -147,7 +148,9 @@ window.Firebug =
         // Append early registered panels at the end.
         panelTypes.push.apply(panelTypes, tempPanelTypes);
 
-        Firebug.Options.addListener(this);
+        // Firebug is getting option-updates from the connection so,
+        // do not register it again here (see issue 6035)
+        //Firebug.Options.addListener(this);
 
         this.isInitialized = true;
 
@@ -253,10 +256,6 @@ window.Firebug =
         if (Firebug.PanelActivation)
             Firebug.PanelActivation.activatePanelTypes(panelTypes);
 
-        // bug712289
-        if (Firebug.PanelActivation && !FBS.isJSDAvailable())
-            Firebug.PanelActivation.disablePanel(this.getPanelType("script"));
-
         // Tell the modules the UI is up.
         Events.dispatch(modules, "initializeUI", [detachArgs]);
     },
@@ -397,23 +396,29 @@ window.Firebug =
         var contextURLSet = [];
 
         // create a list of all unique activeContexts
-        Firebug.connection.eachContext( function createActiveContextList(context)
+        Firebug.connection.eachContext(function createActiveContextList(context)
         {
             if (FBTrace.DBG_WINDOWS)
-                FBTrace.sysout("context "+context.getName());
+                FBTrace.sysout("context " + context.getName());
 
             try
             {
                 var cw = context.window;
                 if (cw)
                 {
+                    var url;
                     if (cw.closed)
+                    {
                         url = "about:closed";
+                    }
                     else
-                        if ('location' in cw)
-                            var url = cw.location.toString();
+                    {
+                        if ("location" in cw)
+                            url = cw.location.toString();
                         else
-                            var url = context.getName();
+                            url = context.getName();
+                    }
+
                     if (url)
                     {
                         if (contextURLSet.indexOf(url) == -1)
@@ -657,6 +662,16 @@ window.Firebug =
             Firebug.TraceModule.removeListener(listener);
     },
 
+    registerCommand: function(name, config)
+    {
+        return CommandLineExposed.registerCommand(name, config);
+    },
+
+    unregistereCommand: function(name)
+    {
+        return CommandLineExposed.unregisterCommand(name);
+    },
+
     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
     // Options
 
@@ -861,11 +876,11 @@ window.Firebug =
             // TODO reattach
 
             // window is closing in detached mode
-            if (Firebug.chrome.window.top)
+            var parent = this.getFirebugFrameParent();
+            if (parent)
             {
-                topWindow = Firebug.chrome.window.top;
-                topWindow.exportFirebug();
-                topWindow.close();
+                parent.exportFirebug();
+                parent.close();
             }
 
             Firebug.setPlacement("minimized");
@@ -906,9 +921,9 @@ window.Firebug =
         //detached -> inbrowser
         if (!forceOpen && Firebug.isDetached())
         {
-            var topWin = Firebug.chrome.window.top;
-            topWin.exportFirebug();
-            topWin.close();
+            var parent = this.getFirebugFrameParent();
+            parent.exportFirebug();
+            parent.close();
 
             if (reopenInBrowser)
             {
@@ -953,7 +968,6 @@ window.Firebug =
         Firebug.StartButton.resetTooltip();
     },
 
-
     detachBar: function()
     {
         if (Firebug.isDetached())  // can be set true attachBrowser
@@ -964,8 +978,8 @@ window.Firebug =
 
         if (Firebug.chrome.waitingForDetach)
             return null;
-        Firebug.chrome.waitingForDetach = true;
 
+        Firebug.chrome.waitingForDetach = true;
         Firebug.chrome.toggleOpen(false);  // don't show in browser.xul now
 
         if (FBTrace.DBG_ACTIVATION)
@@ -996,6 +1010,22 @@ window.Firebug =
     },
 
     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+    /**
+     * Returns parent of the firebugFrame.xul frame. The actual parent depends on whether
+     * Firebug is attached or detached.
+     *
+     * attached -> browser.xul
+     * detached -> firebug.xul
+     */
+    getFirebugFrameParent: function()
+    {
+        // We need firebug.xul in case of detached state. So, don't use 'top' since
+        // it references browser.xul
+        return Firebug.chrome.window.parent;
+    },
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
     // deprecated
 
     resetAllOptions: function(confirm)
@@ -1240,7 +1270,7 @@ window.Firebug =
             if (Css.hasClass(child, "repTarget"))
                 target = child;
 
-            if (child.repObject)
+            if (child.repObject != null)
             {
                 if (!target && Css.hasClass(child, "repIgnore"))
                     break;
@@ -1257,7 +1287,7 @@ window.Firebug =
     {
         for (var child = node; child; child = child.parentNode)
         {
-            if (child.repObject)
+            if (child.repObject != null)
                 return child;
         }
     },
@@ -1266,7 +1296,7 @@ window.Firebug =
     {
         for (var child = element.firstChild; child; child = child.nextSibling)
         {
-            if (child.repObject == object)
+            if (child.repObject === object)
                 return child;
         }
     },
@@ -1394,7 +1424,7 @@ window.Firebug =
     {
         testLists.push({
             extension: "Firebug",
-            testListURL: "http://getfirebug.com/tests/head/firebug.html"
+            testListURL: "https://getfirebug.com/tests/1.11/firebug.html"
         });
     }
 };
@@ -1719,9 +1749,11 @@ Firebug.Panel = Obj.extend(new Firebug.Listener(),
 
         if (this.panelNode)
         {
+            var scrollTop = this.panelNode.scrollTop;
             this.panelNode = doc.adoptNode(this.panelNode, true);
             this.panelNode.ownerPanel = this;
             doc.body.appendChild(this.panelNode);
+            this.panelNode.scrollTop = scrollTop;
         }
     },
 
@@ -2507,6 +2539,11 @@ Firebug.Rep = domplate(
             return m ? m[1] : label;
     },
 
+    showInfoTip: function(infoTip, target, x, y)
+    {
+        return false;
+    },
+
     getTooltip: function(object)
     {
         return null;
diff --git a/trace/FBTrace/chrome/firebug/content/firebugOverlay.xul b/trace/FBTrace/chrome/firebug/content/firebugOverlay.xul
index daba10f..a7963c1 100644
--- a/trace/FBTrace/chrome/firebug/content/firebugOverlay.xul
+++ b/trace/FBTrace/chrome/firebug/content/firebugOverlay.xul
@@ -4,8 +4,6 @@
 <?xul-overlay href="firefox/firebugMenuOverlay.xul"?>
 <?xul-overlay href="chrome://firebug/content/cookies/cookiePanel.xul"?>
 
-<?xml-stylesheet href="firebug.css"?>
-
 <overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
          xmlns:html="http://www.w3.org/1999/xhtml">
 
@@ -36,8 +34,8 @@
             noautofocus="true">
         </panel>
 
-        <panel id="fbCommandHistory" noautofocus="true">
-        </panel>
+        <menupopup id="fbCommandHistory" noautofocus="true" ignorekeys="true">
+        </menupopup>
 
         <!-- Context menu for the Command Editor -->
         <menupopup id="fbCommandEditorPopup" />
@@ -62,8 +60,8 @@
                                 <image src="chrome://firebug/skin/firebug.png"/>
 
                                 <menupopup id="menu_firebug_iconMenu" class="fbFirebugMenuPopup"
-                                    onpopupshowing="return Firebug.GlobalUI.onMenuShowing(this);"
-                                    onpopuphiding="return Firebug.GlobalUI.onMenuHiding(this);">
+                                    onpopupshowing="return Firebug.browserOverlay.onMenuShowing(this, event);"
+                                    onpopuphiding="return Firebug.browserOverlay.onMenuHiding(this, event);">
                                     <!-- Content comes from firebugMenuContent -->
                                 </menupopup>
                             </toolbarbutton>
@@ -117,7 +115,7 @@
                     <!-- Open In New Window & Minimize & Close -->
                     <hbox id="fbWindowButtons" role="toolbar" class="innerToolbar"
                         aria-label="firebug window" context="_child">
-                        <menupopup onpopupshowing="Firebug.GlobalUI.onPositionPopupShowing(this)"/>
+                        <menupopup onpopupshowing="Firebug.browserOverlay.onPositionPopupShowing(this)"/>
                         <toolbarbutton id="fbMinimizeButton"
                             class="toolbarbutton-iconic fbInternational"
                             tooltiptext="Minimize Firebug" command="cmd_firebug_minimizeFirebug"/>
@@ -489,10 +487,11 @@
                         <!-- completion text -->
                         <html:input id="fbCommandLineCompletion" class="fbCommandLine"
                             type="text" maxlength="2048" autocomplete="off" tabindex="-1" />
-                        <!-- holds the misspelling and a red squiggly line -->
-                        <html:div id="misspell" class="lst"></html:div>
                         <textbox id="fbCommandLine" class="fbCommandLine" flex="1"
                             aria-autocomplete="inline" multiline="false" newlines="pasteintact"/>
+                        <!-- font width measurer, contains 60 arbitrary characters -->
+                        <html:span id="fbCommandLineMeasurer" class="fbCommandLine"
+                            >aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</html:span>
                     </html:div>
                 </vbox>
             </hbox>
diff --git a/trace/FBTrace/chrome/firebug/content/firefox/bindings.xml b/trace/FBTrace/chrome/firebug/content/firefox/bindings.xml
index 239acd7..96a4cb0 100644
--- a/trace/FBTrace/chrome/firebug/content/firefox/bindings.xml
+++ b/trace/FBTrace/chrome/firebug/content/firefox/bindings.xml
@@ -1258,8 +1258,9 @@
 
                 for (var j = 0; j < urls.length; ++j)
                 {
+                    var label = urls[j].fileName != path ? urls[j].fileName : "Inline";
                     var menuInfo = {
-                        label: urls[j].fileName != path ? urls[j].fileName : "Inline",
+                        label: FBL.cropString(label, Firebug.Options.get("stringCropLength")),
                         tooltiptext: path + urls[j].fileName,
                         nol10n: true
                     };
@@ -1293,14 +1294,14 @@
             this.filter.filterString = "";
 
             this.onkeypress = FBL.bind(this.onKeyPress, this);
-            window.top.addEventListener("keypress", this.onkeypress, true);
+            window.parent.addEventListener("keypress", this.onkeypress, true);
 
             this.onclick = FBL.bind(this.onClick, this);
             this.popup.addEventListener("click", this.onclick, true);
         ]]></handler>
 
         <handler event="popuphidden"><![CDATA[
-            window.top.removeEventListener("keypress", this.onkeypress, true);
+            window.parent.removeEventListener("keypress", this.onkeypress, true);
             this.popup.removeEventListener("click", this.onclick, true);
 
             delete this.onkeypress;
@@ -1340,7 +1341,7 @@
                 {
                     if (child.localName == "menuitem")
                     {
-                        var label = child.getAttribute("label").toLowerCase();
+                        var label = child.getAttribute("tooltiptext").toLowerCase();
                         child._searchMatch = label.indexOf(substring) != -1;
                         if (child._searchMatch)
                         {
diff --git a/trace/FBTrace/chrome/firebug/content/firefox/browserCommands.js b/trace/FBTrace/chrome/firebug/content/firefox/browserCommands.js
new file mode 100644
index 0000000..8f8d6d2
--- /dev/null
+++ b/trace/FBTrace/chrome/firebug/content/firefox/browserCommands.js
@@ -0,0 +1,107 @@
+/* See license.txt for terms of usage */
+
+define([
+    "firebug/lib/trace",
+    "firebug/lib/options",
+    "firebug/lib/locale",
+    "firebug/firefox/browserOverlayLib",
+],
+function(FBTrace, Options, Locale, BrowserOverlayLib) {
+with (BrowserOverlayLib) {
+
+// ********************************************************************************************* //
+// Constants
+
+var shortcuts = [
+    "toggleFirebug",
+    "toggleInspecting",
+    "focusCommandLine",
+    "detachFirebug",
+    "closeFirebug",
+    "toggleBreakOn"
+]
+
+/* Used by the browser menu, but should be really global shortcuts?
+key_increaseTextSize
+key_decreaseTextSize
+key_normalTextSize
+key_help
+key_toggleProfiling
+key_focusFirebugSearch
+key_customizeFBKeys
+*/
+
+// ********************************************************************************************* //
+// BrowserCommands Implementation
+
+var BrowserCommands =
+{
+    overlay: function(doc)
+    {
+        this.overlayCommands(doc);
+        this.overlayShortcuts(doc);
+    },
+
+    overlayCommands: function(doc)
+    {
+        $command(doc, "cmd_firebug_closeFirebug", "Firebug.closeFirebug(true);");
+        $command(doc, "cmd_firebug_toggleInspecting", "if (!Firebug.currentContext) Firebug.toggleBar(true); Firebug.Inspector.toggleInspecting(Firebug.currentContext);");
+        $command(doc, "cmd_firebug_focusCommandLine", "if (!Firebug.currentContext) Firebug.toggleBar(true); Firebug.CommandLine.focus(Firebug.currentContext);");
+        $command(doc, "cmd_firebug_toggleFirebug", "Firebug.toggleBar();");
+        $command(doc, "cmd_firebug_detachFirebug", "Firebug.toggleDetachBar(false, true);");
+        $command(doc, "cmd_firebug_inspect", "Firebug.Inspector.inspectFromContextMenu(arg);", "document.popupNode");
+        $command(doc, "cmd_firebug_toggleBreakOn", "if (Firebug.currentContext) Firebug.chrome.breakOnNext(Firebug.currentContext, event);");
+        $command(doc, "cmd_firebug_toggleDetachFirebug", "Firebug.toggleDetachBar(false, true);");
+        $command(doc, "cmd_firebug_increaseTextSize", "Firebug.Options.changeTextSize(1);");
+        $command(doc, "cmd_firebug_decreaseTextSize", "Firebug.Options.changeTextSize(-1);");
+        $command(doc, "cmd_firebug_normalTextSize", "Firebug.Options.setTextSize(0);");
+        $command(doc, "cmd_firebug_focusFirebugSearch", "if (Firebug.currentContext) Firebug.Search.onSearchCommand(document);");
+        $command(doc, "cmd_firebug_customizeFBKeys", "Firebug.ShortcutsModel.customizeShortcuts();");
+        $command(doc, "cmd_firebug_enablePanels", "Firebug.PanelActivation.enableAllPanels();");
+        $command(doc, "cmd_firebug_disablePanels", "Firebug.PanelActivation.disableAllPanels();");
+        $command(doc, "cmd_firebug_clearActivationList", "Firebug.PanelActivation.clearAnnotations();");
+        $command(doc, "cmd_firebug_clearConsole", "Firebug.Console.clear(Firebug.currentContext);");
+        $command(doc, "cmd_firebug_allOn", "Firebug.PanelActivation.toggleAll('on');");
+        $command(doc, "cmd_firebug_toggleOrient", "Firebug.chrome.toggleOrient();");
+        $command(doc, "cmd_firebug_resetAllOptions", "Firebug.resetAllOptions(true);");
+        $command(doc, "cmd_firebug_toggleProfiling", ""); //todo
+        $command(doc, "cmd_firebug_openInEditor", "Firebug.ExternalEditors.onContextMenuCommand(event)");
+    },
+
+    overlayShortcuts: function(doc)
+    {
+        var keyset = $(doc, "mainKeyset");
+
+        for (var i=0; i<shortcuts.length ; i++)
+        {
+            var id = shortcuts[i];
+            var shortcut = Options.get("key.shortcut." + id);
+            var tokens = shortcut.split(" ");
+            var key = tokens.pop();
+
+            var keyProps = {
+                id: "key_firebug_" + id,
+                modifiers: tokens.join(","),
+                command: "cmd_firebug_" + id,
+                position: 1
+            };
+
+            if (key.length <= 1)
+                keyProps.key = key;
+            else if (doc.defaultView.KeyEvent["DOM_"+key])
+                keyProps.keycode = key;
+
+            $el(doc, "key", keyProps, keyset);
+        }
+
+        keyset.parentNode.insertBefore(keyset, keyset.nextSibling);
+    }
+}
+
+// ********************************************************************************************* //
+// Registration
+
+return BrowserCommands;
+
+// ********************************************************************************************* //
+}});
diff --git a/trace/FBTrace/chrome/firebug/content/firefox/browserMenu.js b/trace/FBTrace/chrome/firebug/content/firefox/browserMenu.js
new file mode 100644
index 0000000..d1ce9ec
--- /dev/null
+++ b/trace/FBTrace/chrome/firebug/content/firefox/browserMenu.js
@@ -0,0 +1,522 @@
+/* See license.txt for terms of usage */
+
+define([
+    "firebug/lib/trace",
+    "firebug/lib/options",
+    "firebug/lib/locale",
+    "firebug/firefox/browserOverlayLib",
+],
+function(FBTrace, Options, Locale, BrowserOverlayLib) {
+with (BrowserOverlayLib) {
+
+// ********************************************************************************************* //
+// GlobalCommands Implementation
+
+var BrowserMenu =
+{
+    overlay: function(doc)
+    {
+        this.overlayStartButtonMenu(doc);
+        this.overlayFirebugMenu(doc);
+        this.overlayFirefoxMenu(doc);
+    },
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+    // Firebug Start Button Popup Menu
+
+    overlayStartButtonMenu: function(doc)
+    {
+        $menupopupOverlay(doc, $(doc, "mainPopupSet"), [
+            $menupopup(doc, 
+            {
+                id: "fbStatusContextMenu",
+                onpopupshowing: "Firebug.browserOverlay.onOptionsShowing(this)"
+            },
+            [
+                $menu(doc, 
+                {
+                    label: "firebug.uiLocation",
+                    tooltiptext: "firebug.menu.tip.UI_Location",
+                    "class": "fbInternational"
+                },
+                [
+                    $menupopup(doc, {
+                        onpopupshowing: "Firebug.browserOverlay.onPositionPopupShowing(this)"
+                    })
+                ]),
+                $menuseparator(doc),
+                $menuitem(doc, {
+                    id: "menu_firebug_ClearConsole",
+                    label: "firebug.ClearConsole",
+                    tooltiptext: "firebug.ClearTooltip",
+                    command: "cmd_firebug_clearConsole",
+                    key: "key_firebug_clearConsole"
+                }),
+                $menuitem(doc, {
+                    id: "menu_firebug_showErrorCount",
+                    type: "checkbox",
+                    label: "firebug.Show_Error_Count",
+                    tooltiptext: "firebug.menu.tip.Show_Error_Count",
+                    oncommand: "Firebug.browserOverlay.onToggleOption(this)",
+                    option: "showErrorCount"
+                }),
+                $menuseparator(doc),
+                $menuitem(doc, {
+                    id: "menu_firebug_enablePanels",
+                    label: "firebug.menu.Enable_All_Panels",
+                    tooltiptext: "firebug.menu.tip.Enable_All_Panels",
+                    command: "cmd_firebug_enablePanels"
+                }),
+                $menuitem(doc, {
+                    id: "menu_firebug_disablePanels",
+                    label: "firebug.menu.Disable_All_Panels",
+                    tooltiptext: "firebug.menu.tip.Disable_All_Panels",
+                    command: "cmd_firebug_disablePanels"
+                }),
+                $menuseparator(doc),
+                $menuitem(doc, {
+                    id: "menu_firebug_AllOn",
+                    type: "checkbox",
+                    label: "On_for_all_web_pages",
+                    tooltiptext: "firebug.menu.tip.On_for_all_Web_Sites",
+                    command: "cmd_firebug_allOn",
+                    option: "allPagesActivation"
+                }),
+                $menuitem(doc, {
+                    id: "menu_firebug_clearActivationList",
+                    label: "firebug.menu.Clear_Activation_List",
+                    tooltiptext: "firebug.menu.tip.Clear_Activation_List",
+                    command: "cmd_firebug_clearActivationList"
+                })
+            ])
+        ])
+    },
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+    // Firebug Global Menu
+
+    /**
+     * There are more instances of Firebug Menu (e.g. one in Firefox -> Tools -> Web Developer
+     * and one in Firefox 4 (top-left orange button menu) -> Web Developer
+     *
+     * If extensions want to override the menu thay need to iterate all existing instance
+     * using document.querySelectorAll(".fbFirebugMenuPopup") and append new menu items to all
+     * of them. Iteration must be done in the global space (browser.xul)
+     *
+     * The same menu is also used for Firebug Icon Menu (Firebug's toolbar). This menu is cloned
+     * and initialized as soon as Firebug UI is actually loaded. Since it's cloned from the original
+     * (global scope) extensions don't have to extend it (possible new menu items are already there).
+     */
+    overlayFirebugMenu: function(doc)
+    {
+        this.firebugMenuContent =
+        [
+            // Open/close Firebug
+            $menuitem(doc,
+            {
+                id: "menu_firebug_toggleFirebug",
+                label: "firebug.ShowFirebug",
+                tooltiptext: "firebug.menu.tip.Open_Firebug",
+                command: "cmd_firebug_toggleFirebug",
+                key: "key_firebug_toggleFirebug",
+                "class": "fbInternational"
+            }),
+            $menuitem(doc,
+            {
+                id: "menu_firebug_closeFirebug",
+                label: "firebug.Deactivate_Firebug",
+                tooltiptext: "firebug.tip.Deactivate_Firebug",
+                command: "cmd_firebug_closeFirebug",
+                key: "key_firebug_closeFirebug",
+                "class": "fbInternational"
+            }),
+
+            // Firebug UI position
+            $menu(doc,
+            {
+                label: "firebug.uiLocation",
+                tooltiptext: "firebug.menu.tip.UI_Location",
+                "class": "fbInternational"
+            },
+            [
+                $menupopup(doc, {
+                    onpopupshowing: "Firebug.browserOverlay.onPositionPopupShowing(this)"
+                })
+            ]),
+
+            $menuseparator(doc),
+
+            // External Editors
+            $menu(doc,
+            {
+                id: "FirebugMenu_OpenWith",
+                label:"firebug.OpenWith",
+                tooltiptext:"firebug.menu.tip.Open_With",
+                "class": "fbInternational",
+                insertafter: "menu_firebug_openActionsSeparator",
+                openFromContext: "true",
+                command: "cmd_firebug_openInEditor"
+            },
+            [
+                $menupopup(doc,{id:"fbFirebugMenu_OpenWith",
+                    onpopupshowing: "return Firebug.browserOverlay.onEditorsShowing(this);"})
+            ]),
+
+            // Text Size
+            $menu(doc,
+            {
+                id: "FirebugMenu_TextSize",
+                label: "firebug.TextSize",
+                tooltiptext: "firebug.menu.tip.Text_Size",
+                "class": "fbInternational"
+            },
+            [
+                $menupopup(doc,{},
+                [
+                    $menuitem(doc,
+                    {
+                        id: "menu_firebug_increaseTextSize",
+                        label: "firebug.IncreaseTextSize",
+                        tooltiptext: "firebug.menu.tip.Increase_Text_Size",
+                        command: "cmd_firebug_increaseTextSize",
+                        key: "key_firebug_increaseTextSize",
+                        "class": "fbInternational"
+                    }),
+                    $menuitem(doc,
+                    {
+                        id: "menu_firebug_decreaseTextSize",
+                        label: "firebug.DecreaseTextSize",
+                        tooltiptext: "firebug.menu.tip.Decrease_Text_Size",
+                        command: "cmd_firebug_decreaseTextSize",
+                        key: "key_firebug_decreaseTextSize",
+                        "class": "fbInternational"
+                    }),
+                    $menuitem(doc,
+                    {
+                        id: "menu_firebug_normalTextSize",
+                        label: "firebug.NormalTextSize",
+                        tooltiptext: "firebug.menu.tip.Normal_Text_Size",
+                        command: "cmd_firebug_normalTextSize",
+                        key: "key_firebug_normalTextSize",
+                        "class": "fbInternational"
+                    }),
+                ])
+            ]),
+
+            // Options
+            $menu(doc,
+            {
+                id: "FirebugMenu_Options",
+                label: "firebug.Options",
+                tooltiptext: "firebug.menu.tip.Options",
+                "class": "fbInternational"
+            },
+            [
+                $menupopup(doc,
+                {
+                    id: "FirebugMenu_OptionsPopup",
+                    onpopupshowing: "return Firebug.browserOverlay.onOptionsShowing(this);"
+                },
+                [
+                    $menuitem(doc,
+                    {
+                        id: "menu_firebug_toggleShowErrorCount",
+                        type: "checkbox",
+                        label: "firebug.Show_Error_Count",
+                        tooltiptext: "firebug.menu.tip.Show_Error_Count",
+                        oncommand: "Firebug.browserOverlay.onToggleOption(this)",
+                        option: "showErrorCount",
+                        "class": "fbInternational"
+                    }),
+                    $menuitem(doc,
+                    {
+                        id: "menu_firebug_showTooltips",
+                        type: "checkbox",
+                        label: "firebug.menu.Show_Info_Tips",
+                        tooltiptext: "firebug.menu.tip.Show_Info_Tips",
+                        oncommand: "Firebug.browserOverlay.onToggleOption(this)",
+                        option: "showInfoTips",
+                        "class": "fbInternational"
+                    }),
+                    $menuitem(doc,
+                    {
+                        id: "menu_firebug_shadeBoxModel",
+                        type: "checkbox",
+                        label: "ShadeBoxModel",
+                        tooltiptext: "inspect.option.tip.Shade_Box_Model",
+                        oncommand: "Firebug.browserOverlay.onToggleOption(this)",
+                        option: "shadeBoxModel",
+                        "class": "fbInternational"
+                    }),
+                    $menuitem(doc,
+                    {
+                        id: "menu_firebug_showQuickInfoBox",
+                        type: "checkbox",
+                        label: "ShowQuickInfoBox",
+                        tooltiptext: "inspect.option.tip.Show_Quick_Info_Box",
+                        oncommand: "Firebug.browserOverlay.onToggleOption(this)",
+                        option: "showQuickInfoBox",
+                        "class": "fbInternational"
+                    }),
+                    $menuitem(doc,
+                    {
+                        id: "menu_firebug_enableA11y",
+                        type: "checkbox",
+                        label: "firebug.menu.Enable_Accessibility_Enhancements",
+                        tooltiptext: "firebug.menu.tip.Enable_Accessibility_Enhancements",
+                        oncommand: "Firebug.browserOverlay.onToggleOption(this)",
+                        option: "a11y.enable",
+                        "class": "fbInternational"
+                    }),
+                    $menuitem(doc,
+                    {
+                        id: "menu_firebug_activateSameOrigin",
+                        type: "checkbox",
+                        label: "firebug.menu.Activate_Same_Origin_URLs2",
+                        tooltiptext: "firebug.menu.tip.Activate_Same_Origin_URLs",
+                        oncommand: "Firebug.browserOverlay.onToggleOption(this)",
+                        option: "activateSameOrigin",
+                        "class": "fbInternational"
+                    }),
+                    $menuitem(doc,
+                    {
+                        id: "menu_firebug_toggleOrient",
+                        type: "checkbox",
+                        label: "firebug.menu.Vertical_Panels",
+                        tooltiptext: "firebug.menu.tip.Vertical_Panels",
+                        command: "cmd_firebug_toggleOrient",
+                        option: "viewPanelOrient",
+                        "class": "fbInternational"
+                    }),
+                    $menuseparator(doc, {id: "menu_firebug_optionsSeparator"}),
+                    $menuitem(doc,
+                    {
+                        id: "menu_firebug_resetAllOptions",
+                        label: "firebug.menu.Reset_All_Firebug_Options",
+                        tooltiptext: "firebug.menu.tip.Reset_All_Firebug_Options",
+                        command: "cmd_firebug_resetAllOptions",
+                        "class": "fbInternational"
+                    }),
+                ])
+            ]),
+
+            $menuseparator(doc,{id: "FirebugBetweenOptionsAndSites", collapsed: "true"}),
+
+            // Sites
+            $menu(doc,
+            {
+                id: "FirebugMenu_Sites",
+                label: "firebug.menu.Firebug_Online",
+                tooltiptext: "firebug.menu.tip.Firebug_Online",
+                "class": "fbInternational"
+            },
+            [
+                $menupopup(doc,{},
+                [
+                    $menuitem(doc,
+                    {
+                        id: "menu_firebug_firebugUrlWebsite",
+                        label: "firebug.Website",
+                        tooltiptext: "firebug.menu.tip.Website",
+                        oncommand: "Firebug.chrome.visitWebsite('main')",
+                        "class": "fbInternational"
+                    }),
+                    $menuitem(doc,
+                    {
+                        id: "menu_firebug_firebugUrlExtensions",
+                        label: "firebug.menu.Extensions",
+                        tooltiptext: "firebug.menu.tip.Extensions",
+                        oncommand: "Firebug.chrome.visitWebsite('extensions')",
+                        "class": "fbInternational"
+                    }),
+                    $menuitem(doc,
+                    {
+                        id: "menu_firebug_firebugHelp",
+                        label: "firebug.help",
+                        tooltiptext: "firebug.menu.tip.help",
+                        command: "cmd_firebug_openHelp",
+                        key: "key_firebug_help",
+                        "class": "fbInternational"
+                    }),
+                    $menuitem(doc,
+                    {
+                        id: "menu_firebug_firebugDoc",
+                        label: "firebug.Documentation",
+                        tooltiptext: "firebug.menu.tip.Documentation",
+                        oncommand: "Firebug.chrome.visitWebsite('docs')",
+                        "class": "fbInternational"
+                    }),
+                    $menuitem(doc,
+                    {
+                        id: "menu_firebug_firebugKeyboard",
+                        label: "firebug.KeyShortcuts",
+                        tooltiptext: "firebug.menu.tip.Key_Shortcuts",
+                        oncommand: "Firebug.chrome.visitWebsite('keyboard')",
+                        "class": "fbInternational"
+                    }),
+                    $menuitem(doc,
+                    {
+                        id: "menu_firebug_firebugForums",
+                        label: "firebug.Forums",
+                        tooltiptext: "firebug.menu.tip.Forums",
+                        oncommand: "Firebug.chrome.visitWebsite('discuss')",
+                        "class": "fbInternational"
+                    }),
+                    $menuitem(doc,
+                    {
+                        id: "menu_firebug_firebugIssues",
+                        label: "firebug.Issues",
+                        tooltiptext: "firebug.menu.tip.Issues",
+                        oncommand: "Firebug.chrome.visitWebsite('issues')",
+                        "class": "fbInternational"
+                    }),
+                    $menuitem(doc,
+                    {
+                        id: "menu_firebug_firebugDonate",
+                        label: "firebug.Donate",
+                        tooltiptext: "firebug.menu.tip.Donate",
+                        oncommand: "Firebug.chrome.visitWebsite('donate')",
+                        "class": "fbInternational"
+                    }),
+                ])
+            ]),
+
+            $menuseparator(doc, {id: "menu_firebug_miscActionsSeparator", collapsed: "true"}),
+
+            $menuseparator(doc, {id: "menu_firebug_toolsSeparator", collapsed: "true"}),
+
+            $menuitem(doc,
+            {
+                id: "menu_firebug_customizeShortcuts",
+                label: "firebug.menu.Customize_shortcuts",
+                tooltiptext: "firebug.menu.tip.Customize_Shortcuts",
+                command: "cmd_firebug_customizeFBKeys",
+                key: "key_firebug_customizeFBKeys",
+                "class": "fbInternational"
+            }),
+
+            $menuseparator(doc, {id: "menu_firebug_aboutSeparator"}),
+
+            $menuitem(doc, {
+                id: "menu_firebug_about",
+                label: "firebug.About",
+                tooltiptext: "firebug.menu.tip.About",
+                oncommand: "Firebug.browserOverlay.openAboutDialog()",
+                "class": "firebugAbout fbInternational"
+            }),
+        ];
+    },
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+    // Global Menu Overlays
+
+    overlayFirefoxMenu: function(doc)
+    {
+        // Firefox page context menu
+        $menupopupOverlay(doc, $(doc, "contentAreaContextMenu"), [
+            $menuseparator(doc),
+            $menuitem(doc,{
+                id: "menu_firebug_firebugInspect",
+                label: "firebug.InspectElementWithFirebug",
+                command: "cmd_firebug_inspect",
+                "class": "menuitem-iconic fbInternational"
+            })
+        ]);
+
+        // Firefox view menu
+        $menupopupOverlay(doc, $(doc, "menu_viewPopup"), [
+            $menuitem(doc, {
+                id: "menu_firebug_viewToggleFirebug",
+                insertbefore: "toggle_taskbar",
+                label: "firebug.Firebug",
+                type: "checkbox",
+                key: "key_firebug_toggleFirebug",
+                command: "cmd_firebug_toggleFirebug",
+                "class": "fbInternational"
+            })
+        ]);
+        
+        // SeaMonkey view menu
+        $menupopupOverlay(doc, $(doc, "menu_View_Popup"), [
+            $menuitem(doc, {
+                id: "menu_firebug_viewToggleFirebug",
+                insertafter: "menuitem_fullScreen",
+                label: "firebug.Firebug",
+                type: "checkbox",
+                key: "key_firebug_toggleFirebug",
+                command: "cmd_firebug_toggleFirebug",
+                "class": "menuitem-iconic fbInternational"
+            })
+        ]);
+
+        // Firefox Tools -> Web Developer Menu
+        $menupopupOverlay(doc, $(doc, "menuWebDeveloperPopup"), [
+            $menu(doc, {
+                id: "menu_webDeveloper_firebug",
+                position: 1,
+                label: "firebug.Firebug",
+                "class": "menu-iconic fbInternational"
+            }, [
+                $menupopup(doc, {
+                    id: "menu_firebug_firebugMenuPopup",
+                    "class": "fbFirebugMenuPopup",
+                    onpopupshowing: "return Firebug.browserOverlay.onMenuShowing(this, event);",
+                    onpopuphiding: "return Firebug.browserOverlay.onMenuHiding(this, event);"
+                })
+            ]),
+            $menuseparator(doc, {
+                insertafter: "menu_webDeveloper_firebug"
+            })
+        ]);
+
+        // Firefox Button -> Web Developer Menu
+        $menupopupOverlay(doc, $(doc, "appmenu_webDeveloper_popup"), [
+            $splitmenu(doc, {
+                id: "appmenu_firebug",
+                position: 1,
+                command: "cmd_firebug_toggleFirebug",
+                key: "key_firebug_toggleFirebug",
+                label: "firebug.Firebug",
+                iconic: "true",
+                "class": "fbInternational"
+            }, [
+                $menupopup(doc, {
+                    id: "appmenu_firebugMenuPopup",
+                    "class": "fbFirebugMenuPopup",
+                    onpopupshowing: "return Firebug.browserOverlay.onMenuShowing(this, event);",
+                    onpopuphiding: "return Firebug.browserOverlay.onMenuHiding(this, event);"
+                })
+            ]),
+            $menuseparator(doc, {
+                insertafter: "appmenu_firebug"
+            })
+        ]);
+
+        // Sea Monkey Tools Menu
+        $menupopupOverlay(doc, $(doc, "toolsPopup"), [
+            $menu(doc, {
+                id: "menu_firebug",
+                insertbefore: "appmenu_webConsole",
+                command: "cmd_firebug_toggleFirebug",
+                key: "key_firebug_toggleFirebug",
+                label: "firebug.Firebug",
+                "class": "menuitem-iconic fbInternational"
+            }, [
+                $menupopup(doc, {
+                    id: "toolsmenu_firebugMenuPopup",
+                    "class": "fbFirebugMenuPopup",
+                    onpopupshowing: "return Firebug.browserOverlay.onMenuShowing(this, event);",
+                    onpopupshowing: "return Firebug.browserOverlay.onMenuHiding(this, event);"
+                })
+            ])
+        ]);
+    }
+}
+
+// ********************************************************************************************* //
+// Registration
+
+return BrowserMenu;
+
+// ********************************************************************************************* //
+}});
diff --git a/trace/FBTrace/chrome/firebug/content/firefox/browserOverlay.css b/trace/FBTrace/chrome/firebug/content/firefox/browserOverlay.css
index ef4552c..630971c 100644
--- a/trace/FBTrace/chrome/firebug/content/firefox/browserOverlay.css
+++ b/trace/FBTrace/chrome/firebug/content/firefox/browserOverlay.css
@@ -44,8 +44,8 @@
     border-radius: 3px;
     background-color: rgba(255, 0, 0, 0.9);
     box-shadow: inset 0px 0px 1px white;
-    background-image: -moz-linear-gradient(
-        center bottom,
+    background-image: linear-gradient(
+        to top,
         #DBE1EB 0%,
         #DEE4EB 80%,
         #E7EBF3 81%
@@ -125,7 +125,7 @@
 }
 
 #fbContentSplitter[dir=reverse]{
-    -moz-transform: scale(-1, -1);
+    transform: scale(-1, -1);
 }
 
 #fbContentSplitter[orient=vertical] {
diff --git a/trace/FBTrace/chrome/firebug/content/firefox/browserOverlay.js b/trace/FBTrace/chrome/firebug/content/firefox/browserOverlay.js
index 5cebf44..82da56a 100644
--- a/trace/FBTrace/chrome/firebug/content/firefox/browserOverlay.js
+++ b/trace/FBTrace/chrome/firebug/content/firefox/browserOverlay.js
@@ -1,296 +1,111 @@
 /* See license.txt for terms of usage */
 
-(function() {
+define([
+    "firebug/lib/trace",
+    "firebug/lib/options",
+    "firebug/lib/locale",
+    "firebug/lib/array",
+    "firebug/firefox/browserOverlayLib",
+    "firebug/firefox/browserCommands",
+    "firebug/firefox/browserMenu",
+    "firebug/firefox/browserToolbar",
+],
+function(FBTrace, Options, Locale, Arr, BrowserOverlayLib, BrowserCommands, BrowserMenu,
+    BrowserToolbar) {
+
+with (BrowserOverlayLib) {
 
 // ********************************************************************************************* //
 // Constants
 
-var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
+var Cc = Components.classes;
+var Ci = Components.interfaces;
+var Cu = Components.utils;
 
-Cu.import("resource://firebug/fbtrace.js");
-Cu.import("resource://firebug/loader.js");
+Locale.registerStringBundle("chrome://firebug/locale/firebug.properties");
+Locale.registerStringBundle("chrome://firebug/locale/cookies.properties");
 
-// Make sure PrefLoader variable doesn't leak into the global scope.
-var prefLoaderScope = {};
-Cu.import("resource://firebug/prefLoader.js", prefLoaderScope);
-var PrefLoader = prefLoaderScope.PrefLoader;
+Cu.import("resource://firebug/loader.js");
+Cu.import("resource://firebug/fbtrace.js");
 
 const firstRunPage = "https://getfirebug.com/firstrun#Firebug ";
 
-var Locale = Cu.import("resource://firebug/locale.js").Locale;
-
 // ********************************************************************************************* //
-// String Bundles
+// BrowserOverlay Implementation
 
-// Register bundle yet before any Locale.$STR* API is used.
-Locale.registerStringBundle("chrome://firebug/locale/firebug.properties");
-
-// xxxHonza: this needs to be done befor firebug/cookies modules are loaded
-// and it should be part of the cookies directory.
-Locale.registerStringBundle("chrome://firebug/locale/cookies.properties");
-
-// ********************************************************************************************* //
-// Overlay Helpers
-
-function $(id)
+function BrowserOverlay(win)
 {
-    return document.getElementById(id);
+    this.win = win;
+    this.doc = win.document;
 }
 
-function $$(selector)
+BrowserOverlay.prototype =
 {
-    return document.querySelectorAll(selector);
-}
+    // When Firebug is disabled or unistalled this elements must be removed from
+    // chrome UI (XUL).
+    nodesToRemove: [],
 
-function $el(name, attributes, children, parent)
-{
-    attributes = attributes || {};
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+    // Initialization
 
-    if (!Array.isArray(children) && !parent)
+    initialize: function(reason)
     {
-        parent = children;
-        children = null;
-    }
-
-    // localize
-    if (attributes.label)
-        attributes.label = Locale.$STR(attributes.label);
+        // Expose BrowserOverlayLib object to extensions.
+        this.win.Firebug.BrowserOverlayLib = BrowserOverlayLib;
 
-    if (attributes.tooltiptext)
-        attributes.tooltiptext = Locale.$STR(attributes.tooltiptext);
+        // This element (a broadcaster) is storing Firebug state information. Other elements
+        // (like for example the Firebug start button) can watch it and display the info to
+        // the user.
+        $el(this.doc, "broadcaster", {id: "firebugStatus", suspended: true},
+            $(this.doc, "mainBroadcasterSet"));
 
-    // persist
-    if (attributes.persist)
-        updatePersistedValues(attributes);
+        var node = $stylesheet(this.doc, "chrome://firebug/content/firefox/browserOverlay.css");
+        this.nodesToRemove.push(node);
 
-    var el = document.createElement(name);
-    for (var a in attributes)
-        el.setAttribute(a, attributes[a]);
-
-    for each (var a in children)
-        el.appendChild(a);
-
-    if (parent)
-    {
-        if (attributes.position)
-            parent.insertBefore(el, parent.children[attributes.position - 1]);
-        else
-            parent.appendChild(el);
+        this.loadContextMenuOverlay();
+        this.loadFirstRunPage(reason);
 
-        // Mark to remove when Firebug is uninstalled.
-        el.setAttribute("firebugRootNode", true);
-    }
+        var version = this.getVersion();
 
-    return el;
-}
+        BrowserCommands.overlay(this.doc);
+        BrowserMenu.overlay(this.doc);
+        BrowserToolbar.overlay(this.doc, version);
 
-function $command(id, oncommand, arg)
-{
-    // Wrap the command within a startFirebug call. If Firebug isn't yet loaded
-    // this will force it to load.
-    oncommand = "Firebug.GlobalUI.startFirebug(function(){" + oncommand + "})";
-    if (arg)
-        oncommand = "void function(arg){" + oncommand + "}(" + arg + ")";
-
-    return $el("command", {
-        id: id,
-        oncommand: oncommand
-    }, $("mainCommandSet"))
-}
+        this.internationalize();
+        this.allPagesActivation();
+    },
 
-function $key(id, key, modifiers, command, position)
-{
-    var attributes = 
+    internationalize: function()
     {
-        id: id,
-        modifiers: modifiers,
-        command: command,
-        position: position
-    };
-
-    attributes[KeyEvent["DOM_"+key] ? "keycode" : "key"] = key;
-
-    return $el("key", attributes, $("mainKeyset"));
-}
-
-function $menupopup(attributes, children, parent)
-{
-    return $el("menupopup", attributes, children, parent);
-}
-
-function $menu(attrs, children)
-{
-    return $el("menu", attrs, children);
-}
-
-function $menuseparator(attrs)
-{
-    return $el("menuseparator", attrs);
-}
-
-function $menuitem(attrs)
-{
-    return $el("menuitem", attrs);
-}
-
-function $splitmenu(attrs, children)
-{
-    return $el("splitmenu", attrs, children);
-}
-
-function $menupopupOverlay(parent, children)
-{
-    if (!parent)
-        return;
+        // Internationalize all elements with 'fbInternational' class. Clone
+        // before internationalizing.
+        var elements = Arr.cloneArray(this.doc.getElementsByClassName("fbInternational"));
+        Locale.internationalizeElements(this.doc, elements, ["label", "tooltiptext", "aria-label"]);
+    },
 
-    for (var i=0; i<children.length; ++i)
+    allPagesActivation: function()
     {
-        var child = children[i];
-        var beforeEl;
-
-        if (child.getAttribute("position"))
-        {
-            var pos = child.getAttribute("position");
-            beforeEl = parent.children[pos - 1];
-        }
-        else if (child.getAttribute("insertbefore"))
-        {
-            var ids = child.getAttribute("insertbefore").split(",");
-            for (var j=0; j < ids.length; ++j)
-            {
-                beforeEl = parent.querySelector("#" + ids[j]);
-                if (beforeEl)
-                    break;
-            }
-        }
-        else if (child.getAttribute("insertafter"))
+        // Load Firebug by default if activation is on for all pages (see issue 5522)
+        if (Options.get("allPagesActivation") == "on" || !Options.get("delayLoad"))
         {
-            var ids = child.getAttribute("insertafter").split(",");
-            for (var j=0; j < ids.length; ++j)
+            var self = this;
+            this.startFirebug(function(Firebug)
             {
-                beforeEl = parent.querySelector("#" + ids[j]);
-                if (beforeEl)
-                    break;
-            }
-            if (beforeEl)
-                beforeEl = beforeEl.nextSibling;
-        }
-
-        if (beforeEl)
-            parent.insertBefore(child, beforeEl);
-        else
-            parent.appendChild(child);
+                var browser = Firebug.Firefox.getBrowserForWindow(self.win);
+                var uri = Firebug.Firefox.getCurrentURI();
 
-        // Mark the inserted node to remove it when Firebug is uninstalled.
-        child.setAttribute("firebugRootNode", true);
-    }
-}
-
-function $toolbarButton(id, attrs, children, defaultPos)
-{
-    attrs["class"] = "toolbarbutton-1";
-    attrs.firebugRootNode = true;
-    attrs.id = id;
+                // Open Firebug UI (e.g. if the annotations say so, issue 5623)
+                if (uri && Firebug.TabWatcher.shouldCreateContext(browser, uri.spec, null))
+                    Firebug.toggleBar(true);
 
-    // in seamonkey gNavToolbox is null onload
-    var button = $el("toolbarbutton", attrs, children, (gNavToolbox || $("navigator-toolbox")).palette);
-
-    var selector = "[currentset^='" + id + ",'],[currentset*='," + id + ",'],[currentset$='," + id + "']";
-    var toolbar = document.querySelector(selector);
-    if (!toolbar)
-        return; // todo defaultPos
-
-    var currentset = toolbar.getAttribute("currentset").split(",");
-    var i = currentset.indexOf(id) + 1;
-
-    var len = currentset.length, beforeEl;
-    while (i < len && !(beforeEl = $(currentset[i])))
-        i++;
-
-    return toolbar.insertItem(id, beforeEl);
-}
-
-function $tooltip(attrs, children)
-{
-    return $el("tooltip", attrs, children);
-}
-
-function $label(attrs)
-{
-    return $el("label", attrs);
-}
-
-// ********************************************************************************************* //
-// Other Helpers
-
-function updatePersistedValues(options)
-{
-    var persist = options.persist.split(",");
-    var id = options.id;
-    var RDF = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
-    var store = PlacesUIUtils.localStore; //this.RDF.GetDataSource("rdf:local-store");
-    var root = RDF.GetResource("chrome://browser/content/browser.xul#" + id);
-
-    var getPersist = function getPersist(aProperty)
-    {
-        var property = RDF.GetResource(aProperty);
-        var target = store.GetTarget(root, property, true);
-
-        if (target instanceof Ci.nsIRDFLiteral)
-            return target.Value;
-    }
-
-    for each(var attr in persist)
-    {
-        var val = getPersist(attr);
-        if (val)
-            options[attr] = val;
-    }
-}
-
-function cloneArray(arr)
-{
-    var newArr = [];
-    for (var i=0; i<arr.length; i++)
-        newArr.push(arr[i]);
-    return newArr;
-}
-
-// ********************************************************************************************* //
-
-Firebug.GlobalUI =
-{
-    nodesToRemove: [],
-
-    $: $,
-    $$: $$,
-    $el: $el,
-    $menupopupOverlay: $menupopupOverlay,
-    $menuitem: $menuitem,
-    $menuseparator: $menuseparator,
-    $command: $command,
-    $key: $key,
-    $splitmenu: $splitmenu,
-    $tooltip: $tooltip,
-    $label: $label,
-
-    $stylesheet: function(href)
-    {
-        var s = document.createProcessingInstruction("xml-stylesheet", 'href="' + href + '"');
-        document.insertBefore(s, document.documentElement);
-        this.nodesToRemove.push(s);
-    },
-
-    $script: function(src)
-    {
-        var script = document.createElementNS("http://www.w3.org/1999/xhtml", "html:script");
-        script.src = src;
-        script.type = "text/javascript";
-        script.setAttribute("firebugRootNode", true);
-        document.documentElement.appendChild(script);
+                FBTrace.sysout("Firebug loaded by default since 'allPagesActivation' is on " +
+                    "or 'delayLoad' is false");
+            });
+        }
     },
 
     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+    // Load Rest of Firebug
 
     /**
      * This method is called by the Fremework to load entire Firebug. It's executed when
@@ -300,35 +115,39 @@ Firebug.GlobalUI =
      */
     startFirebug: function(callback)
     {
-        if (Firebug.waitingForFirstLoad)
+        if (this.win.Firebug.waitingForFirstLoad)
             return;
 
-        if (Firebug.isInitialized)
-            return callback && callback(Firebug);
+        if (this.win.Firebug.isInitialized)
+            return callback && callback(this.win.Firebug);
 
         if (FBTrace.DBG_INITIALIZE)
             FBTrace.sysout("overlay; Load Firebug...", (callback ? callback.toString() : ""));
 
-        Firebug.waitingForFirstLoad = true;
+        this.win.Firebug.waitingForFirstLoad = true;
 
-        var container = $("appcontent");
+        var container = $(this.doc, "appcontent");
 
         // List of Firebug scripts that must be loaded into the global scope (browser.xul)
+        // FBTrace is no longer loaded into the global space.
         var scriptSources = [
-            "chrome://firebug/content/trace.js",
             "chrome://firebug/content/legacy.js",
             "chrome://firebug/content/moduleConfig.js"
         ]
 
         // Create script elements.
-        scriptSources.forEach(this.$script);
+        var self = this;
+        scriptSources.forEach(function(url)
+        {
+            $script(self.doc, url);
+        });
 
         // Create Firebug splitter element.
-        $el("splitter", {id: "fbContentSplitter", collapsed: "true"}, container);
+        $el(this.doc, "splitter", {id: "fbContentSplitter", collapsed: "true"}, container);
 
         // Create Firebug main frame and container.
-        $el("vbox", {id: "fbMainFrame", collapsed: "true", persist: "height,width"}, [
-            $el("browser", {
+        $el(this.doc, "vbox", {id: "fbMainFrame", collapsed: "true", persist: "height,width"}, [
+            $el(this.doc, "browser", {
                 id: "fbMainContainer",
                 flex: "2",
                 src: "chrome://firebug/content/firefox/firebugFrame.xul",
@@ -338,17 +157,20 @@ Firebug.GlobalUI =
 
         // When Firebug is fully loaded and initialized it fires a "FirebugLoaded"
         // event to the browser document (browser.xul scope). Wait for that to happen.
-        document.addEventListener("FirebugLoaded", function onLoad()
+        this.doc.addEventListener("FirebugLoaded", function onLoad()
         {
-            document.removeEventListener("FirebugLoaded", onLoad, false);
-            Firebug.waitingForFirstLoad = false;
+            self.doc.removeEventListener("FirebugLoaded", onLoad, false);
+            self.win.Firebug.waitingForFirstLoad = false;
 
             // xxxHonza: TODO find a better place for notifying extensions
-            FirebugLoader.dispatchToScopes("firebugFrameLoad", [Firebug]);
-            callback && callback(Firebug);
+            FirebugLoader.dispatchToScopes("firebugFrameLoad", [self.win.Firebug]);
+            callback && callback(self.win.Firebug);
         }, false);
     },
 
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+    // Firebug Menu Handlers
+
     onOptionsShowing: function(popup)
     {
         for (var child = popup.firstChild; child; child = child.nextSibling)
@@ -358,7 +180,7 @@ Firebug.GlobalUI =
                 var option = child.getAttribute("option");
                 if (option)
                 {
-                    var checked = PrefLoader.getPref(option);
+                    var checked = Options.get(option);
 
                     // xxxHonza: I belive that allPagesActivation could be simple boolean option.
                     if (option == "allPagesActivation")
@@ -375,31 +197,31 @@ Firebug.GlobalUI =
         var option = menuItem.getAttribute("option");
         var checked = menuItem.getAttribute("checked") == "true";
 
-        PrefLoader.setPref(option, checked);
+        Options.set(option, checked);
     },
 
-    onMenuShowing: function(popup)
+    onMenuShowing: function(popup, event)
     {
-        // If this popup is already open the event comes from a sub menu, just ignore it.
-        if (popup.state == "open")
+        // If the event comes from a sub menu, just ignore it.
+        if (popup != event.target)
             return;
 
         while (popup.lastChild)
             popup.removeChild(popup.lastChild);
 
         // Generate dynamic content.
-        for (var i=0; i<firebugMenuContent.length; i++)
-            popup.appendChild(firebugMenuContent[i].cloneNode(true));
+        for (var i=0; i<BrowserMenu.firebugMenuContent.length; i++)
+            popup.appendChild(BrowserMenu.firebugMenuContent[i].cloneNode(true));
 
         var collapsed = "true";
-        if (Firebug.chrome)
+        if (this.win.Firebug.chrome)
         {
-            var fbContentBox = Firebug.chrome.$("fbContentBox");
+            var fbContentBox = this.win.Firebug.chrome.$("fbContentBox");
             collapsed = fbContentBox.getAttribute("collapsed");
         }
 
-        var currPos = PrefLoader.getPref("framePosition");
-        var placement = Firebug.getPlacement ? Firebug.getPlacement() : "";
+        var currPos = Options.get("framePosition");
+        var placement = this.win.Firebug.getPlacement ? this.win.Firebug.getPlacement() : "";
 
         // Switch between "Open Firebug" and "Hide Firebug" label in the popup menu.
         var toggleFirebug = popup.querySelector("#menu_firebug_toggleFirebug");
@@ -422,7 +244,7 @@ Firebug.GlobalUI =
             // to ensure Firebug isn't closed with close button of detached window
             // and 'inDetachedWindow' variable is also used to ensure the menu is
             // opened from within the detached window.
-            if (currPos == "detached" && Firebug.currentContext &&
+            if (currPos == "detached" && this.win.Firebug.currentContext &&
                 placement != "minimized" && !inDetachedWindow)
             {
                 toggleFirebug.setAttribute("label", Locale.$STR("firebug.FocusFirebug"));
@@ -435,11 +257,12 @@ Firebug.GlobalUI =
         var closeFirebug = popup.querySelector("#menu_firebug_closeFirebug");
         if (closeFirebug)
         {
-            closeFirebug.setAttribute("collapsed", (Firebug.currentContext ? "false" : "true"));
+            closeFirebug.setAttribute("collapsed",
+                (this.win.Firebug.currentContext ? "false" : "true"));
         }
 
         // Update About Menu
-        var version = Firebug.GlobalUI.getVersion();
+        var version = this.getVersion();
         if (version)
         {
             var node = popup.getElementsByClassName("firebugAbout")[0];
@@ -449,18 +272,18 @@ Firebug.GlobalUI =
         }
 
         // Allow Firebug menu customization (see FBTest and FBTrace as an example).
-        var event = new CustomEvent("firebugMenuShowing", {detail: popup});
-        document.dispatchEvent(event);
+        var event = new this.win.CustomEvent("firebugMenuShowing", {detail: popup});
+        this.doc.dispatchEvent(event);
     },
 
-    onMenuHiding: function(popup)
+    onMenuHiding: function(popup, event)
     {
-        if (popup.state == "open")
+        if (popup != event.target)
             return;
 
         // xxxHonza: I don't know why the timeout must be here, but if it isn't
         // the icon menu is broken (see issue 5427)
-        setTimeout(function()
+        this.win.setTimeout(function()
         {
             while (popup.lastChild)
                 popup.removeChild(popup.lastChild);
@@ -473,15 +296,15 @@ Firebug.GlobalUI =
             popup.removeChild(popup.lastChild);
 
         // Load Firebug before the position is changed.
-        var oncommand = "Firebug.GlobalUI.startFirebug(function(){" +
+        var oncommand = "Firebug.browserOverlay.startFirebug(function(){" +
             "Firebug.chrome.setPosition('%pos%')" + "})";
 
         var items = [];
-        var currPos = PrefLoader.getPref("framePosition");
+        var currPos = Options.get("framePosition");
         for each (var pos in ["detached", "top", "bottom", "left", "right"])
         {
             var label = pos.charAt(0).toUpperCase() + pos.slice(1);
-            var item = $menuitem({
+            var item = $menuitem(this.doc, {
                 label: Locale.$STR("firebug.menu." + label),
                 tooltiptext: Locale.$STR("firebug.menu.tip." + label),
                 type: "radio",
@@ -500,27 +323,25 @@ Firebug.GlobalUI =
 
     openAboutDialog: function()
     {
+        var self = this;
+
         // Firefox 4.0+
-        Components.utils["import"]("resource://gre/modules/AddonManager.jsm");
-        AddonManager.getAddonByID("firebug at software.joehewitt.com", function(addon)
+        Cu["import"]("resource://gre/modules/AddonManager.jsm");
+        this.win.AddonManager.getAddonByID("firebug at software.joehewitt.com", function(addon)
         {
-            openDialog("chrome://mozapps/content/extensions/about.xul", "",
+            self.win.openDialog("chrome://mozapps/content/extensions/about.xul", "",
                 "chrome,centerscreen,modal", addon);
         });
     },
 
-    openFirstRunPage: function()
-    {
-        var version = Firebug.GlobalUI.getVersion();
-        url = firstRunPage + version;
-        gBrowser.selectedTab = gBrowser.addTab(url, null, null, null);
-    },
-
     setPosition: function(newPosition)
     {
         // todo
     },
 
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+    // Firebug Version
+
     getVersion: function()
     {
         var versionURL = "chrome://firebug/content/branch.properties";
@@ -555,772 +376,151 @@ Firebug.GlobalUI =
 
     onEditorsShowing: function(popup)
     {
-        Firebug.GlobalUI.startFirebug(function()
+        var self = this;
+        this.startFirebug(function()
         {
-            Firebug.ExternalEditors.onEditorsShowing(popup);
+            self.win.Firebug.ExternalEditors.onEditorsShowing(popup);
         });
 
         return true;
-    }
-}
-
-// ********************************************************************************************* //
-// Global Firebug CSS
-
-Firebug.GlobalUI.$stylesheet("chrome://firebug/content/firefox/browserOverlay.css");
-
-// ********************************************************************************************* //
-// Broadcasters
-
-/**
- * This element (a broadcaster) is storing Firebug state information. Other elements
- * (like for example the Firebug start button) can watch it and display the info to
- * the user.
- */
-$el("broadcaster", {id: "firebugStatus", suspended: true}, $("mainBroadcasterSet"));
-
-// ********************************************************************************************* //
-// Global Commands
-
-$command("cmd_firebug_closeFirebug", "Firebug.closeFirebug(true);");
-$command("cmd_firebug_toggleInspecting", "if (!Firebug.currentContext) Firebug.toggleBar(true); Firebug.Inspector.toggleInspecting(Firebug.currentContext);");
-$command("cmd_firebug_focusCommandLine", "if (!Firebug.currentContext) Firebug.toggleBar(true); Firebug.CommandLine.focus(Firebug.currentContext);");
-$command("cmd_firebug_toggleFirebug", "Firebug.toggleBar();");
-$command("cmd_firebug_detachFirebug", "Firebug.toggleDetachBar(false, true);");
-$command("cmd_firebug_inspect", "Firebug.Inspector.inspectFromContextMenu(arg);", "document.popupNode");
-$command("cmd_firebug_toggleBreakOn", "if (Firebug.currentContext) Firebug.chrome.breakOnNext(Firebug.currentContext, event);");
-$command("cmd_firebug_toggleDetachFirebug", "Firebug.toggleDetachBar(false, true);");
-$command("cmd_firebug_increaseTextSize", "Firebug.Options.changeTextSize(1);");
-$command("cmd_firebug_decreaseTextSize", "Firebug.Options.changeTextSize(-1);");
-$command("cmd_firebug_normalTextSize", "Firebug.Options.setTextSize(0);");
-$command("cmd_firebug_focusFirebugSearch", "if (Firebug.currentContext) Firebug.Search.onSearchCommand(document);");
-$command("cmd_firebug_customizeFBKeys", "Firebug.ShortcutsModel.customizeShortcuts();");
-$command("cmd_firebug_enablePanels", "Firebug.PanelActivation.enableAllPanels();");
-$command("cmd_firebug_disablePanels", "Firebug.PanelActivation.disableAllPanels();");
-$command("cmd_firebug_clearActivationList", "Firebug.PanelActivation.clearAnnotations();");
-$command("cmd_firebug_clearConsole", "Firebug.Console.clear(Firebug.currentContext);");
-$command("cmd_firebug_allOn", "Firebug.PanelActivation.toggleAll('on');");
-$command("cmd_firebug_toggleOrient", "Firebug.chrome.toggleOrient();");
-$command("cmd_firebug_resetAllOptions", "Firebug.resetAllOptions(true);");
-$command("cmd_firebug_toggleProfiling", ""); //todo
-
-$command("cmd_firebug_openInEditor", "Firebug.ExternalEditors.onContextMenuCommand(event)");
-
-// ********************************************************************************************* //
-// Global Shortcuts
+    },
 
-(function(globalShortcuts)
-{
-    var keyset = $("mainKeyset");
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+    // Page Context Menu Overlay
 
-    globalShortcuts.forEach(function(id)
+    loadContextMenuOverlay: function()
     {
-        var shortcut = PrefLoader.getPref("key.shortcut." + id);
-        var tokens = shortcut.split(" ");
-        var key = tokens.pop();
-
-        var keyProps = {
-            id: "key_firebug_" + id,
-            modifiers: tokens.join(","),
-            command: "cmd_firebug_" + id,
-            position: 1
-        };
-
-        if (key.length <= 1)
-            keyProps.key = key;
-        else if (KeyEvent["DOM_"+key])
-            keyProps.keycode = key;
-
-        $el("key", keyProps, keyset);
-    });
-
-    keyset.parentNode.insertBefore(keyset, keyset.nextSibling);
-})(["toggleFirebug", "toggleInspecting", "focusCommandLine",
-    "detachFirebug", "closeFirebug", "toggleBreakOn"]);
-
-
-/* Used by the global menu, but should be really global shortcuts?
-key_increaseTextSize
-key_decreaseTextSize
-key_normalTextSize
-key_help
-key_toggleProfiling
-key_focusFirebugSearch
-key_customizeFBKeys
-*/
-
-// ********************************************************************************************* //
-// Firebug Start Button Popup Menu
+        var contextMenu = this.win.nsContextMenu;
+        if (typeof(contextMenu) == "undefined")
+            return;
 
-$menupopupOverlay($("mainPopupSet"), [
-    $menupopup(
-    {
-        id: "fbStatusContextMenu",
-        onpopupshowing: "Firebug.GlobalUI.onOptionsShowing(this)"
-    },
-    [
-        $menu(
+        // isTargetAFormControl is removed, see:
+        // https://bugzilla.mozilla.org/show_bug.cgi?id=433168
+        if (typeof(contextMenu.prototype.isTargetAFormControl) != "undefined")
         {
-            label: "firebug.uiLocation",
-            tooltiptext: "firebug.menu.tip.UI_Location",
-            "class": "fbInternational"
-        },
-        [
-            $menupopup({onpopupshowing: "Firebug.GlobalUI.onPositionPopupShowing(this)"})
-        ]),
-        $menuseparator(),
-        $menuitem({
-            id: "menu_firebug_ClearConsole",
-            label: "firebug.ClearConsole",
-            tooltiptext: "firebug.ClearTooltip",
-            command: "cmd_firebug_clearConsole",
-            key: "key_firebug_clearConsole"
-        }),
-        $menuitem({
-            id: "menu_firebug_showErrorCount",
-            type: "checkbox",
-            label: "firebug.Show_Error_Count",
-            tooltiptext: "firebug.menu.tip.Show_Error_Count",
-            oncommand: "Firebug.GlobalUI.onToggleOption(this)",
-            option: "showErrorCount"
-        }),
-        $menuseparator(),
-        $menuitem({
-            id: "menu_firebug_enablePanels",
-            label: "firebug.menu.Enable_All_Panels",
-            tooltiptext: "firebug.menu.tip.Enable_All_Panels",
-            command: "cmd_firebug_enablePanels"
-        }),
-        $menuitem({
-            id: "menu_firebug_disablePanels",
-            label: "firebug.menu.Disable_All_Panels",
-            tooltiptext: "firebug.menu.tip.Disable_All_Panels",
-            command: "cmd_firebug_disablePanels"
-        }),
-        $menuseparator(),
-        $menuitem({
-            id: "menu_firebug_AllOn",
-            type: "checkbox",
-            label: "On_for_all_web_pages",
-            tooltiptext: "firebug.menu.tip.On_for_all_Web_Sites",
-            command: "cmd_firebug_allOn",
-            option: "allPagesActivation"
-        }),
-        $menuitem({
-            id: "menu_firebug_clearActivationList",
-            label: "firebug.menu.Clear_Activation_List",
-            tooltiptext: "firebug.menu.tip.Clear_Activation_List",
-            command: "cmd_firebug_clearActivationList"
-        })
-    ])
-])
-
-// ********************************************************************************************* //
-// Firebug Global Menu
-
-/**
- * There are more instances of Firebug Menu (e.g. one in Firefox -> Tools -> Web Developer
- * and one in Firefox 4 (top-left orange button menu) -> Web Developer
- *
- * If extensions want to override the menu thay need to iterate all existing instance
- * using document.querySelectorAll(".fbFirebugMenuPopup") and append new menu items to all
- * of them. Iteration must be done in the global space (browser.xul)
- *
- * The same menu is also used for Firebug Icon Menu (Firebug's toolbar). This menu is cloned
- * and initialized as soon as Firebug UI is actually loaded. Since it's cloned from the original
- * (global scope) extensions don't have to extend it (possible new menu items are already there).
- */
-var firebugMenuContent = [
-
-    // Open/close Firebug
-    $menuitem(
-    {
-        id: "menu_firebug_toggleFirebug",
-        label: "firebug.ShowFirebug",
-        tooltiptext: "firebug.menu.tip.Open_Firebug",
-        command: "cmd_firebug_toggleFirebug",
-        key: "key_firebug_toggleFirebug",
-        "class": "fbInternational"
-    }),
-    $menuitem(
-    {
-        id: "menu_firebug_closeFirebug",
-        label: "firebug.Deactivate_Firebug",
-        tooltiptext: "firebug.tip.Deactivate_Firebug",
-        command: "cmd_firebug_closeFirebug",
-        key: "key_firebug_closeFirebug",
-        "class": "fbInternational"
-    }),
-
-    // Firebug UI position
-    $menu(
-    {
-        label: "firebug.uiLocation",
-        tooltiptext: "firebug.menu.tip.UI_Location",
-        "class": "fbInternational"
-    },
-    [
-        $menupopup({onpopupshowing: "Firebug.GlobalUI.onPositionPopupShowing(this)"})
-    ]),
-
-    $menuseparator(),
+            // https://bugzilla.mozilla.org/show_bug.cgi?id=433168
+            var setTargetOriginal = this.setTargetOriginal = contextMenu.prototype.setTarget;
+            contextMenu.prototype.setTarget = function(aNode, aRangeParent, aRangeOffset)
+            {
+                setTargetOriginal.apply(this, arguments);
 
-    // External Editors
-    $menu(
-    {
-        id: "FirebugMenu_OpenWith",
-        label:"firebug.OpenWith",
-        tooltiptext:"firebug.menu.tip.Open_With",
-        "class": "fbInternational",
-        insertafter: "menu_firebug_openActionsSeparator",
-        openFromContext: "true",
-        command: "cmd_firebug_openInEditor"
-    },
-    [
-        $menupopup({id:"fbFirebugMenu_OpenWith",
-            onpopupshowing: "return Firebug.GlobalUI.onEditorsShowing(this);"})
-    ]),
+                if (this.isTargetAFormControl(aNode))
+                    this.shouldDisplay = true;
+            };
+        }
 
-    // Text Size
-    $menu(
-    {
-        id: "FirebugMenu_TextSize",
-        label: "firebug.TextSize",
-        tooltiptext: "firebug.menu.tip.Text_Size",
-        "class": "fbInternational"
-    },
-    [
-        $menupopup({},
-        [
-            $menuitem(
-            {
-                id: "menu_firebug_increaseTextSize",
-                label: "firebug.IncreaseTextSize",
-                tooltiptext: "firebug.menu.tip.Increase_Text_Size",
-                command: "cmd_firebug_increaseTextSize",
-                key: "key_firebug_increaseTextSize",
-                "class": "fbInternational"
-            }),
-            $menuitem(
-            {
-                id: "menu_firebug_decreaseTextSize",
-                label: "firebug.DecreaseTextSize",
-                tooltiptext: "firebug.menu.tip.Decrease_Text_Size",
-                command: "cmd_firebug_decreaseTextSize",
-                key: "key_firebug_decreaseTextSize",
-                "class": "fbInternational"
-            }),
-            $menuitem(
-            {
-                id: "menu_firebug_normalTextSize",
-                label: "firebug.NormalTextSize",
-                tooltiptext: "firebug.menu.tip.Normal_Text_Size",
-                command: "cmd_firebug_normalTextSize",
-                key: "key_firebug_normalTextSize",
-                "class": "fbInternational"
-            }),
-        ])
-    ]),
-
-    // Options
-    $menu(
-    {
-        id: "FirebugMenu_Options",
-        label: "firebug.Options",
-        tooltiptext: "firebug.menu.tip.Options",
-        "class": "fbInternational"
-    },
-    [
-        $menupopup(
+        // Hide built-in inspector if the pref says so.
+        var initItemsOriginal = this.initItemsOriginal = contextMenu.prototype.initItems;
+        contextMenu.prototype.initItems = function()
         {
-            id: "FirebugMenu_OptionsPopup",
-            onpopupshowing: "return Firebug.GlobalUI.onOptionsShowing(this);"
-        },
-        [
-            $menuitem(
-            {
-                id: "menu_firebug_toggleShowErrorCount",
-                type: "checkbox",
-                label: "firebug.Show_Error_Count",
-                tooltiptext: "firebug.menu.tip.Show_Error_Count",
-                oncommand: "Firebug.GlobalUI.onToggleOption(this)",
-                option: "showErrorCount",
-                "class": "fbInternational"
-            }),
-            $menuitem(
-            {
-                id: "menu_firebug_showTooltips",
-                type: "checkbox",
-                label: "firebug.menu.Show_Info_Tips",
-                tooltiptext: "firebug.menu.tip.Show_Info_Tips",
-                oncommand: "Firebug.GlobalUI.onToggleOption(this)",
-                option: "showInfoTips",
-                "class": "fbInternational"
-            }),
-            $menuitem(
-            {
-                id: "menu_firebug_shadeBoxModel",
-                type: "checkbox",
-                label: "ShadeBoxModel",
-                tooltiptext: "inspect.option.tip.Shade_Box_Model",
-                oncommand: "Firebug.GlobalUI.onToggleOption(this)",
-                option: "shadeBoxModel",
-                "class": "fbInternational"
-            }),
-            $menuitem(
-            {
-                id: "menu_firebug_showQuickInfoBox",
-                type: "checkbox",
-                label: "ShowQuickInfoBox",
-                tooltiptext: "inspect.option.tip.Show_Quick_Info_Box",
-                oncommand: "Firebug.GlobalUI.onToggleOption(this)",
-                option: "showQuickInfoBox",
-                "class": "fbInternational"
-            }),
-            $menuitem(
-            {
-                id: "menu_firebug_enableA11y",
-                type: "checkbox",
-                label: "firebug.menu.Enable_Accessibility_Enhancements",
-                tooltiptext: "firebug.menu.tip.Enable_Accessibility_Enhancements",
-                oncommand: "Firebug.GlobalUI.onToggleOption(this)",
-                option: "a11y.enable",
-                "class": "fbInternational"
-            }),
-            $menuitem(
-            {
-                id: "menu_firebug_activateSameOrigin",
-                type: "checkbox",
-                label: "firebug.menu.Activate_Same_Origin_URLs2",
-                tooltiptext: "firebug.menu.tip.Activate_Same_Origin_URLs",
-                oncommand: "Firebug.GlobalUI.onToggleOption(this)",
-                option: "activateSameOrigin",
-                "class": "fbInternational"
-            }),
-            $menuitem(
-            {
-                id: "menu_firebug_toggleOrient",
-                type: "checkbox",
-                label: "firebug.menu.Vertical_Panels",
-                tooltiptext: "firebug.menu.tip.Vertical_Panels",
-                command: "cmd_firebug_toggleOrient",
-                option: "viewPanelOrient",
-                "class": "fbInternational"
-            }),
-            $menuseparator({id: "menu_firebug_optionsSeparator"}),
-            $menuitem(
+            initItemsOriginal.apply(this, arguments);
+
+            // Hide built-in inspector menu item if the pref "extensions.firebug.hideDefaultInspector"
+            // says so. Note that there is also built-in preference "devtools.inspector.enable" that
+            // can be used for the same purpose.
+            var hideInspect = Options.get("hideDefaultInspector");
+            if (hideInspect)
             {
-                id: "menu_firebug_resetAllOptions",
-                label: "firebug.menu.Reset_All_Firebug_Options",
-                tooltiptext: "firebug.menu.tip.Reset_All_Firebug_Options",
-                command: "cmd_firebug_resetAllOptions",
-                "class": "fbInternational"
-            }),
-        ])
-    ]),
-
-    $menuseparator({id: "FirebugBetweenOptionsAndSites", collapsed: "true"}),
-
-    // Sites
-    $menu(
-    {
-        id: "FirebugMenu_Sites",
-        label: "firebug.menu.Firebug_Online",
-        tooltiptext: "firebug.menu.tip.Firebug_Online",
-        "class": "fbInternational"
+                this.showItem("inspect-separator", false);
+                this.showItem("context-inspect", false);
+            }
+        }
     },
-    [
-        $menupopup({},
-        [
-            $menuitem(
-            {
-                id: "menu_firebug_firebugUrlWebsite",
-                label: "firebug.Website",
-                tooltiptext: "firebug.menu.tip.Website",
-                oncommand: "Firebug.chrome.visitWebsite('main')",
-                "class": "fbInternational"
-            }),
-            $menuitem(
-            {
-                id: "menu_firebug_firebugUrlExtensions",
-                label: "firebug.menu.Extensions",
-                tooltiptext: "firebug.menu.tip.Extensions",
-                oncommand: "Firebug.chrome.visitWebsite('extensions')",
-                "class": "fbInternational"
-            }),
-            $menuitem(
-            {
-                id: "menu_firebug_firebugHelp",
-                label: "firebug.help",
-                tooltiptext: "firebug.menu.tip.help",
-                command: "cmd_firebug_openHelp",
-                key: "key_firebug_help",
-                "class": "fbInternational"
-            }),
-            $menuitem(
-            {
-                id: "menu_firebug_firebugDoc",
-                label: "firebug.Documentation",
-                tooltiptext: "firebug.menu.tip.Documentation",
-                oncommand: "Firebug.chrome.visitWebsite('docs')",
-                "class": "fbInternational"
-            }),
-            $menuitem(
-            {
-                id: "menu_firebug_firebugKeyboard",
-                label: "firebug.KeyShortcuts",
-                tooltiptext: "firebug.menu.tip.Key_Shortcuts",
-                oncommand: "Firebug.chrome.visitWebsite('keyboard')",
-                "class": "fbInternational"
-            }),
-            $menuitem(
-            {
-                id: "menu_firebug_firebugForums",
-                label: "firebug.Forums",
-                tooltiptext: "firebug.menu.tip.Forums",
-                oncommand: "Firebug.chrome.visitWebsite('discuss')",
-                "class": "fbInternational"
-            }),
-            $menuitem(
-            {
-                id: "menu_firebug_firebugIssues",
-                label: "firebug.Issues",
-                tooltiptext: "firebug.menu.tip.Issues",
-                oncommand: "Firebug.chrome.visitWebsite('issues')",
-                "class": "fbInternational"
-            }),
-            $menuitem(
-            {
-                id: "menu_firebug_firebugDonate",
-                label: "firebug.Donate",
-                tooltiptext: "firebug.menu.tip.Donate",
-                oncommand: "Firebug.chrome.visitWebsite('donate')",
-                "class": "fbInternational"
-            }),
-        ])
-    ]),
 
-    $menuseparator({id: "menu_firebug_miscActionsSeparator", collapsed: "true"}),
-
-    $menuseparator({id: "menu_firebug_toolsSeparator", collapsed: "true"}),
-
-    $menuitem(
+    unloadContextMenuOverlay: function()
     {
-        id: "menu_firebug_customizeShortcuts",
-        label: "firebug.menu.Customize_shortcuts",
-        tooltiptext: "firebug.menu.tip.Customize_Shortcuts",
-        command: "cmd_firebug_customizeFBKeys",
-        key: "key_firebug_customizeFBKeys",
-        "class": "fbInternational"
-    }),
-
-    $menuseparator({id: "menu_firebug_aboutSeparator"}),
-
-    $menuitem({
-        id: "menu_firebug_about",
-        label: "firebug.About",
-        tooltiptext: "firebug.menu.tip.About",
-        oncommand: "Firebug.GlobalUI.openAboutDialog()",
-        "class": "firebugAbout fbInternational"
-    }),
-];
-
-// ********************************************************************************************* //
-// Global Menu Overlays
-
-// Firefox page context menu
-$menupopupOverlay($("contentAreaContextMenu"), [
-    $menuseparator(),
-    $menuitem({
-        id: "menu_firebug_firebugInspect",
-        label: "firebug.InspectElementWithFirebug",
-        command: "cmd_firebug_inspect",
-        "class": "menuitem-iconic fbInternational"
-    })
-]);
-
-// Firefox view menu
-$menupopupOverlay($("menu_viewPopup"), [
-    $menuitem({
-        id: "menu_firebug_viewToggleFirebug",
-        insertbefore: "toggle_taskbar",
-        label: "firebug.Firebug",
-        type: "checkbox",
-        key: "key_firebug_toggleFirebug",
-        command: "cmd_firebug_toggleFirebug",
-        "class": "fbInternational"
-    })
-]);
-
-// SeaMonkey view menu
-$menupopupOverlay($("menu_View_Popup"), [
-    $menuitem({
-        id: "menu_firebug_viewToggleFirebug",
-        insertafter: "menuitem_fullScreen",
-        label: "firebug.Firebug",
-        type: "checkbox",
-        key: "key_firebug_toggleFirebug",
-        command: "cmd_firebug_toggleFirebug",
-        "class": "menuitem-iconic fbInternational"
-    })
-]);
-
-// Firefox Tools -> Web Developer Menu
-$menupopupOverlay($("menuWebDeveloperPopup"), [
-    $menu({
-        id: "menu_webDeveloper_firebug",
-        position: 1,
-        label: "firebug.Firebug",
-        "class": "menu-iconic fbInternational"
-    }, [
-        $menupopup({
-            id: "menu_firebug_firebugMenuPopup",
-            "class": "fbFirebugMenuPopup",
-            onpopupshowing: "return Firebug.GlobalUI.onMenuShowing(this);",
-            onpopuphiding: "return Firebug.GlobalUI.onMenuHiding(this);"
-        })
-    ]),
-    $menuseparator({
-        insertafter: "menu_webDeveloper_firebug"
-    })
-]);
-
-// Firefox Button -> Web Developer Menu
-$menupopupOverlay($("appmenu_webDeveloper_popup"), [
-    $splitmenu({
-        id: "appmenu_firebug",
-        position: 1,
-        command: "cmd_firebug_toggleFirebug",
-        key: "key_firebug_toggleFirebug",
-        label: "firebug.Firebug",
-        iconic: "true",
-        "class": "fbInternational"
-    }, [
-        $menupopup({
-            id: "appmenu_firebugMenuPopup",
-            "class": "fbFirebugMenuPopup",
-            onpopupshowing: "return Firebug.GlobalUI.onMenuShowing(this);",
-            onpopuphiding: "return Firebug.GlobalUI.onMenuHiding(this);"
-        })
-    ]),
-    $menuseparator({
-        insertafter: "appmenu_firebug"
-    })
-]);
-
-// Sea Monkey Tools Menu
-$menupopupOverlay($("toolsPopup"), [
-    $menu({
-        id: "menu_firebug",
-        insertbefore: "appmenu_webConsole",
-        command: "cmd_firebug_toggleFirebug",
-        key: "key_firebug_toggleFirebug",
-        label: "firebug.Firebug",
-        "class": "menuitem-iconic fbInternational"
-    }, [
-        $menupopup({
-            id: "toolsmenu_firebugMenuPopup",
-            "class": "fbFirebugMenuPopup",
-            onpopupshowing: "return Firebug.GlobalUI.onMenuShowing(this);",
-            onpopupshowing: "return Firebug.GlobalUI.onMenuHiding(this);"
-        })
-    ])
-]);
-
-// ********************************************************************************************* //
-// Firefox Toolbar Buttons
-
-$toolbarButton("firebug-inspectorButton", {
-    label: "firebug.Inspect",
-    tooltiptext: "firebug.InspectElement",
-    observes: "cmd_firebug_toggleInspecting",
-    style: "list-style-image: url(chrome://firebug/skin/inspect.png);" +
-        "-moz-image-region: rect(0, 16px, 16px, 0);"
-});
-
-// Start Button Tooltip. As soon as Firebug is fully loaded, the tooltip content will be
-// generated by firebug/firefox/start-button/startButtonOverlay module.
-$menupopupOverlay($("mainPopupSet"), [
-    $tooltip({
-        "class": "firebugButtonTooltip",
-        id: "firebug-buttonTooltip",
-        orient: "vertical",
-    }, [
-        $label({
-            "class": "version",
-            "value": "Firebug " + Firebug.GlobalUI.getVersion()
-        }),
-        $label({
-            "class": "status",
-            "value": Locale.$STR("startbutton.tip.deactivated")
-        })
-    ])
-]);
-
-// TODO: why contextmenu doesn't work without cloning
-$toolbarButton("firebug-button", {
-    label: "firebug.Firebug",
-    tooltip: "firebug-buttonTooltip",
-    type: "menu-button",
-    command: "cmd_firebug_toggleFirebug",
-    contextmenu: "fbStatusContextMenu",
-    observes: "firebugStatus",
-    style: "list-style-image: url(chrome://firebug/skin/firebug16.png)"
-}, [$("fbStatusContextMenu").cloneNode(true)]);
-
-// Appends Firebug start button into Firefox toolbar automatically after installation.
-// The button is appended only once - if the user removes it, it isn't appended again.
-// TODO: merge into $toolbarButton?
-// toolbarpalette check is for seamonkey, where it is in the document
-if ((!$("firebug-button") || $("firebug-button").parentNode.tagName == "toolbarpalette")
-    && !PrefLoader.getPref("toolbarCustomizationDone"))
-{
-    PrefLoader.setPref("toolbarCustomizationDone", true);
+        var contextMenu = this.win.nsContextMenu;
+        if (typeof(contextMenu) == "undefined")
+            return;
 
-    // Get the current navigation bar button set (a string of button IDs) and append
-    // ID of the Firebug start button into it.
-    var startButtonId = "firebug-button";
-    var navBarId = "nav-bar";
-    var navBar = $(navBarId);
-    var currentSet = navBar.currentSet;
+        contextMenu.prototype.setTarget = this.setTargetOriginal;
+        contextMenu.prototype.initItems = this.initItemsOriginal;
+    },
 
-    if (FBTrace.DBG_INITIALIZE)
-        FBTrace.sysout("Startbutton; curSet (before modification): " + currentSet);
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+    // First Run Page
 
-    // Append only if the button is not already there.
-    var curSet = currentSet.split(",");
-    if (curSet.indexOf(startButtonId) == -1)
+    loadFirstRunPage: function(reason)
     {
-        navBar.insertItem(startButtonId);
-        navBar.setAttribute("currentset", navBar.currentSet);
-        navBar.ownerDocument.persist("nav-bar", "currentset");
-
-        // Check whether insertItem really works
-        var curSet = navBar.currentSet.split(",");
-        if (curSet.indexOf(startButtonId) == -1)
-            FBTrace.sysout("Startbutton; navBar.insertItem doesn't work", curSet);
+        if (this.checkFirebugVersion(Options.get("currentVersion")) <= 0)
+            return;
 
-        if (FBTrace.DBG_INITIALIZE)
-            FBTrace.sysout("Startbutton; curSet (after modification): " + navBar.currentSet);
+        // Do not show the first run page when Firebug is being updated. It'll be displayed
+        // the next time the browser is restarted
+        // # ADDON_UPGRADE == 7
+        if (reason == 7)
+            return;
 
-        try
+        // Open the page in the top most window, so the user can see it immediately.
+        var wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
+        if (wm.getMostRecentWindow("navigator:browser") == this.win.top)
         {
-            // The current global scope is browser.xul.
-            BrowserToolboxCustomizeDone(true);
-        }
-        catch (e)
-        {
-            if (FBTrace.DBG_ERRORS)
-                FBTrace.sysout("startButton; appendToToolbar EXCEPTION " + e, e);
-        }
-    }
-
-    // Don't forget to show the navigation bar - just in case it's hidden.
-    navBar.removeAttribute("collapsed");
-    document.persist(navBarId, "collapsed");
-}
-
-// ********************************************************************************************* //
-// Localization
-
-// Internationalize all elements with 'fbInternational' class. Clone before internationalizing.
-var elements = cloneArray(document.getElementsByClassName("fbInternational"));
-Locale.internationalizeElements(document, elements, ["label", "tooltiptext", "aria-label"]);
-
-// ********************************************************************************************* //
-// First Run Page
+            // Update the preference to make sure the page is not displayed again.
+            // To avoid being annoying when Firefox crashes, forcibly save it, too.
+            var version = this.getVersion();
+            Options.set("currentVersion", version);
 
-var wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
-
-function checkFirebugVersion(currentVersion)
-{
-    if (!currentVersion)
-        return 1;
+            if (Options.get("showFirstRunPage"))
+            {
+                var self = this;
+                var timeout = this.win.setTimeout(function()
+                {
+                    if (self.win.closed)
+                        return;
 
-    var version = Firebug.GlobalUI.getVersion();
+                    self.openFirstRunPage(self.win);
+                }, 1000);
 
-    // Use Firefox comparator service.
-    var versionChecker = Cc["@mozilla.org/xpcom/version-comparator;1"].
-        getService(Ci.nsIVersionComparator);
-    return versionChecker.compare(version, currentVersion);
-}
+                this.win.addEventListener("unload", function()
+                {
+                    clearTimeout(timeout);
+                }, false);
+            }
+        }
+    },
 
-if (checkFirebugVersion(PrefLoader.getPref("currentVersion")) > 0)
-{
-    // Open the page in the top most window, so the user can see it immediately.
-    if (wm.getMostRecentWindow("navigator:browser") == window.top)
+    openFirstRunPage: function(win)
     {
-        // Don't forget to update the preference, so the page is not displayed again
-        var version = Firebug.GlobalUI.getVersion();
-        PrefLoader.setPref("currentVersion", version);
+        var version = this.getVersion();
+        var url = firstRunPage + version;
 
-        if (PrefLoader.getPref("showFirstRunPage"))
+        var browser = win.gBrowser;
+        if (!browser)
         {
-            var timeout = setTimeout(function()
-            {
-                if (window.closed)
-                    return;
-
-                Firebug.GlobalUI.openFirstRunPage();
-            }, 1000);
-
-            window.addEventListener("unload", function()
-            {
-                clearTimeout(timeout);
-            }, false);
+            FBTrace.sysout("browserOverlay.openFirstRunPage; ERROR there is no gBrowser!");
+            return;
         }
-    }
-}
 
-// ********************************************************************************************* //
-// Firefox Page Context Menu
+        // Open the firstRunPage in background
+        /*gBrowser.selectedTab = */browser.addTab(url, null, null, null);
 
-if (typeof(nsContextMenu) != "undefined")
-{
-    // https://bugzilla.mozilla.org/show_bug.cgi?id=433168
-    var setTargetOriginal = nsContextMenu.prototype.setTarget;
-    nsContextMenu.prototype.setTarget = function(aNode, aRangeParent, aRangeOffset)
-    {
-        setTargetOriginal.apply(this, arguments);
-        if (this.isTargetAFormControl(aNode))
-            this.shouldDisplay = true;
-    };
-
-    // Hide built-in inspector if the pref says so.
-    var initItemsOriginal = nsContextMenu.prototype.initItems;
-    nsContextMenu.prototype.initItems = function()
+        // Make sure prefs are stored, otherwise the firstRunPage would be displayed
+        // again if Firefox crashes.
+        this.win.setTimeout(function()
+        {
+            Options.forceSave();
+        }, 400);
+    },
+
+    checkFirebugVersion: function(currentVersion)
     {
-        initItemsOriginal.apply(this, arguments);
+        if (!currentVersion)
+            return 1;
 
-        // Hide built-in inspector menu item if the pref "extensions.firebug.hideDefaultInspector"
-        // says so. Note that there is also built-in preference "devtools.inspector.enable" that
-        // can be used for the same purpose.
-        var hideInspect = PrefLoader.getPref("hideDefaultInspector");
-        if (hideInspect)
-        {
-            this.showItem("inspect-separator", false);
-            this.showItem("context-inspect", false);
-        }
-    }
-}
+        var version = this.getVersion();
 
-// ********************************************************************************************* //
-// All Pages Activation" is on
+        // Use Firefox comparator service.
+        var versionChecker = Cc["@mozilla.org/xpcom/version-comparator;1"].
+            getService(Ci.nsIVersionComparator);
 
-// Load Firebug by default if activation is on for all pages (see issue 5522)
-if (PrefLoader.getPref("allPagesActivation") == "on" || !PrefLoader.getPref("delayLoad"))
-{
-    Firebug.GlobalUI.startFirebug(function()
-    {
-        FBTrace.sysout("Firebug loaded by default since 'allPagesActivation' is on " +
-            "or 'delayLoad' is false");
-    });
+        return versionChecker.compare(version, currentVersion);
+    }
 }
 
 // ********************************************************************************************* //
+// Registration
 
-if (FBTrace.DBG_INITIALIZE)
-    FBTrace.sysout("Firebug global overlay applied");
+return BrowserOverlay;
 
 // ********************************************************************************************* //
-})();
+}});
diff --git a/trace/FBTrace/chrome/firebug/content/firefox/browserOverlayLib.js b/trace/FBTrace/chrome/firebug/content/firefox/browserOverlayLib.js
new file mode 100644
index 0000000..e5e967e
--- /dev/null
+++ b/trace/FBTrace/chrome/firebug/content/firefox/browserOverlayLib.js
@@ -0,0 +1,272 @@
+/* See license.txt for terms of usage */
+
+define([
+    "firebug/lib/trace",
+    "firebug/lib/locale",
+],
+function(FBTrace, Locale) {
+
+// ********************************************************************************************* //
+// Constants
+
+var Cc = Components.classes;
+var Ci = Components.interfaces;
+var Cu = Components.utils;
+
+// ********************************************************************************************* //
+// Overlay Helpers
+
+var BrowserOverlayLib =
+{
+    $: function(doc, id)
+    {
+        return doc.getElementById(id);
+    },
+
+    $$: function(doc, selector)
+    {
+        return doc.querySelectorAll(selector);
+    },
+
+    $el: function(doc, name, attributes, children, parent)
+    {
+        if (!(doc instanceof Ci.nsIDOMDocument))
+        {
+            if (FBTrace.DBG_ERRORS)
+                FBTrace.sysout("browserOvelayLib.$el; No document!")
+            return;
+        }
+
+        attributes = attributes || {};
+
+        if (!Array.isArray(children) && !parent)
+        {
+            parent = children;
+            children = null;
+        }
+
+        // localize
+        if (attributes.label)
+            attributes.label = Locale.$STR(attributes.label);
+
+        if (attributes.tooltiptext)
+            attributes.tooltiptext = Locale.$STR(attributes.tooltiptext);
+
+        // persist
+        if (attributes.persist)
+            updatePersistedValues(doc, attributes);
+
+        var el = doc.createElement(name);
+        for (var a in attributes)
+            el.setAttribute(a, attributes[a]);
+
+        for each (var a in children)
+            el.appendChild(a);
+
+        if (parent)
+        {
+            if (attributes.position)
+                parent.insertBefore(el, parent.children[attributes.position - 1]);
+            else
+                parent.appendChild(el);
+
+            // Mark to remove when Firebug is uninstalled.
+            el.setAttribute("firebugRootNode", true);
+        }
+
+        return el;
+    },
+
+    $command: function(doc, id, oncommand, arg)
+    {
+        // Wrap the command within a startFirebug call. If Firebug isn't yet loaded
+        // this will force it to load.
+        oncommand = "Firebug.browserOverlay.startFirebug(function(){" + oncommand + "})";
+        if (arg)
+            oncommand = "void function(arg){" + oncommand + "}(" + arg + ")";
+
+        return this.$el(doc, "command", {
+            id: id,
+            oncommand: oncommand
+        }, this.$(doc, "mainCommandSet"))
+    },
+
+    $key: function(doc, id, key, modifiers, command, position)
+    {
+        var attributes = {
+            id: id,
+            modifiers: modifiers,
+            command: command,
+            position: position
+        };
+
+        attributes[KeyEvent["DOM_" + key] ? "keycode" : "key"] = key;
+
+        return this.$el(doc, "key", attributes, $(doc, "mainKeyset"));
+    },
+
+    $menupopup: function(doc, attributes, children, parent)
+    {
+        return this.$el(doc, "menupopup", attributes, children, parent);
+    },
+
+    $menu: function(doc, attrs, children)
+    {
+        return this.$el(doc, "menu", attrs, children);
+    },
+
+    $menuseparator: function(doc, attrs)
+    {
+        return this.$el(doc, "menuseparator", attrs);
+    },
+
+    $menuitem: function(doc, attrs)
+    {
+        return this.$el(doc, "menuitem", attrs);
+    },
+
+    $splitmenu: function(doc, attrs, children)
+    {
+        return this.$el(doc, "splitmenu", attrs, children);
+    },
+
+    $menupopupOverlay: function(doc, parent, children)
+    {
+        if (!parent)
+            return;
+
+        for (var i=0; i<children.length; ++i)
+        {
+            var child = children[i];
+            var beforeEl;
+
+            if (child.getAttribute("position"))
+            {
+                var pos = child.getAttribute("position");
+                beforeEl = parent.children[pos - 1];
+            }
+            else if (child.getAttribute("insertbefore"))
+            {
+                var ids = child.getAttribute("insertbefore").split(",");
+                for (var j=0; j < ids.length; ++j)
+                {
+                    beforeEl = parent.querySelector("#" + ids[j]);
+                    if (beforeEl)
+                        break;
+                }
+            }
+            else if (child.getAttribute("insertafter"))
+            {
+                var ids = child.getAttribute("insertafter").split(",");
+                for (var j=0; j < ids.length; ++j)
+                {
+                    beforeEl = parent.querySelector("#" + ids[j]);
+                    if (beforeEl)
+                        break;
+                }
+                if (beforeEl)
+                    beforeEl = beforeEl.nextSibling;
+            }
+
+            if (beforeEl)
+                parent.insertBefore(child, beforeEl);
+            else
+                parent.appendChild(child);
+
+            // Mark the inserted node to remove it when Firebug is uninstalled.
+            child.setAttribute("firebugRootNode", true);
+        }
+    },
+
+    $toolbarButton: function(doc, id, attrs, children, defaultPos)
+    {
+        attrs["class"] = "toolbarbutton-1";
+        attrs.firebugRootNode = true;
+        attrs.id = id;
+
+        // in seamonkey gNavToolbox is null onload
+        var button = this.$el(doc, "toolbarbutton", attrs, children,
+            (doc.defaultView.gNavToolbox || this.$(doc, "navigator-toolbox")).palette);
+
+        var selector = "[currentset^='" + id + ",'],[currentset*='," + id +
+            ",'],[currentset$='," + id + "']";
+
+        var toolbar = doc.querySelector(selector);
+        if (!toolbar)
+            return; // todo defaultPos
+
+        var currentset = toolbar.getAttribute("currentset").split(",");
+        var i = currentset.indexOf(id) + 1;
+
+        var len = currentset.length, beforeEl;
+        while (i < len && !(beforeEl = this.$(doc, currentset[i])))
+            i++;
+
+        return toolbar.insertItem(id, beforeEl);
+    },
+
+    $tooltip: function(doc, attrs, children)
+    {
+        return this.$el(doc, "tooltip", attrs, children);
+    },
+
+    $label: function(doc, attrs)
+    {
+        return this.$el(doc, "label", attrs);
+    },
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+    // Stylesheets & Scripts
+
+    $stylesheet: function(doc, href)
+    {
+        var s = doc.createProcessingInstruction("xml-stylesheet", 'href="' + href + '"');
+        doc.insertBefore(s, doc.documentElement);
+        return s;
+    },
+
+    $script: function(doc, src)
+    {
+        var script = doc.createElementNS("http://www.w3.org/1999/xhtml", "html:script");
+        script.src = src;
+        script.type = "text/javascript";
+        script.setAttribute("firebugRootNode", true);
+        doc.documentElement.appendChild(script);
+    },
+}
+
+// ********************************************************************************************* //
+// Helpers
+
+function updatePersistedValues(doc, options)
+{
+    var persist = options.persist.split(",");
+    var id = options.id;
+    var RDF = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
+    var store = doc.defaultView.PlacesUIUtils.localStore; //this.RDF.GetDataSource("rdf:local-store");
+    var root = RDF.GetResource("chrome://browser/content/browser.xul#" + id);
+
+    var getPersist = function getPersist(aProperty)
+    {
+        var property = RDF.GetResource(aProperty);
+        var target = store.GetTarget(root, property, true);
+
+        if (target instanceof Ci.nsIRDFLiteral)
+            return target.Value;
+    }
+
+    for each(var attr in persist)
+    {
+        var val = getPersist(attr);
+        if (val)
+            options[attr] = val;
+    }
+}
+
+// ********************************************************************************************* //
+// Registration
+
+return BrowserOverlayLib;
+
+// ********************************************************************************************* //
+});
diff --git a/trace/FBTrace/chrome/firebug/content/firefox/browserToolbar.js b/trace/FBTrace/chrome/firebug/content/firefox/browserToolbar.js
new file mode 100644
index 0000000..ebd7c87
--- /dev/null
+++ b/trace/FBTrace/chrome/firebug/content/firefox/browserToolbar.js
@@ -0,0 +1,136 @@
+/* See license.txt for terms of usage */
+
+define([
+    "firebug/lib/trace",
+    "firebug/lib/options",
+    "firebug/lib/locale",
+    "firebug/firefox/browserOverlayLib",
+],
+function(FBTrace, Options, Locale, BrowserOverlayLib) {
+with (BrowserOverlayLib) {
+
+// ********************************************************************************************* //
+// Constants
+
+// ********************************************************************************************* //
+// Firefox Toolbar Buttons
+
+var BrowserToolbar =
+{
+    overlay: function(doc, version)
+    {
+        this.overlayToolbarButtons(doc, version);
+        this.customizeToolbar(doc);
+    },
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+    // Firebug Start Button Popup Menu
+
+    overlayToolbarButtons: function(doc, version)
+    {
+        $toolbarButton(doc, "firebug-inspectorButton", {
+            label: "firebug.Inspect",
+            tooltiptext: "firebug.InspectElement",
+            observes: "cmd_firebug_toggleInspecting",
+            style: "list-style-image: url(chrome://firebug/skin/inspect.png);" +
+                "-moz-image-region: rect(0, 16px, 16px, 0);"
+        });
+
+        // Start Button Tooltip. As soon as Firebug is fully loaded, the tooltip content will be
+        // generated by firebug/firefox/start-button/startButtonOverlay module.
+        $menupopupOverlay(doc, $(doc, "mainPopupSet"), [
+            $tooltip(doc, {
+                "class": "firebugButtonTooltip",
+                id: "firebug-buttonTooltip",
+                orient: "vertical",
+            }, [
+                $label(doc, {
+                    "class": "version",
+                    "value": "Firebug " + version
+                }),
+                $label(doc, {
+                    "class": "status",
+                    "value": Locale.$STR("startbutton.tip.deactivated")
+                })
+            ])
+        ]);
+
+        // TODO: why contextmenu doesn't work without cloning
+        $toolbarButton(doc, "firebug-button", {
+            label: "firebug.Firebug",
+            tooltip: "firebug-buttonTooltip",
+            type: "menu-button",
+            command: "cmd_firebug_toggleFirebug",
+            contextmenu: "fbStatusContextMenu",
+            observes: "firebugStatus",
+            style: "list-style-image: url(chrome://firebug/skin/firebug16.png)"
+        }, [$(doc, "fbStatusContextMenu").cloneNode(true)]);
+    },
+
+    customizeToolbar: function(doc)
+    {
+        // Appends Firebug start button into Firefox toolbar automatically after installation.
+        // The button is appended only once - if the user removes it, it isn't appended again.
+        // TODO: merge into $toolbarButton?
+        // toolbarpalette check is for seamonkey, where it is in the document
+        if ((!$(doc, "firebug-button") ||
+            $(doc, "firebug-button").parentNode.tagName == "toolbarpalette")
+            && !Options.get("toolbarCustomizationDone"))
+        {
+            Options.set("toolbarCustomizationDone", true);
+
+            // Get the current navigation bar button set (a string of button IDs) and append
+            // ID of the Firebug start button into it.
+            var startButtonId = "firebug-button";
+            var navBarId = "nav-bar";
+            var navBar = $(doc, navBarId);
+            var currentSet = navBar.currentSet;
+
+            if (FBTrace.DBG_INITIALIZE)
+                FBTrace.sysout("Startbutton; curSet (before modification): " + currentSet);
+
+            // Append only if the button is not already there.
+            var curSet = currentSet.split(",");
+            if (curSet.indexOf(startButtonId) == -1)
+            {
+                navBar.insertItem(startButtonId);
+                navBar.setAttribute("currentset", navBar.currentSet);
+                navBar.ownerDocument.persist("nav-bar", "currentset");
+
+                // Check whether insertItem really works
+                var curSet = navBar.currentSet.split(",");
+                if (curSet.indexOf(startButtonId) == -1)
+                    FBTrace.sysout("Startbutton; navBar.insertItem doesn't work", curSet);
+
+                if (FBTrace.DBG_INITIALIZE)
+                {
+                    FBTrace.sysout("Startbutton; curSet (after modification): " +
+                        navBar.currentSet);
+                }
+
+                try
+                {
+                    // The current global scope is browser.xul.
+                    BrowserToolboxCustomizeDone(true);
+                }
+                catch (e)
+                {
+                    if (FBTrace.DBG_ERRORS)
+                        FBTrace.sysout("startButton; appendToToolbar EXCEPTION " + e, e);
+                }
+            }
+
+            // Don't forget to show the navigation bar - just in case it's hidden.
+            navBar.removeAttribute("collapsed");
+            doc.persist(navBarId, "collapsed");
+        }
+    },
+}
+
+// ********************************************************************************************* //
+// Registration
+
+return BrowserToolbar;
+
+// ********************************************************************************************* //
+}});
diff --git a/trace/FBTrace/chrome/firebug/content/firefox/external-editors/changeeditor.js b/trace/FBTrace/chrome/firebug/content/firefox/external-editors/changeeditor.js
index 6ca76f0..06e1322 100644
--- a/trace/FBTrace/chrome/firebug/content/firefox/external-editors/changeeditor.js
+++ b/trace/FBTrace/chrome/firebug/content/firefox/external-editors/changeeditor.js
@@ -29,7 +29,7 @@ function onLoad()
         origImage = FBL.getIconURLForFile(item.executable);
         try
         {
-            var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
+            var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
             file.initWithPath(item.executable);
             document.getElementById("executable").file = file;
             origLabel = file.leafName.replace(".exe","");
@@ -123,7 +123,7 @@ function onAccept()
 
     try
     {
-        var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
+        var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
         file.initWithPath(item.executable);
         if (!file.isExecutable())
            throw "NotAnExecutable";
diff --git a/trace/FBTrace/chrome/firebug/content/firefox/external-editors/editors.xul b/trace/FBTrace/chrome/firebug/content/firefox/external-editors/editors.xul
index 0c1b6aa..8da86d3 100644
--- a/trace/FBTrace/chrome/firebug/content/firefox/external-editors/editors.xul
+++ b/trace/FBTrace/chrome/firebug/content/firefox/external-editors/editors.xul
@@ -9,13 +9,15 @@
         id="firebug-external-editors"
         width="600" height="300"
         title="firebug.Configure_Editors"
-        onload="gEditorManager.init();gUrlMappingManager.init()"
-        onunload="gEditorManager.uninit();gUrlMappingManager.uninit()"
+        onload="gEditorManager.init();/*gUrlMappingManager.init()*/"
+        onunload="gEditorManager.uninit();/*gUrlMappingManager.uninit()*/"
         persist="screenX screenY width height">
 
-    <script src="chrome://firebug/content/xpcom.js"/>
-    <script src="chrome://firebug/content/firefox/external-editors/editors.js"/>
+    <script type="application/x-javascript" src="chrome://firebug/content/xpcom.js"/>
+    <script type="application/x-javascript"
+        src="chrome://firebug/content/firefox/external-editors/editors.js"/>
 
+    <!--
     <tabbox flex="1" class="contentPane">
         <tabs>
             <tab label="editors.Configured_Firebug_Editors" class="fbInternational"/>
@@ -23,49 +25,56 @@
         </tabs>
         <tabpanels flex="1">
             <tabpanel flex="1" orient="vertical">
-                 <tree id="editorsList" flex="1" seltype="single"
-                    lastSelected="0" persist="lastSelected"
-                    onselect="gEditorManager.onSelectionChanged();"
-                    ondblclick="gEditorManager.changeEditorHandler();">
-                    <treecols>
-                        <treecol id="editorName" ignoreincolumnpicker="true" flex="1"
-                            persist="width" class="fbInternational"
-                            label="editors.Editor"/>
-                        <splitter class="tree-splitter" />
-                        <treecol id="editorExecutable" flex="1"
-                            persist="width" class="fbInternational"
-                            label="editors.Executable"/>
-                        <splitter class="tree-splitter" />
-                        <treecol id="editorParams" flex="1"
-                            persist="width" class="fbInternational"
-                            label="editors.Launch_Arguments"/>
-                    </treecols>
-                    <treechildren/>
-                </tree>
+    -->
+    <vbox flex="1" class="contentPane">
+        <label id="actionsIntro" control="editorsList"
+            value="editors.Configured_Firebug_Editors" class="fbInternational"/>
+        <separator class="thin"/>
+        <tree id="editorsList" flex="1" seltype="single"
+            lastSelected="0" persist="lastSelected"
+            onselect="gEditorManager.onSelectionChanged();"
+            ondblclick="gEditorManager.changeEditorHandler();">
+            <treecols>
+                <treecol id="editorName" ignoreincolumnpicker="true" flex="1"
+                    persist="width" class="fbInternational"
+                    label="editors.Editor"/>
+                <splitter class="tree-splitter" />
+                <treecol id="editorExecutable" flex="1"
+                    persist="width" class="fbInternational"
+                    label="editors.Executable"/>
+                <splitter class="tree-splitter" />
+                <treecol id="editorParams" flex="1"
+                    persist="width" class="fbInternational"
+                    label="editors.Launch_Arguments"/>
+            </treecols>
+            <treechildren/>
+        </tree>
+    </vbox>
 
-                <separator class="thin"/>
+    <separator class="thin"/>
 
-                <hbox>
-                    <hbox flex="1" class="actionButtons">
-                        <button id="addEditor" icon="add"
-                            label="editors.Add" class="fbInternational"
-                            oncommand="gEditorManager.addEditorHandler();"/>
-                        <button id="removeEditor" icon="remove"
-                            label="editors.Remove" class="fbInternational"
-                            oncommand="gEditorManager.removeEditorHandler();"/>
-                        <button id="changeEditor"
-                            label="editors.Change" class="fbInternational"
-                            oncommand="gEditorManager.changeEditorHandler();"/>
-                        <button id="moveUpEditor"
-                            label="editors.Move_Up" class="fbInternational"
-                            oncommand="gEditorManager.moveUpEditorHandler();"/>
-                            <spacer flex="1"/>
-                        <button id="closeDialogButton"
-                            oncommand="close();" icon="close"
-                            label="editors.Close" class="fbInternational"/>
-                    </hbox>
-                    <resizer dir="bottomright"/>
-                </hbox>
+    <hbox>
+        <hbox flex="1" class="actionButtons">
+            <button id="addEditor" icon="add"
+                label="editors.Add" class="fbInternational"
+                oncommand="gEditorManager.addEditorHandler();"/>
+            <button id="removeEditor" icon="remove"
+                label="editors.Remove" class="fbInternational"
+                oncommand="gEditorManager.removeEditorHandler();"/>
+            <button id="changeEditor"
+                label="editors.Change" class="fbInternational"
+                oncommand="gEditorManager.changeEditorHandler();"/>
+            <button id="moveUpEditor"
+                label="editors.Move_Up" class="fbInternational"
+                oncommand="gEditorManager.moveUpEditorHandler();"/>
+            <spacer flex="1"/>
+            <button id="closeDialogButton"
+                oncommand="close();" icon="close"
+                label="editors.Close" class="fbInternational"/>
+        </hbox>
+        <resizer dir="bottomright"/>
+    </hbox>
+    <!--
             </tabpanel>
             <tabpanel flex="1" orient="vertical">
                 <textbox id="urlMappings" multiline="true" flex="1" wrap="off"
@@ -79,5 +88,6 @@
             </tabpanel>
         </tabpanels>
     </tabbox>
+    -->
 
 </window>
diff --git a/trace/FBTrace/chrome/firebug/content/firefox/external-editors/externalEditors.js b/trace/FBTrace/chrome/firebug/content/firefox/external-editors/externalEditors.js
index 3fe7775..d287134 100644
--- a/trace/FBTrace/chrome/firebug/content/firefox/external-editors/externalEditors.js
+++ b/trace/FBTrace/chrome/firebug/content/firefox/external-editors/externalEditors.js
@@ -30,7 +30,6 @@ const DirService = Xpcom.CCSV("@mozilla.org/file/directory_service;1",
     "nsIDirectoryServiceProvider");
 const NS_OS_TEMP_DIR = "TmpD"
 const nsIFile = Ci.nsIFile;
-const nsILocalFile = Ci.nsILocalFile;
 const nsISafeOutputStream = Ci.nsISafeOutputStream;
 const nsIURI = Ci.nsIURI;
 
@@ -237,11 +236,17 @@ Firebug.ExternalEditors = Obj.extend(Firebug.Module,
         var item = doc.createElement("menu");
         item.setAttribute("type", "splitmenu");
         item.setAttribute("iconic", "true");
-        item.setAttribute("oncommand", "Firebug.ExternalEditors.onContextMenuCommand(event)");
+
+        item.addEventListener("command", function(event)
+        {
+            Firebug.ExternalEditors.onContextMenuCommand(event);
+        });
 
         var menupopup = doc.createElement("menupopup");
-        menupopup.setAttribute("onpopupshowing",
-            "return Firebug.ExternalEditors.onEditorsShowing(this)");
+        menupopup.addEventListener("popupshowing", function(event)
+        {
+            return Firebug.ExternalEditors.onEditorsShowing(this)
+        });
 
         item.appendChild(menupopup);
         return item;
@@ -535,7 +540,7 @@ Firebug.ExternalEditors = Obj.extend(Firebug.Module,
         if (System.getPlatformName() == "WINNT")
             lpath = lpath.replace(/\//g, "\\");
 
-        var file = Xpcom.QI(temporaryDirectory.clone(), nsILocalFile);
+        var file = Xpcom.QI(temporaryDirectory.clone(), nsIFile);
         file.appendRelativePath(lpath);
         if (!file.exists())
             file.create(nsIFile.NORMAL_FILE_TYPE, 0664);
@@ -561,7 +566,7 @@ Firebug.ExternalEditors = Obj.extend(Firebug.Module,
     {
         try
         {
-            var file = Xpcom.CCIN("@mozilla.org/file/local;1", "nsILocalFile");
+            var file = Xpcom.CCIN("@mozilla.org/file/local;1", "nsIFile");
             for (var i = 0; i < temporaryFiles.length; ++i)
             {
                 file.initWithPath(temporaryFiles[i]);
diff --git a/trace/FBTrace/chrome/firebug/content/firefox/firebug.xul b/trace/FBTrace/chrome/firebug/content/firefox/firebug.xul
index 47476b8..dc35fa6 100644
--- a/trace/FBTrace/chrome/firebug/content/firefox/firebug.xul
+++ b/trace/FBTrace/chrome/firebug/content/firefox/firebug.xul
@@ -10,7 +10,6 @@
         persist="screenX,screenY,width,height,sizemode"
         onload="importFirebug()" onunload="" onclose="return exportFirebug();">
 
-
     <vbox flex="2" id="fbMainFrame" collapsed="false">
         <browser id="fbMainContainer" flex="2" src="" disablehistory="true" />
     </vbox>
@@ -23,6 +22,8 @@
         <key oncommand="doFirefoxCommand('Browser:ReloadSkipCache')" key='r' modifiers='accel,shift'/>
     </keyset>
 
+    <script type="application/x-javascript" src="chrome://firebug/content/trace.js"/>
+
     <script type="application/x-javascript">
         doFirefoxCommand = function(id)
         {
@@ -31,8 +32,9 @@
 
         importFirebug = function()
         {
-            var Firebug = opener.Firebug, fbc = Firebug.chrome;
+            FBTrace.sysout("firebug.xul; importFirebug");
 
+            var Firebug = opener.Firebug, fbc = Firebug.chrome;
             if (fbc.inDetachedScope)
             {
                 exportFirebug = null;
@@ -51,8 +53,7 @@
 
             fbc.originalBrowser.contentWindow.onunload = function()
             {
-                fbc.shutdown();
-                fbc.window.top.close();
+                window.close();
             }
 
             fbc.onDetach();
@@ -61,6 +62,8 @@
 
         exportFirebug = function()
         {
+            FBTrace.sysout("firebug.xul; exportFirebug");
+
             exportFirebug = null;
             var Firebug = opener.Firebug, fbc = Firebug.chrome;
 
diff --git a/trace/FBTrace/chrome/firebug/content/firefox/start-button/startButtonOverlay.js b/trace/FBTrace/chrome/firebug/content/firefox/start-button/startButtonOverlay.js
index 75c0290..0ae7c0f 100644
--- a/trace/FBTrace/chrome/firebug/content/firefox/start-button/startButtonOverlay.js
+++ b/trace/FBTrace/chrome/firebug/content/firefox/start-button/startButtonOverlay.js
@@ -7,9 +7,10 @@ define([
     "firebug/lib/locale",
     "firebug/lib/events",
     "firebug/lib/dom",
-    "firebug/lib/options"
+    "firebug/lib/options",
+    "firebug/firefox/browserOverlayLib",
 ],
-function(Obj, Firebug, Firefox, Locale, Events, Dom, Options) {
+function(Obj, Firebug, Firefox, Locale, Events, Dom, Options, BrowserOverlayLib) {
 
 // ********************************************************************************************* //
 // Constants
@@ -58,20 +59,22 @@ Firebug.StartButton = Obj.extend(Firebug.Module,
     onTooltipShowing: function(event)
     {
         var tooltip = event.target;
+        var doc = tooltip.ownerDocument;
+
         Dom.eraseNode(tooltip);
 
-        with (Firebug.GlobalUI)
+        with (BrowserOverlayLib)
         {
-            tooltip.appendChild($label({
+            tooltip.appendChild($label(doc, {
                 "class": "version",
                 value: "Firebug " + Firebug.getVersion()
             }));
 
-            var status = $el("hbox");
+            var status = $el(doc, "hbox");
             tooltip.appendChild(status);
 
             var suspended = Firebug.getSuspended();
-            status.appendChild($label({
+            status.appendChild($label(doc, {
                 "class": "status",
                 value: suspended ? Locale.$STR("startbutton.tip.deactivated") :
                     Locale.$STRP("plural.Total_Firebugs2", [Firebug.TabWatcher.contexts.length])
@@ -80,14 +83,14 @@ Firebug.StartButton = Obj.extend(Firebug.Module,
             if (suspended)
                 return;
 
-            status.appendChild($label({
+            status.appendChild($label(doc, {
                 "class": "placement",
                 value: "(" + Locale.$STR(Firebug.getPlacement()) + ")"
             }));
 
             if (Firebug.allPagesActivation == "on")
             {
-                tooltip.appendChild($label({
+                tooltip.appendChild($label(doc, {
                     "class": "alwaysOn",
                     value: Locale.$STR("enablement.on") + " " +
                         Locale.$STR("enablement.for_all_pages")
@@ -95,7 +98,7 @@ Firebug.StartButton = Obj.extend(Firebug.Module,
             }
 
             // Panel enablement status info
-            tooltip.appendChild($label({
+            tooltip.appendChild($label(doc, {
                 "class": "enablement",
                 value: Locale.$STR("enablement.Panel_activation_status")
             }));
@@ -104,15 +107,15 @@ Firebug.StartButton = Obj.extend(Firebug.Module,
             for (var i=0; i<statuses.length; i++)
             {
                 var status = statuses[i];
-                var parent = $el("hbox");
+                var parent = $el(doc, "hbox");
                 tooltip.appendChild(parent);
 
-                parent.appendChild($label({
+                parent.appendChild($label(doc, {
                     "class": "panelName " + status.status,
                     value: status.name + ":"
                 }));
 
-                parent.appendChild($label({
+                parent.appendChild($label(doc, {
                     "class": "panelStatus " + status.status,
                     value: status.statusLabel
                 }));
diff --git a/trace/FBTrace/chrome/firebug/content/html/highlighter.css b/trace/FBTrace/chrome/firebug/content/html/highlighter.css
index cd9a93d..a8aad6c 100644
--- a/trace/FBTrace/chrome/firebug/content/html/highlighter.css
+++ b/trace/FBTrace/chrome/firebug/content/html/highlighter.css
@@ -14,8 +14,8 @@
     min-height: 0 !important;
     max-height: none !important;
     position: fixed !important;
-    -moz-transform: rotate(0deg) !important;
-    -moz-transform-origin: 50% 50% !important;
+    transform: rotate(0deg) !important;
+    transform-origin: 50% 50% !important;
     border-radius: 0 !important;
     box-shadow: none !important;
     background: transparent none !important;
@@ -126,4 +126,4 @@
 .fbProxyElement {
     position: fixed !important;
     pointer-events: auto !important;
-}
\ No newline at end of file
+}
diff --git a/trace/FBTrace/chrome/firebug/content/html/htmlPanel.js b/trace/FBTrace/chrome/firebug/content/html/htmlPanel.js
index 0318c9f..1d71977 100644
--- a/trace/FBTrace/chrome/firebug/content/html/htmlPanel.js
+++ b/trace/FBTrace/chrome/firebug/content/html/htmlPanel.js
@@ -20,6 +20,7 @@ define([
     "firebug/lib/persist",
     "firebug/chrome/menu",
     "firebug/lib/url",
+    "firebug/css/cssModule",
     "firebug/css/cssReps",
     "firebug/js/breakpoint",
     "firebug/editor/editor",
@@ -30,7 +31,7 @@ define([
 ],
 function(Obj, Firebug, Domplate, FirebugReps, Locale, HTMLLib, Events,
     SourceLink, Css, Dom, Win, Options, Xpath, Str, Xml, Arr, Persist, Menu,
-    Url, CSSInfoTip) {
+    Url, CSSModule, CSSInfoTip) {
 
 with (Domplate) {
 
@@ -346,6 +347,30 @@ Firebug.HTMLPanel.prototype = Obj.extend(WalkingPanel,
             null : ["link", "script", "style"]);
     },
 
+    updateNodeVisibility: function(node)
+    {
+        var wasHidden = node.classList.contains("nodeHidden");
+        if (!Xml.isVisible(node.repObject))
+        {
+            // Hide this node and, through CSS, every descendant.
+            node.classList.add("nodeHidden");
+        }
+        else if (wasHidden)
+        {
+            // The node has changed state from hidden to shown. While in the
+            // hidden state, some descendants may have been explicitly marked
+            // with .nodeHidden (not just through CSS inheritance), so we need
+            // to recheck the visibility of those.
+            node.classList.remove("nodeHidden");
+            var desc = Arr.cloneArray(node.getElementsByClassName("nodeHidden"));
+            for (var i = 0; i < desc.length; ++i)
+            {
+                if (Xml.isVisible(desc[i].repObject))
+                    desc[i].classList.remove("nodeHidden");
+            }
+        }
+    },
+
     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
     getElementSourceText: function(node)
@@ -479,10 +504,7 @@ Firebug.HTMLPanel.prototype = Obj.extend(WalkingPanel,
         if (!objectNodeBox)
             return;
 
-        if (Xml.isVisible(objectNodeBox.repObject))
-            Css.removeClass(objectNodeBox, "nodeHidden");
-        else
-            Css.setClass(objectNodeBox, "nodeHidden");
+        this.updateNodeVisibility(objectNodeBox);
 
         if (attrChange == MODIFICATION || attrChange == ADDITION)
         {
@@ -667,6 +689,10 @@ Firebug.HTMLPanel.prototype = Obj.extend(WalkingPanel,
                 {
                     this.ioBox.removeChildBox(parentNodeBox, target);
 
+                    // Special case for docType.
+                    if (target instanceof HTMLHtmlElement)
+                        this.ioBox.removeChildBox(parentNodeBox, target.parentNode.doctype);
+
                     this.highlightMutation(parentNodeBox, parentNodeBox, "mutated");
                 }
                 else
@@ -694,6 +720,13 @@ Firebug.HTMLPanel.prototype = Obj.extend(WalkingPanel,
                         this.ioBox.insertChildBoxBefore(parentNodeBox, target, nextSibling) :
                         this.ioBox.appendChildBox(parentNodeBox, target);
 
+                    // Special case for docType.
+                    if (target instanceof HTMLHtmlElement)
+                    {
+                        this.ioBox.insertChildBoxBefore(parentNodeBox,
+                            target.parentNode.doctype, target);
+                    }
+
                     this.highlightMutation(objectBox, objectBox, "mutated");
                 }
             }
@@ -1161,6 +1194,74 @@ Firebug.HTMLPanel.prototype = Obj.extend(WalkingPanel,
     },
 
     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+    // CSS Listener
+
+    updateVisibilitiesForSelectorInSheet: function(sheet, selector)
+    {
+        if (!selector)
+            return;
+        var doc = (sheet && sheet.ownerNode && sheet.ownerNode.ownerDocument);
+        if (!doc)
+            return;
+
+        var affected = doc.querySelectorAll(selector);
+        if (!affected.length || !this.ioBox.isInExistingRoot(affected[0]))
+            return;
+
+        for (var i = 0; i < affected.length; ++i)
+        {
+            var node = this.ioBox.findObjectBox(affected[i]);
+            if (node)
+                this.updateNodeVisibility(node);
+        }
+    },
+
+    updateVisibilitiesForRule: function(rule)
+    {
+        this.updateVisibilitiesForSelectorInSheet(rule.parentStyleSheet, rule.selectorText);
+    },
+
+    cssPropAffectsVisibility: function(propName)
+    {
+        // Pretend that "display" is the only property which affects visibility,
+        // which is a half-truth. We could make this more technically correct
+        // by unconditionally returning true, but forcing a synchronous reflow
+        // and computing offsetWidth/Height on up to every element on the page
+        // isn't worth it.
+        return (propName === "display");
+    },
+
+    cssTextAffectsVisibility: function(cssText)
+    {
+        return (cssText.indexOf("display:") !== -1);
+    },
+
+    onAfterCSSDeleteRule: function(styleSheet, cssText, selector)
+    {
+        if (this.cssTextAffectsVisibility(cssText))
+            this.updateVisibilitiesForSelectorInSheet(styleSheet, selector);
+    },
+
+    onCSSInsertRule: function(styleSheet, cssText, ruleIndex)
+    {
+        if (this.cssTextAffectsVisibility(cssText))
+            this.updateVisibilitiesForRule(styleSheet.cssRules[ruleIndex]);
+    },
+
+    onCSSSetProperty: function(style, propName, propValue, propPriority, prevValue,
+        prevPriority, rule, baseText)
+    {
+        if (this.cssPropAffectsVisibility(propName))
+            this.updateVisibilitiesForRule(rule);
+    },
+
+    onCSSRemoveProperty: function(style, propName, prevValue, prevPriority, rule, baseText)
+    {
+        if (this.cssPropAffectsVisibility(propName))
+            this.updateVisibilitiesForRule(rule);
+    },
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
     // extends Panel
 
     name: "html",
@@ -1181,6 +1282,7 @@ Firebug.HTMLPanel.prototype = Obj.extend(WalkingPanel,
         this.onKeyPress = Obj.bind(this.onKeyPress, this);
 
         Firebug.Panel.initialize.apply(this, arguments);
+        Firebug.CSSModule.addListener(this);
     },
 
     destroy: function(state)
@@ -1199,6 +1301,7 @@ Firebug.HTMLPanel.prototype = Obj.extend(WalkingPanel,
             delete this.inspectorHistory[i];
         delete this.inspectorHistory;
 
+        Firebug.CSSModule.removeListener(this);
         this.unregisterMutationListeners();
     },
 
@@ -2262,6 +2365,25 @@ AttributeEditor.prototype = domplate(Firebug.InlineEditor.prototype,
         var emptyAttr = {name: "", value: ""};
         var sibling = insertWhere == "before" ? target.previousSibling : target;
         return AttrTag.insertAfter({attr: emptyAttr}, sibling);
+    },
+
+    getInitialValue: function(target, value)
+    {
+        if (value == "")
+            return value;
+
+        var element = Firebug.getRepObject(target);
+        if (element && element instanceof window.Element)
+        {
+            // If object that was clicked to edit was
+            // attribute value, not attribute name.
+            if (Css.hasClass(target, "nodeValue"))
+            {
+                var attributeName = Dom.getPreviousByClass(target, "nodeName").textContent;
+                return element.getAttribute(attributeName);
+            }
+        }
+        return value;
     }
 });
 
diff --git a/trace/FBTrace/chrome/firebug/content/html/insideOutBox.js b/trace/FBTrace/chrome/firebug/content/html/insideOutBox.js
index a3ab406..51b5ab2 100644
--- a/trace/FBTrace/chrome/firebug/content/html/insideOutBox.js
+++ b/trace/FBTrace/chrome/firebug/content/html/insideOutBox.js
@@ -96,6 +96,7 @@ Firebug.InsideOutBox.prototype =
     {
         if (FBTrace.DBG_HTML)
             FBTrace.sysout("insideOutBox.select object:"+object, object);
+
         var objectBox = this.createObjectBox(object);
         this.selectObjectBox(objectBox, forceOpen);
 
diff --git a/trace/FBTrace/chrome/firebug/content/html/inspector.js b/trace/FBTrace/chrome/firebug/content/html/inspector.js
index 55e15ba..4b21ca1 100644
--- a/trace/FBTrace/chrome/firebug/content/html/inspector.js
+++ b/trace/FBTrace/chrome/firebug/content/html/inspector.js
@@ -8,6 +8,7 @@ define([
     "firebug/lib/locale",
     "firebug/lib/events",
     "firebug/lib/wrapper",
+    "firebug/lib/array",
     "firebug/lib/css",
     "firebug/lib/dom",
     "firebug/lib/xml",
@@ -15,7 +16,7 @@ define([
     "firebug/lib/system",
     "firebug/html/highlighterCache"
 ],
-function(Obj, Firebug, Firefox, FirebugReps, Locale, Events, Wrapper, Css, Dom, Xml,
+function(Obj, Firebug, Firefox, FirebugReps, Locale, Events, Wrapper, Arr, Css, Dom, Xml,
     Win, System, HighlighterCache) {
 
 // ********************************************************************************************* //
@@ -24,6 +25,7 @@ function(Obj, Firebug, Firefox, FirebugReps, Locale, Events, Wrapper, Css, Dom,
 const inspectDelay = 200;
 const highlightCSS = "chrome://firebug/content/html/highlighter.css";
 const ident = HighlighterCache.ident;
+const Cu = Components.utils;
 
 // ********************************************************************************************* //
 // Globals
@@ -70,7 +72,7 @@ Firebug.Inspector = Obj.extend(Firebug.Module,
         var i, elt, elementLen, oldContext, usingColorArray;
         var highlighter = highlightType ? getHighlighter(highlightType) : this.defaultHighlighter;
 
-        if (!elementArr || !FirebugReps.Arr.isArray(elementArr, context.window))
+        if (!elementArr || !Arr.isArrayLike(elementArr))
         {
             // highlight a single element
             if (!elementArr || !Dom.isElement(elementArr) ||
@@ -124,12 +126,6 @@ Firebug.Inspector = Obj.extend(Firebug.Module,
                     if (oldContext.window && oldContext.window.document)
                     {
                         highlighter.unhighlight(oldContext);
-
-                        if (oldContext.inspectorMouseMove)
-                        {
-                            Events.removeEventListener(oldContext.window.document, "mousemove",
-                                oldContext.inspectorMouseMove, true);
-                        }
                     }
                 }, inspectDelay);
             }
@@ -144,7 +140,7 @@ Firebug.Inspector = Obj.extend(Firebug.Module,
             }
 
             this.clearAllHighlights();
-            usingColorArray = FirebugReps.Arr.isArray(colorObj, context.window);
+            usingColorArray = Arr.isArray(colorObj);
 
             if (context && context.window && context.window.document)
             {
@@ -1244,19 +1240,19 @@ Firebug.Inspector.FrameHighlighter.prototype =
             {
                 cs = body.ownerDocument.defaultView.getComputedStyle(element, null);
 
-                if (cs.MozTransform && cs.MozTransform != "none")
-                    css += "-moz-transform: "+cs.MozTransform+"!important;" +
-                           "-moz-transform-origin: "+cs.MozTransformOrigin+"!important;";
+                if (cs.transform && cs.transform != "none")
+                    css += "transform: " + cs.transform + " !important;" +
+                           "transform-origin: " + cs.transformOrigin + " !important;";
                 if (cs.borderRadius)
-                    css += "border-radius: "+cs.borderRadius+"!important;";
+                    css += "border-radius: " + cs.borderRadius + " !important;";
                 if (cs.borderTopLeftRadius)
-                    css += "border-top-left-radius: "+cs.borderTopLeftRadius+"!important;";
+                    css += "border-top-left-radius: " + cs.borderTopLeftRadius + " !important;";
                 if (cs.borderTopRightRadius)
-                    css += "border-top-right-radius: "+cs.borderTopRightRadius+"!important;";
+                    css += "border-top-right-radius: " + cs.borderTopRightRadius + " !important;";
                 if (cs.borderBottomRightRadius)
-                    css += "border-bottom-right-radius: "+cs.borderBottomRightRadius+"!important;";
+                    css += "border-bottom-right-radius: " + cs.borderBottomRightRadius + " !important;";
                 if (cs.borderBottomLeftRadius)
-                    css += "border-bottom-left-radius: "+cs.borderBottomLeftRadius+"!important;";
+                    css += "border-bottom-left-radius: " + cs.borderBottomLeftRadius + " !important;";
             }
             css += "box-shadow: 0 0 2px 2px "+
                 (colorObj && colorObj.border ? colorObj.border : "highlight")+"!important;";
@@ -1640,12 +1636,25 @@ function getNonFrameBody(elt)
 
 function attachStyles(context, body)
 {
+    if (FBTrace.DBG_ERRORS && context.highlightStyle && Cu.isDeadWrapper(context.highlightStyle))
+        FBTrace.sysout("inspector.attachStyles; ERROR can't access dead object");
+
     var doc = body.ownerDocument;
+
     if (!context.highlightStyle)
         context.highlightStyle = Css.createStyleSheet(doc, highlightCSS);
 
-    if (!context.highlightStyle.parentNode || context.highlightStyle.ownerDocument != doc)
-        Css.addStyleSheet(body.ownerDocument, context.highlightStyle);
+    var parentNode = context.highlightStyle.parentNode;
+    if (!parentNode || context.highlightStyle.ownerDocument != doc)
+    {
+        // Clone the <style> element so, it doesn't adopt the new document as parent.
+        // The other doc (except of the original one that is always the top doc) comes
+        // from an iframe, which can be reloaded (within the context life-time) and
+        // consequent access to context.highlightStyle would fire "can't access dead object"
+        // exception (see issue 6013).
+        var style = parentNode ? context.highlightStyle.cloneNode(true) : context.highlightStyle;
+        Css.addStyleSheet(body.ownerDocument, style);
+    }
 }
 
 function createProxiesForDisabledElements(body)
@@ -1669,9 +1678,9 @@ function createProxiesForDisabledElements(body)
         div.className = "firebugResetStyles fbProxyElement";
 
         css = moveImp(null, rect.left, rect.top + body.scrollTop) + resizeImp(null, rect.width, rect.height);
-        if (cs.MozTransform && cs.MozTransform != "none")
-          css += "-moz-transform:" + cs.MozTransform + "!important;" +
-                 "-moz-transform-origin:" + cs.MozTransformOrigin + "!important;";
+        if (cs.transform && cs.transform != "none")
+            css += "transform:" + cs.transform + " !important;" +
+                   "transform-origin:" + cs.transformOrigin + " !important;";
         if (cs.borderRadius)
             css += "border-radius:" + cs.borderRadius + " !important;";
         if (cs.borderTopLeftRadius)
diff --git a/trace/FBTrace/chrome/firebug/content/html/layout.js b/trace/FBTrace/chrome/firebug/content/html/layout.js
index df2246f..b13a3c5 100644
--- a/trace/FBTrace/chrome/firebug/content/html/layout.js
+++ b/trace/FBTrace/chrome/firebug/content/html/layout.js
@@ -25,90 +25,170 @@ LayoutPanel.prototype = Obj.extend(Firebug.Panel,
     {
         tag:
             DIV({"class": "outerLayoutBox"},
-                DIV({"class": "positionLayoutBox $outerTopMode $outerRightMode $outerBottomMode $outerLeftMode focusGroup"},
+                DIV({"class": "positionLayoutBox $outerTopMode $outerRightMode $outerBottomMode "+
+                        "$outerLeftMode focusGroup"},
                     DIV({"class": "layoutEdgeTop layoutEdge"}),
                     DIV({"class": "layoutEdgeRight layoutEdge"}),
                     DIV({"class": "layoutEdgeBottom layoutEdge"}),
                     DIV({"class": "layoutEdgeLeft layoutEdge"}),
 
                     DIV({"class": "layoutLabelBottom layoutLabel layoutLabelPosition"},
-                            SPAN({"class": "layoutPosition layoutCaption",
-                                    "aria-label": Locale.$STR("a11y.layout.position")},
-                                Locale.$STR("position") + ": " + "$position"),
-                            SPAN({"class": "layoutBoxSizing layoutCaption",
-                                    "aria-label": Locale.$STR("a11y.layout.box-sizing")},
-                                Locale.$STR("a11y.layout.box-sizing") + ": " + "$boxSizing"),
-                            SPAN({"class": "layoutZIndex v$zIndex",
-                                    "aria-label": Locale.$STR("a11y.layout.z-index")},
-                                "z: " + "$zIndex")
+                        SPAN({"class": "layoutPosition layoutCaption",
+                                "aria-label": Locale.$STR("a11y.layout.position")},
+                            Locale.$STR("position") + ": " + "$position"),
+                        SPAN({"class": "layoutBoxSizing layoutCaption",
+                                "aria-label": Locale.$STR("a11y.layout.box-sizing")},
+                            Locale.$STR("a11y.layout.box-sizing") + ": " + "$boxSizing"),
+                        SPAN({"class": "layoutZIndex", $invisible: "$zIndex|isInvisible",
+                                "aria-label": Locale.$STR("a11y.layout.z-index")},
+                            "z: " + "$zIndex")
                     ),
 
-                    DIV({"class": "layoutLabelTop layoutLabel v$outerTop"},
-                        SPAN({"class": "editable focusStart", 'aria-label' : Locale.$STR('a11y.layout.position top')}, '$outerTop')
+                    DIV({"class": "layoutLabelTop layoutLabel",
+                            $invisible: "$outerTop|isInvisible"},
+                        SPAN({"class": "layoutLabelOuterTop editable focusStart",
+                                "aria-label": Locale.$STR("a11y.layout.position top")},
+                            "$outerTop"
+                        )
                     ),
-                    DIV({"class": "layoutLabelRight layoutLabel v$outerRight"},
-                        SPAN({"class": "editable", 'aria-label' : Locale.$STR('a11y.layout.position right')}, '$outerRight')
+                    DIV({"class": "layoutLabelRight layoutLabel",
+                            $invisible: "$outerRight|isInvisible"},
+                        SPAN({"class": "layoutLabelOuterRight editable",
+                                "aria-label": Locale.$STR("a11y.layout.position right")},
+                            "$outerRight"
+                        )
                     ),
-                    DIV({"class": "layoutLabelBottom layoutLabel v$outerBottom"},
-                        SPAN({"class": "editable", 'aria-label' : Locale.$STR('a11y.layout.position bottom')}, '$outerBottom')
+                    DIV({"class": "layoutLabelBottom layoutLabel",
+                            $invisible: "$outerBottom|isInvisible"},
+                        SPAN({"class": "layoutLabelOuterBottom editable",
+                                "aria-label": Locale.$STR("a11y.layout.position bottom")},
+                            "$outerBottom"
+                        )
                     ),
-                    DIV({"class": "layoutLabelLeft layoutLabel v$outerLeft"},
-                        SPAN({"class": "editable", 'aria-label' : Locale.$STR('a11y.layout.position left')}, '$outerLeft')
+                    DIV({"class": "layoutLabelLeft layoutLabel",
+                            $invisible: "$outerLeft|isInvisible"},
+                        SPAN({"class": "layoutLabelOuterLeft editable",
+                                "aria-label": Locale.$STR("a11y.layout.position left")},
+                            "$outerLeft"
+                        )
                     ),
 
-                    DIV({"class": "layoutCaption"}, '$outerLabel'),
+                    DIV({"class": "outerLabel layoutCaption"}, "$outerLabel"),
 
 
                     DIV({"class": "marginLayoutBox layoutBox editGroup focusGroup"},
                         DIV({"class": "layoutCaption"}, Locale.$STR("LayoutMargin")),
-                        DIV({"class": "layoutLabelTop layoutLabel v$marginTop"},
-                            SPAN({"class": "editable focusStart", 'aria-label' : Locale.$STR('a11y.layout.margin top')}, '$marginTop')
+                        DIV({"class": "layoutLabelTop layoutLabel",
+                                $invisible: "$marginTop|isInvisible"},
+                            SPAN({"class": "layoutLabelMarginTop editable focusStart",
+                                    "aria-label": Locale.$STR("a11y.layout.margin top")},
+                                "$marginTop"
+                            )
                         ),
-                        DIV({"class": "layoutLabelRight layoutLabel v$marginRight"},
-                            SPAN({"class": "editable", 'aria-label' : Locale.$STR('a11y.layout..margin right')}, '$marginRight')
+                        DIV({"class": "layoutLabelRight layoutLabel",
+                                $invisible: "$marginRight|isInvisible"},
+                            SPAN({"class": "layoutLabelMarginRight editable",
+                                    "aria-label": Locale.$STR("a11y.layout.margin right")},
+                                "$marginRight"
+                            )
                         ),
-                        DIV({"class": "layoutLabelBottom layoutLabel v$marginBottom"},
-                            SPAN({"class": "editable", 'aria-label' : Locale.$STR('a11y.layout.margin bottom')}, '$marginBottom')
+                        DIV({"class": "layoutLabelBottom layoutLabel",
+                                $invisible: "$marginBottom|isInvisible"},
+                            SPAN({"class": "layoutLabelMarginBottom editable",
+                                    "aria-label": Locale.$STR("a11y.layout.margin bottom")},
+                                "$marginBottom"
+                            )
                         ),
-                        DIV({"class": "layoutLabelLeft layoutLabel v$marginLeft"},
-                            SPAN({"class": "editable", 'aria-label' : Locale.$STR('a11y.layout.margin left')}, '$marginLeft')
+                        DIV({"class": "layoutLabelLeft layoutLabel",
+                                $invisible: "$marginLeft|isInvisible"},
+                            SPAN({"class": "layoutLabelMarginLeft editable",
+                                    "aria-label": Locale.$STR("a11y.layout.margin left")},
+                                "$marginLeft"
+                            )
                         ),
 
                         DIV({"class": "borderLayoutBox layoutBox editGroup focusGroup"},
                             DIV({"class": "layoutCaption"}, Locale.$STR("LayoutBorder")),
-                            DIV({"class": "layoutLabelTop layoutLabel v$borderTop"},
-                                SPAN({"class": "editable  focusStart", 'aria-label' : Locale.$STR('a11y.layout.border top')}, '$borderTop')
+                            DIV({"class": "layoutLabelTop layoutLabel",
+                                    $invisible: "$borderTop|isInvisible"},
+                                SPAN({"class": "layoutLabelBorderTop editable  focusStart",
+                                        "aria-label": Locale.$STR("a11y.layout.border top")},
+                                    "$borderTop"
+                                )
                             ),
-                            DIV({"class": "layoutLabelRight layoutLabel v$borderRight"},
-                                SPAN({"class": "editable", 'aria-label' : Locale.$STR('a11y.layout.border right')}, '$borderRight')
+                            DIV({"class": "layoutLabelRight layoutLabel",
+                                    $invisible: "$borderRight|isInvisible"},
+                                SPAN({"class": "layoutLabelBorderRight editable",
+                                        "aria-label": Locale.$STR("a11y.layout.border right")},
+                                    "$borderRight"
+                                )
                             ),
-                            DIV({"class": "layoutLabelBottom layoutLabel v$borderBottom"},
-                                SPAN({"class": "editable", 'aria-label' : Locale.$STR('a11y.layout.border bottom')}, '$borderBottom')
+                            DIV({"class": "layoutLabelBottom layoutLabel",
+                                    $invisible: "$borderBottom|isInvisible"},
+                                SPAN({"class": "layoutLabelBorderBottom editable",
+                                        "aria-label": Locale.$STR("a11y.layout.border bottom")},
+                                    "$borderBottom"
+                                )
                             ),
-                            DIV({"class": "layoutLabelLeft layoutLabel v$borderLeft"},
-                                SPAN({"class": "editable", 'aria-label' : Locale.$STR('a11y.layout.border left')}, '$borderLeft')
+                            DIV({"class": "layoutLabelLeft layoutLabel",
+                                    $invisible: "$borderLeft|isInvisible"},
+                                SPAN({"class": "layoutLabelBorderLeft editable",
+                                        "aria-label": Locale.$STR("a11y.layout.border left")},
+                                    "$borderLeft"
+                                )
                             ),
 
                             DIV({"class": "paddingLayoutBox layoutBox editGroup focusGroup"},
                                 DIV({"class": "layoutCaption"}, Locale.$STR("LayoutPadding")),
-                                DIV({"class": "layoutLabelTop layoutLabel v$paddingTop"},
-                                    SPAN({"class": "editable focusStart", 'aria-label' : Locale.$STR('a11y.layout.padding top')}, '$paddingTop')
+                                DIV({"class": "layoutLabelTop layoutLabel",
+                                        $invisible: "$paddingTop|isInvisible"},
+                                    SPAN({"class": "layoutLabelPaddingTop editable focusStart",
+                                            "aria-label": Locale.$STR("a11y.layout.padding top")},
+                                        "$paddingTop"
+                                    )
                                 ),
-                                DIV({"class": "layoutLabelRight layoutLabel v$paddingRight"},
-                                    SPAN({"class": "editable", 'aria-label' : Locale.$STR('a11y.layout.padding right')}, '$paddingRight')
+                                DIV({"class": "layoutLabelRight layoutLabel",
+                                        $invisible: "$paddingRight|isInvisible"},
+                                    SPAN(
+                                        {
+                                            "class": "layoutLabelPaddingRight editable",
+                                            "aria-label":
+                                                Locale.$STR("a11y.layout.padding right")
+                                        },
+                                        "$paddingRight"
+                                    )
                                 ),
-                                DIV({"class": "layoutLabelBottom layoutLabel v$paddingBottom"},
-                                    SPAN({"class": "editable", 'aria-label' : Locale.$STR('a11y.layout.padding bottom')}, '$paddingBottom')
+                                DIV({"class": "layoutLabelBottom layoutLabel",
+                                        $invisible: "$paddingBottom|isInvisible"},
+                                    SPAN(
+                                        {
+                                            "class": "layoutLabelPaddingBottom editable",
+                                            "aria-label":
+                                                Locale.$STR("a11y.layout.padding bottom")
+                                        },
+                                        "$paddingBottom"
+                                    )
                                 ),
-                                DIV({"class": "layoutLabelLeft layoutLabel v$paddingLeft"},
-                                    SPAN({"class": "editable", 'aria-label' : Locale.$STR('a11y.layout.padding left')}, '$paddingLeft')
+                                DIV({"class": "layoutLabelLeft layoutLabel",
+                                        $invisible: "$paddingLeft|isInvisible"},
+                                    SPAN({"class": "layoutLabelPaddingLeft editable",
+                                            "aria-label": Locale.$STR("a11y.layout.padding left")},
+                                        "$paddingLeft"
+                                    )
                                 ),
 
                                 DIV({"class": "contentLayoutBox layoutBox editGroup focusGroup"},
                                     DIV({"class": "layoutLabelCenter layoutLabel"},
-                                        SPAN({"class": "layoutLabelWidth layoutLabel editable focusStart", 'aria-label' : Locale.$STR('a11y.layout.width')}, '$width'),
+                                        SPAN({"class": "layoutLabelWidth layoutLabel editable "+
+                                                "focusStart",
+                                                "aria-label": Locale.$STR("a11y.layout.width")},
+                                            "$width"
+                                        ),
                                         " x ",
-                                        SPAN({"class": "layoutLabelHeight layoutLabel editable", 'aria-label' : Locale.$STR('a11y.layout.height')}, '$height')
+                                        SPAN({"class": "layoutLabelHeight layoutLabel editable",
+                                                "aria-label": Locale.$STR("a11y.layout.height")},
+                                            "$height"
+                                        )
                                     )
                                 )
                             )
@@ -117,6 +197,11 @@ LayoutPanel.prototype = Obj.extend(Firebug.Panel,
                 )
             ),
 
+        isInvisible: function(value)
+        {
+            return value == 0;
+        },
+
         getVerticalText: function(n)
         {
             return getVerticalText(n);
@@ -167,6 +252,7 @@ LayoutPanel.prototype = Obj.extend(Firebug.Panel,
     {
         this.onMouseOver = Obj.bind(this.onMouseOver, this);
         this.onMouseOut = Obj.bind(this.onMouseOut, this);
+        this.onAfterPaint = Obj.bindFixed(this.refresh, this);
 
         Firebug.Panel.initialize.apply(this, arguments);
     },
@@ -187,6 +273,16 @@ LayoutPanel.prototype = Obj.extend(Firebug.Panel,
         Firebug.Panel.destroyNode.apply(this, arguments);
     },
 
+    show: function(state)
+    {
+        Events.addEventListener(this.context.browser, "MozAfterPaint", this.onAfterPaint, true);
+    },
+
+    hide: function()
+    {
+        Events.removeEventListener(this.context.browser, "MozAfterPaint", this.onAfterPaint, true);
+    },
+    
     supportsObject: function(object, type)
     {
         return object instanceof window.Element ? 1 : 0;
@@ -201,14 +297,12 @@ LayoutPanel.prototype = Obj.extend(Firebug.Panel,
     {
         var view = element ? element.ownerDocument.defaultView : null;
         if (!view)
-            return this.panelNode.innerHTML = "";
+            return this.panelNode.textContent = "";
 
         var prev = Dom.getPreviousElement(element.previousSibling);
         var next = Dom.getNextElement(element.nextSibling);
 
         var style = view.getComputedStyle(element, "");
-        var prevStyle = prev ? view.getComputedStyle(prev, "") : null;
-        var nextStyle = next ? view.getComputedStyle(next, "") : null;
 
         var args = Css.getBoxFromStyles(style, element);
 
@@ -222,7 +316,7 @@ LayoutPanel.prototype = Obj.extend(Firebug.Panel,
 
         var position = style.getPropertyCSSValue("position").cssText;
         args.position = position;
-        args.outerLabel = '';
+        args.outerLabel = "";
 
         if (Xml.isElementSVG(element) || Xml.isElementMathML(element) || Xml.isElementXUL(element))
         {
@@ -236,28 +330,86 @@ LayoutPanel.prototype = Obj.extend(Firebug.Panel,
         }
 
         // these Modes are classes on the domplate
-        args.outerLeftMode = args.outerRightMode = args.outerTopMode
-        = args.outerBottomMode = "blankEdge";
+        args.outerLeftMode = args.outerRightMode = args.outerTopMode = args.outerBottomMode =
+            "blankEdge";
 
         if (position == "absolute" || position == "fixed" || position == "relative")
         {
-            function getStyle(style, name) { var v = style.getPropertyCSSValue(name); return (v && v.cssText) ? parseInt(v.cssText) : ' '; }
+            function getStyle(style, name)
+            {
+                var value = style.getPropertyCSSValue(name);
+                return value && value.cssText ? parseInt(value.cssText) : " ";
+            }
 
             args.outerLabel = Locale.$STR("LayoutPosition");
 
-            args.outerLeft = getStyle(style,'left');
-            args.outerTop = getStyle(style,'top');
-            args.outerRight = getStyle(style,'right');
-            args.outerBottom = getStyle(style,'bottom');
+            args.outerLeft = getStyle(style, "left");
+            args.outerTop = getStyle(style, "top");
+            args.outerRight = getStyle(style, "right");
+            args.outerBottom = getStyle(style, "bottom");
 
-            args.outerLeftMode = args.outerRightMode = args.outerTopMode
-                = args.outerBottomMode = "absoluteEdge";
+            args.outerLeftMode = args.outerRightMode = args.outerTopMode = args.outerBottomMode =
+                "absoluteEdge";
+        }
+
+        var node;
+        // If the layout panel content was already created, just fill in the new values
+        if (this.panelNode.getElementsByClassName("outerLayoutBox").item(0))
+        {
+            // The styles for the positionLayoutBox need to be set manually
+            var positionLayoutBox = this.panelNode.getElementsByClassName("positionLayoutBox").
+                item(0);
+            positionLayoutBox.className = "positionLayoutBox "+args.outerTopMode+" "+
+                args.outerRightMode+" "+args.outerBottomMode+" "+args.outerLeftMode+" focusGroup";
+
+            var values =
+            {
+                layoutPosition: {label: Locale.$STR("position"), value: "position"},
+                layoutBoxSizing: {label: Locale.$STR("a11y.layout.box-sizing"),
+                    value: "boxSizing"},
+                layoutZIndex: {label: "z", value: "zIndex"},
+                layoutLabelOuterTop: {value: "outerTop"},
+                layoutLabelOuterRight: {value: "outerRight"},
+                layoutLabelOuterBottom: {value: "outerBottom"},
+                layoutLabelOuterLeft: {value: "outerLeft"},
+                layoutLabelMarginTop: {value: "marginTop"},
+                layoutLabelMarginRight: {value: "marginRight"},
+                layoutLabelMarginBottom: {value: "marginBottom"},
+                layoutLabelMarginLeft: {value: "marginLeft"},
+                layoutLabelBorderTop: {value: "borderTop"},
+                layoutLabelBorderRight: {value: "borderRight"},
+                layoutLabelBorderBottom: {value: "borderBottom"},
+                layoutLabelBorderLeft: {value: "borderLeft"},
+                layoutLabelPaddingTop: {value: "paddingTop"},
+                layoutLabelPaddingRight: {value: "paddingRight"},
+                layoutLabelPaddingBottom: {value: "paddingBottom"},
+                layoutLabelPaddingLeft: {value: "paddingLeft"},
+                layoutLabelWidth: {value: "width"},
+                layoutLabelHeight: {value: "height"},
+                outerLabel: {value: "outerLabel"},
+            }
+
+            for (val in values)
+            {
+                var element = this.panelNode.getElementsByClassName(val).item(0);
+
+                element.textContent = values[val].label ?
+                    values[val].label+": "+args[values[val].value] : args[values[val].value];
+
+                if (this.template.isInvisible(args[values[val].value]))
+                    Css.setClass(element.parentNode, "invisible");
+                else
+                    Css.removeClass(element.parentNode, "invisible");
+            }
+        }
+        else
+        {
+            node = this.template.tag.replace(args, this.panelNode);
         }
 
-        var node = this.template.tag.replace(args, this.panelNode);
         this.adjustCharWidth(this.getMaxCharWidth(args, node), this.panelNode);
 
-        Events.dispatch(this.fbListeners, 'onLayoutBoxCreated', [this, node, args]);
+        Events.dispatch(this.fbListeners, "onLayoutBoxCreated", [this, node, args]);
     },
 
     /*
@@ -295,7 +447,7 @@ LayoutPanel.prototype = Obj.extend(Firebug.Panel,
     adjustBoxWidth: function(node, boxName, width)
     {
         var box = node.getElementsByClassName(boxName).item(0);
-        box.style.cssText = "right: "+width + 'px;'+" left: "+width + 'px;';
+        box.style.cssText = "right: "+width + 'px;'+" left: "+width + "px;";
     },
 
     getMaxCharWidth: function(args, node)
@@ -374,12 +526,7 @@ LayoutEditor.prototype = domplate(Firebug.InlineEditor.prototype,
         if (Css.hasClass(target, "layoutVerticalText"))
             target.innerHTML = getVerticalText(intValue);
         else
-            target.innerHTML = intValue;
-
-        if (previousValue == "0" && !!value)
-            Css.removeClass(target.parentNode, "v0");
-        else if (!value)
-            Css.setClass(target.parentNode, "v0");
+            target.textContent = intValue;
     },
 
     endEditing: function(target, value, cancel)
diff --git a/trace/FBTrace/chrome/firebug/content/js/breakpoint.js b/trace/FBTrace/chrome/firebug/content/js/breakpoint.js
index 86630fa..1e0473b 100644
--- a/trace/FBTrace/chrome/firebug/content/js/breakpoint.js
+++ b/trace/FBTrace/chrome/firebug/content/js/breakpoint.js
@@ -108,8 +108,7 @@ Firebug.Breakpoint = Obj.extend(Firebug.Module,
         var menuPopup = Firebug.chrome.$("fbBreakOnNextOptions");
         Dom.eraseNode(menuPopup);
 
-        for (var i=0; i<menuItems.length; ++i)
-            Menu.createMenuItem(menuPopup, menuItems[i]);
+        Menu.createMenuItems(menuPopup, menuItems);
     },
 
     /* see issue 5618
diff --git a/trace/FBTrace/chrome/firebug/content/js/debugger.js b/trace/FBTrace/chrome/firebug/content/js/debugger.js
index 1190364..810c673 100644
--- a/trace/FBTrace/chrome/firebug/content/js/debugger.js
+++ b/trace/FBTrace/chrome/firebug/content/js/debugger.js
@@ -124,7 +124,7 @@ Firebug.Debugger = Obj.extend(Firebug.ActivableModule,
 
     /**
      * Used by autocomplete in commandLine
-     * @return array of global property names
+     * @return array of locally visible property names for each scope we are in
      */
     getCurrentFrameKeys: function(context)  // TODO remote, on bti
     {
@@ -151,11 +151,6 @@ Firebug.Debugger = Obj.extend(Firebug.ActivableModule,
             {
                 var prop = listValue.value[i];
                 var name = Wrapper.unwrapIValue(prop.name);
-
-                // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=712289.
-                if (typeof name !== "string")
-                    break;
-
                 names.push(name);
             }
 
@@ -2561,58 +2556,11 @@ Firebug.Debugger = Obj.extend(Firebug.ActivableModule,
         }
         */
 
-        // context.watchScriptAdditions = Obj.bind(this.watchScriptAdditions, this, context);
-        // context.window.document.addEventListener("DOMNodeInserted", context.watchScriptAdditions, false);
-
         if (FBTrace.DBG_SOURCEFILES)
             FBTrace.sysout("debugger("+this.debuggerName+").loadedContext enabled on load: "+
                 context.onLoadWindowContent+" context.sourceFileMap", context.sourceFileMap);
     },
 
-    /*
-     * A DOM Mutation Event handler for script tag additions
-     * FAILS see http://code.google.com/p/fbug/issues/detail?id=2912
-     */
-    watchScriptAdditions: function(event, context)
-    {
-        if (event.type !== "DOMNodeInserted")
-            return;
-
-        if (event.target.tagName.toLowerCase() !== "script")
-            return;
-
-        FBTrace.sysout("debugger.watchScriptAdditions ", event.target.innerHTML);
-        var location = Win.safeGetWindowLocation(context.window);
-
-        jsd.enumerateScripts({enumerateScript: function(script)
-        {
-            if (Url.normalizeURL(script.fileName) === location)
-            {
-                var sourceFile = Firebug.SourceFile.getSourceFileByScript(context, script);
-                FBTrace.sysout('debugger.watchScriptAdditions '+script.tag+" in "+
-                    (sourceFile?sourceFile.href:"NONE")+" "+script.functionSource,
-                    script.functionSource);
-                // The dynamically added script tags via element.appendChild do not show up.
-            }
-        }});
-
-        if (context.pendingScriptTagSourceFile)
-        {
-            var sourceFile = context.pendingScriptTagSourceFile;
-            sourceFile.scriptTag = event.target;
-            sourceFile.source = Str.splitLines(event.target.innerHTML);
-
-            var panel = context.getPanel("script", true);
-            if (panel)
-                panel.removeSourceBoxBySourceFile(sourceFile);
-
-            FBTrace.sysout("debugger.watchScriptAdditions connected tag to sourcefile",
-                sourceFile);
-
-            delete context.pendingScriptTagSourceFile;
-        }
-    },
-
     // clean up the source file map in case the frame is being reloaded.
     unwatchWindow: function(context, win)
     {
@@ -2639,9 +2587,6 @@ Firebug.Debugger = Obj.extend(Firebug.ActivableModule,
     {
         Firebug.ActivableModule.destroyContext.apply(this, arguments);
 
-        Events.removeEventListener(context.window.document, "DOMNodeInserted",
-            context.watchScriptAdditions, false);
-
         if (context.stopped)
         {
             // the abort will call resume, but the nestedEventLoop would continue the load...
@@ -2728,11 +2673,6 @@ Firebug.Debugger = Obj.extend(Firebug.ActivableModule,
         if (this.hasObservers())
         {
             this.activateDebugger();
-
-            // bug712289, do not display the activation message if JSD is not available
-            if (!FBS.isJSDAvailable())
-                return;
-
             if (Firebug.currentContext)
             {
                 var name = observer.name || observer.dispatchName || observer.toolName;
diff --git a/trace/FBTrace/chrome/firebug/content/js/scriptPanel.js b/trace/FBTrace/chrome/firebug/content/js/scriptPanel.js
index 96ee531..d27112a 100644
--- a/trace/FBTrace/chrome/firebug/content/js/scriptPanel.js
+++ b/trace/FBTrace/chrome/firebug/content/js/scriptPanel.js
@@ -22,7 +22,6 @@ define([
     "firebug/chrome/menu",
     "firebug/trace/debug",
     "firebug/lib/keywords",
-    "firebug/js/fbs",   // bug712289
     "firebug/editor/editorSelector",
     "firebug/chrome/infotip",
     "firebug/chrome/searchBox",
@@ -31,7 +30,7 @@ define([
 ],
 function (Obj, Firebug, Firefox, FirebugReps, Domplate, JavaScriptTool, CompilationUnit,
     Locale, Events, Url, SourceLink, StackFrame, Css, Dom, Win, Search, Persist,
-    System, Menu, Debug, Keywords, FBS) {
+    System, Menu, Debug, Keywords) {
 
 // ********************************************************************************************* //
 // Script panel
@@ -170,7 +169,13 @@ Firebug.ScriptPanel.prototype = Obj.extend(Firebug.SourceBoxPanel,
         // Front side UI mark
         var firebugStatus = Firefox.getElementById("firebugStatus");
         if (firebugStatus)
-            firebugStatus.setAttribute("script", active ? "on" : "off");
+        {
+            // Use enabled state for the status flag. JSD can be active even if
+            // the Script panel itself is deactivated (i.e. because the Console
+            // panel is enabled). See issue 2582 for more details.
+            var enabled = this.isEnabled();
+            firebugStatus.setAttribute("script", (enabled && active) ? "on" : "off");
+        }
 
         if (Firebug.StartButton)
             Firebug.StartButton.resetTooltip();
@@ -182,8 +187,8 @@ Firebug.ScriptPanel.prototype = Obj.extend(Firebug.SourceBoxPanel,
 
         if (FBTrace.DBG_ACTIVATION)
         {
-            FBTrace.sysout("script.onJavaScriptDebugging "+active+" icon attribute: "+
-                Firefox.getElementById('firebugStatus').getAttribute("script"));
+            FBTrace.sysout("script.onJavaScriptDebugging " + active + " icon attribute: " +
+                Firefox.getElementById("firebugStatus").getAttribute("script"));
         }
     },
 
@@ -908,6 +913,7 @@ Firebug.ScriptPanel.prototype = Obj.extend(Firebug.SourceBoxPanel,
         this.showToolbarButtons("fbLocationButtons", active);
         this.showToolbarButtons("fbScriptButtons", active);
         this.showToolbarButtons("fbStatusButtons", active);
+        this.showToolbarButtons("fbLocationList", active);
 
         Firebug.chrome.$("fbRerunButton").setAttribute("tooltiptext",
             Locale.$STRF("firebug.labelWithShortcut", [Locale.$STR("script.Rerun"), "Shift+F8"]));
@@ -1377,8 +1383,14 @@ Firebug.ScriptPanel.prototype = Obj.extend(Firebug.SourceBoxPanel,
     optionMenu: function(label, option)
     {
         var checked = Firebug.Options.get(option);
-        return {label: label, type: "checkbox", checked: checked,
-            command: Obj.bindFixed(Firebug.Options.set, Firebug, option, !checked) };
+        return {
+            label: label, type: "checkbox", checked: checked,
+            command: function()
+            {
+                var checked = this.hasAttribute("checked");
+                Firebug.Options.set(option, checked)
+            }
+        };
     },
 
     getContextMenuItems: function(fn, target)
@@ -1569,27 +1581,6 @@ Firebug.ScriptPanel.prototype = Obj.extend(Firebug.SourceBoxPanel,
         this.onJavaScriptDebugging(isActive, "onActiveTool");
     },
 
-    setEnabled: function(enable)
-    {
-        // bug712289
-        if (!FBS.isJSDAvailable())
-        {
-            Firebug.SourceBoxPanel.setEnabled.apply(this, [false]);
-            return;
-        }
-
-        Firebug.SourceBoxPanel.setEnabled.apply(this, arguments);
-    },
-
-    isPanelEnabled: function(panelType)
-    {
-        // bug712289
-        if (!FBS.isJSDAvailable())
-            return false;
-
-        return Firebug.SourceBoxPanel.isPanelEnabled.apply(this, arguments);
-    },
-
     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
     // Toolbar functions
 
@@ -1992,4 +1983,4 @@ Firebug.registerPanel(Firebug.ScriptPanel);
 return Firebug.ScriptPanel;
 
 // ********************************************************************************************* //
-});
\ No newline at end of file
+});
diff --git a/trace/FBTrace/chrome/firebug/content/js/sourceCache.js b/trace/FBTrace/chrome/firebug/content/js/sourceCache.js
index a32d943..2f22f25 100644
--- a/trace/FBTrace/chrome/firebug/content/js/sourceCache.js
+++ b/trace/FBTrace/chrome/firebug/content/js/sourceCache.js
@@ -170,7 +170,10 @@ Firebug.SourceCache.prototype = Obj.extend(new Firebug.Listener(),
 
     removeAnchor: function(url)
     {
-        var index = url.indexOf("#");
+        if (FBTrace.DBG_ERRORS && !url)
+            FBTrace.sysout("sourceCache.removeAnchor; ERROR url must not be null");
+
+        var index = url ? url.indexOf("#") : -1;
         if (index < 0)
             return url;
 
diff --git a/trace/FBTrace/chrome/firebug/content/js/tabCache.js b/trace/FBTrace/chrome/firebug/content/js/tabCache.js
index a9ddd37..b7df9da 100644
--- a/trace/FBTrace/chrome/firebug/content/js/tabCache.js
+++ b/trace/FBTrace/chrome/firebug/content/js/tabCache.js
@@ -27,7 +27,7 @@ const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 const ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
-const prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch2);
+const prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
 const versionChecker = Cc["@mozilla.org/xpcom/version-comparator;1"].getService(Ci.nsIVersionComparator);
 const appInfo = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo);
 
@@ -64,6 +64,8 @@ var contentTypes =
     "application/xhtml+xml": 1,
     "application/atom+xml": 1,
     "application/rss+xml": 1,
+    "application/mathml+xml": 1,
+    "application/rdf+xml": 1,
     "application/vnd.mozilla.maybe.feed": 1,
     "application/vnd.mozilla.xul+xml": 1,
     "application/javascript": 1,
diff --git a/trace/FBTrace/chrome/firebug/content/js/watchPanel.js b/trace/FBTrace/chrome/firebug/content/js/watchPanel.js
index 2b535f3..b9d0a2a 100644
--- a/trace/FBTrace/chrome/firebug/content/js/watchPanel.js
+++ b/trace/FBTrace/chrome/firebug/content/js/watchPanel.js
@@ -2,6 +2,7 @@
 
 define([
     "firebug/lib/object",
+    "firebug/chrome/firefox",
     "firebug/firebug",
     "firebug/dom/toggleBranch",
     "firebug/lib/events",
@@ -12,7 +13,7 @@ define([
     "firebug/lib/string",
     "firebug/dom/domPanel",     // Firebug.DOMBasePanel, Firebug.DOMPanel.DirTable
 ],
-function(Obj, Firebug, ToggleBranch, Events, Dom, Css, StackFrame, Locale, Str) {
+function(Obj, Firefox, Firebug, ToggleBranch, Events, Dom, Css, StackFrame, Locale, Str) {
 
 // ********************************************************************************************* //
 // Watch Panel
@@ -188,8 +189,17 @@ Firebug.WatchPanel.prototype = Obj.extend(Firebug.DOMBasePanel.prototype,
 
     showEmptyMembers: function()
     {
-        this.tag.replace({domPanel: this, toggles: new ToggleBranch.ToggleBranch()},
+        var domTable = this.tag.replace({domPanel: this, toggles: new ToggleBranch.ToggleBranch()},
             this.panelNode);
+
+        // The direction needs to be adjusted according to the direction
+        // of the user agent. See issue 5073.
+        // TODO: Set the direction at the <body> to allow correct formatting of all relevant parts.
+        // This requires more adjustments related for rtl user agents.
+        var mainFrame = Firefox.getElementById("fbMainFrame");
+        var cs = mainFrame.ownerDocument.defaultView.getComputedStyle(mainFrame);
+        var watchRow = domTable.getElementsByClassName("watchNewRow").item(0);
+        watchRow.style.direction = cs.direction;
     },
 
     addWatch: function(expression)
@@ -260,6 +270,19 @@ Firebug.WatchPanel.prototype = Obj.extend(Firebug.DOMBasePanel.prototype,
         }, this));
     },
 
+    // deletes all the watches
+    deleteAllWatches: function()
+    {
+        if (FBTrace.DBG_WATCH)
+            FBTrace.sysout("Firebug.WatchPanel.deleteAllWatches");
+        this.watches = [];
+        this.rebuild(true);
+        this.context.setTimeout(Obj.bindFixed(function()
+        {
+            this.showToolbox(null);
+        }, this));
+    },
+
     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
     showToolbox: function(row)
@@ -348,6 +371,7 @@ Firebug.WatchPanel.prototype = Obj.extend(Firebug.DOMBasePanel.prototype,
         if (!path || !path.length)
             return;
 
+
         // Ignore top level variables in the Watch panel.
         if (panel.name == "watches" && path.length == 1)
             return;
@@ -359,6 +383,37 @@ Firebug.WatchPanel.prototype = Obj.extend(Firebug.DOMBasePanel.prototype,
            command: Obj.bindFixed(this.addWatch, this, path.join(""))
         });
     },
+
+    getContextMenuItems: function(object, target)
+    {
+        var items = Firebug.DOMBasePanel.prototype.getContextMenuItems.apply(this, arguments);
+
+        if (!this.watches || this.watches.length == 0)
+            return items;
+
+        // find the index of "DeletePropery" in the items:
+        var deleteWatchIndex = items.map(function(item)
+        {
+            return item.id;
+        }).indexOf("DeleteProperty");
+
+        // if DeleteWatch was found, we insert DeleteAllWatches after it
+        // otherwise, we insert the item at the beginning of the menu
+        var deleteAllWatchesIndex = (deleteWatchIndex >= 0) ? deleteWatchIndex + 1 : 0;
+
+        if (FBTrace.DBG_WATCH)
+            FBTrace.sysout("insert DeleteAllWatches at: "+ deleteAllWatchesIndex);
+
+        // insert DeleteAllWatches after DeleteWatch
+        items.splice(deleteAllWatchesIndex, 0, {
+            id: "fbDeleteAllWatches",
+            label: "DeleteAllWatches",
+            tooltiptext: "watch.tip.Delete_All_Watches",
+            command: Obj.bindFixed(this.deleteAllWatches, this)
+        });
+
+        return items;
+    }
 });
 
 // ********************************************************************************************* //
diff --git a/trace/FBTrace/chrome/firebug/content/lib/array.js b/trace/FBTrace/chrome/firebug/content/lib/array.js
index b93d865..724683d 100644
--- a/trace/FBTrace/chrome/firebug/content/lib/array.js
+++ b/trace/FBTrace/chrome/firebug/content/lib/array.js
@@ -8,18 +8,41 @@ function(FBTrace) {
 // ********************************************************************************************* //
 // Constants
 
+const Ci = Components.interfaces;
 var Arr = {};
 
 // ********************************************************************************************* //
 // Arrays
 
-Arr.isArray = function(obj)
+Arr.isArray = Array.isArray || function(obj)
 {
-    if (Array.isArray)
-        return Array.isArray(obj);
-
     return Object.prototype.toString.call(obj) === "[object Array]";
-}
+};
+
+Arr.isArrayLike = function(obj)
+{
+    try
+    {
+        if (typeof obj !== "object")
+            return false;
+        if (!isFinite(obj.length))
+            return false;
+        if (Arr.isArray(obj))
+            return true;
+        if (typeof obj.callee === "function") // arguments
+            return true;
+        if (typeof obj.splice === "function") // jQuery etc.
+            return true;
+        if (obj instanceof Ci.nsIDOMHTMLCollection)
+            return true;
+        if (obj instanceof Ci.nsIDOMNodeList)
+            return true;
+        if (obj instanceof Ci.nsIDOMDOMTokenList)
+            return true;
+    }
+    catch (exc) {}
+    return false;
+};
 
 // At least sometimes the keys will be on user-level window objects
 Arr.keys = function(map)
@@ -91,13 +114,13 @@ Arr.sliceArray = function(array, index)
 
 Arr.cloneArray = function(array, fn)
 {
-   var newArray = [];
+   var newArray = [], len = array.length;
 
    if (fn)
-       for (var i = 0; i < array.length; ++i)
+       for (var i = 0; i < len; ++i)
            newArray.push(fn(array[i]));
    else
-       for (var i = 0; i < array.length; ++i)
+       for (var i = 0; i < len; ++i)
            newArray.push(array[i]);
 
    return newArray;
diff --git a/trace/FBTrace/chrome/firebug/content/lib/css.js b/trace/FBTrace/chrome/firebug/content/lib/css.js
index c1c1794..d1f449c 100644
--- a/trace/FBTrace/chrome/firebug/content/lib/css.js
+++ b/trace/FBTrace/chrome/firebug/content/lib/css.js
@@ -113,6 +113,68 @@ Css.getCSSShorthandCategory = function(nodeType, shorthandProp, keyword)
     return category;
 };
 
+/**
+ * Parses the CSS properties of a CSSStyleRule
+ * @param {Object} style CSSStyleRule to get the properties of
+ * @param {Object} element Element to which the style applies. Needed for parsing shorthand properties correctly.
+ * @returns {Array} Properties represented by {name, value, priority, longhandProps}
+ */
+Css.parseCSSProps = function(style, element)
+{
+    var props = [];
+
+    if (!element)
+    {
+        for (var i = 0, len = style.length; i < len; ++i)
+        {
+            var prop = style.item(i);
+            props.push({name: prop,
+                value: style.getPropertyValue(prop),
+                priority: style.getPropertyPriority(longhandProp)});
+        }
+    }
+    else
+    {
+        var lineRE = /(?:[^;\(]*(?:\([^\)]*?\))?[^;\(]*)*;?/g;
+        var propRE = /\s*([^:\s]*)\s*:\s*(.*?)\s*(?:! (important))?;?$/;
+        var lines = style.cssText.match(lineRE);
+        for (var i = 0, len = lines.length; i < len; ++i)
+        {
+            var match = propRE.exec(lines[i]);
+            if (!match)
+                continue;
+
+            if (match[2])
+            {
+                var prop = {name: match[1], value: match[2], priority: match[3] || ""};
+
+                // Add longhand properties to shorthand property
+                var doc = element.ownerDocument;
+                var dummyElement = doc.createElementNS(element.namespaceURI, element.tagName);
+                var dummyStyle = dummyElement.style;
+                dummyStyle.cssText = "";
+                dummyStyle.setProperty(prop.name, prop.value, prop.priority);
+
+                if (dummyStyle.length > 1)
+                {
+                    prop.longhandProps = [];
+                    for (var j = 0, propLen = dummyStyle.length; j < propLen; ++j)
+                    {
+                        var longhandProp = dummyStyle.item(j);
+                        prop.longhandProps.push({name: longhandProp,
+                            value: dummyStyle.getPropertyValue(longhandProp),
+                            priority: dummyStyle.getPropertyPriority(longhandProp)});
+                    }
+                }
+
+                props.push(prop);
+            }
+        }
+    }
+
+    return props;
+};
+
 Css.isColorKeyword = function(keyword)
 {
     if (keyword == "transparent")
@@ -150,16 +212,20 @@ Css.isImageRule = function(nodeType,rule)
 
 Css.copyTextStyles = function(fromNode, toNode, style)
 {
-    var view = fromNode.ownerDocument.defaultView;
+    var view = fromNode ? fromNode.ownerDocument.defaultView : null;
     if (view)
     {
         if (!style)
             style = view.getComputedStyle(fromNode, "");
 
-        toNode.style.fontFamily = style.getPropertyCSSValue("font-family").cssText;
-        toNode.style.fontSize = style.getPropertyCSSValue("font-size").cssText;
-        toNode.style.fontWeight = style.getPropertyCSSValue("font-weight").cssText;
-        toNode.style.fontStyle = style.getPropertyCSSValue("font-style").cssText;
+        toNode.style.fontFamily = style.fontFamily;
+        toNode.style.fontSize = style.fontSize;
+        toNode.style.fontWeight = style.fontWeight;
+        toNode.style.fontStyle = style.fontStyle;
+        toNode.style.fontSizeAdjust = style.fontSizeAdjust;
+        toNode.style.fontStretch = style.fontStretch;
+        toNode.style.fontVariant = style.fontVariant;
+        toNode.style.MozFontFeatureSettings = style.MozFontFeatureSettings;
 
         return style;
     }
@@ -469,7 +535,7 @@ Css.createStyleSheet = function(doc, url)
         var expr = /url\(([\'"]?)(?![\'"]?(?:[a-z]+:|\/))/gi;
         cssText = cssText.replace(expr, "url($1" + absURL);
 
-        style.innerHTML = cssText;
+        style.textContent = cssText;
     }
 
     Firebug.setIgnored(style);
@@ -775,6 +841,16 @@ Css.rgbToHSL = function(value)
 Css.cssInfo = {};
 Css.cssInfo.html =
 {
+    "animation": [],
+    "animation-delay": [],
+    "animation-direction": ["normal", "alternate", "reverse", "alternate-reverse"],
+    "animation-duration": [],
+    "animation-iteration-count": ["infinite"],
+    "animation-name" : ["none"],
+    "animation-play-state": ["running", "paused"],
+    "animation-timing-function": [],
+    "animation-fill-mode": ["none", "forwards", "backwards", "both"],
+
     "background": ["bgRepeat", "bgAttachment", "position", "color", "image", "none", "boxModels"],
     "background-attachment": ["bgAttachment"],
     "background-color": ["color"],
@@ -812,10 +888,10 @@ Css.cssInfo.html =
     "border-top-right-radius": ["length"], // FF 4.0
     "border-bottom-right-radius": ["length"], // FF 4.0
     "border-bottom-left-radius": ["length"], // FF 4.0
-    "-moz-border-image": ["mozBorderImageRepeat", "thickness", "url()", "none"],
-    "border-image": ["mozBorderImageRepeat", "thickness", "url()", "none"], // FF 15.0
+    "-moz-border-image": ["borderImageRepeat", "thickness", "url()", "none"],
+    "border-image": ["borderImageRepeat", "thickness", "url()", "none"], // FF 15.0
     "border-image-outset": ["length"], // FF 15.0
-    "border-image-repeat": ["mozBorderImageRepeat"], // FF 15.0
+    "border-image-repeat": ["borderImageRepeat"], // FF 15.0
     "border-image-slice": ["fill"],
     "border-image-source": ["image", "none"],
     "border-image-width": ["auto", "length"], // FF 15.0
@@ -888,6 +964,8 @@ Css.cssInfo.html =
     "padding-bottom": ["length"],
     "padding-left": ["length"],
 
+    "page-break-after": ["pageBreak"],
+    "page-break-before": ["pageBreak"],
     "pointer-events": ["auto", "none"],
     "position": ["elPosition"],
     "quotes": ["none"],
@@ -901,6 +979,14 @@ Css.cssInfo.html =
     "text-rendering": ["textRendering"],
     "text-shadow": ["color", "length"],
     "text-transform": ["textTransform"],
+    "transition": ["transitionProperty", "timingFunction"],
+    "transition-property": ["transitionProperty"],
+    "transition-duration": [],
+    "transition-timing-function": ["timingFunction"],
+    "transition-delay": [],
+    "transform": ["transformFunction", "none", "length"],
+    "transform-origin": ["position", "length"],
+    "transform-style": ["transformStyle"],
     "unicode-bidi": ["unicodeBidi"],
     "vertical-align": ["verticalAlign", "length"],
     "visibility": ["visibility"],
@@ -909,8 +995,6 @@ Css.cssInfo.html =
     "word-spacing": ["normal", "length"],
     "word-wrap": ["wordWrap"], // FF 3.5
     "z-index": ["auto"],
-    "page-break-after": ["pageBreak"],
-    "page-break-before": ["pageBreak"],
 
     "-moz-appearance": ["mozAppearance"],
     "-moz-backface-visibility": ["mozBackfaceVisibility"], // FF 10.0
@@ -948,26 +1032,9 @@ Css.cssInfo.html =
     "-moz-column-rule-color": ["color"],
     "-moz-column-width": ["auto", "length"],
     "-moz-image-region": [],
-    "-moz-transform": ["mozTransformFunction", "none", "length"],
-    "-moz-transform-origin": ["position", "length"],
-    "-moz-transform-style": ["mozTransformStyle"], // FF 10.0
     "-moz-font-feature-settings": ["mozFontFeatureSettings"], // FF 4.0
     "-moz-font-language-override": ["normal"],
     "-moz-tab-size": [], // FF 4.0,
-    "-moz-transition": ["mozTransitionProperty", "mozTimingFunction"], // FF 4.0
-    "-moz-transition-property": ["mozTransitionProperty"], // FF 4.0
-    "-moz-transition-duration": [], // FF 4.0
-    "-moz-transition-timing-function": ["mozTimingFunction"], // FF 4.0
-    "-moz-transition-delay": [], // FF 4.0
-    "-moz-animation": [], // FF 5.0
-    "-moz-animation-delay": [], // FF 5.0
-    "-moz-animation-direction": ["normal", "alternate"], // FF 5.0
-    "-moz-animation-duration": [], // FF 5.0
-    "-moz-animation-iteration-count": ["infinite"], // FF 5.0
-    "-moz-animation-name" : ["none"], // FF 5.0
-    "-moz-animation-play-state": ["running", "paused"], // FF 5.0
-    "-moz-animation-timing-function": [], // FF 5.0
-    "-moz-animation-fill-mode": ["none", "forwards", "backwards", "both"], // FF 5.0
     "orient": ["horizontal", "vertical"], // FF 6.0
     "-moz-text-blink": ["none", "blink"], // FF 6.0
     "-moz-text-decoration-color": ["color"], // FF 6.0
@@ -1044,43 +1111,9 @@ Css.cssInfo.svg =
     "writing-mode": ["writingMode"]
 };
 
-Css.inheritedStyleNames =
-{
-    "border-collapse": 1,
-    "border-spacing": 1,
-    "border-style": 1,
-    "caption-side": 1,
-    "color": 1,
-    "cursor": 1,
-    "direction": 1,
-    "empty-cells": 1,
-    "font": 1,
-    "font-family": 1,
-    "font-size-adjust": 1,
-    "font-size": 1,
-    "font-style": 1,
-    "font-variant": 1,
-    "font-weight": 1,
-    "letter-spacing": 1,
-    "line-height": 1,
-    "list-style": 1,
-    "list-style-image": 1,
-    "list-style-position": 1,
-    "list-style-type": 1,
-    "opacity": 1,
-    "quotes": 1,
-    "text-align": 1,
-    "text-decoration": 1,
-    "text-indent": 1,
-    "text-shadow": 1,
-    "text-transform": 1,
-    "white-space": 1,
-    "word-spacing": 1,
-    "word-wrap": 1
-};
-
 Css.multiValuedProperties =
 {
+    "animation": 1,
     "background": 1,
     "background-position": 1,
     "border": 1,
@@ -1092,8 +1125,7 @@ Css.multiValuedProperties =
     "font": 1,
     "font-family": 1,
     "margin": 1,
-    "padding": 1,
-    "-moz-animation": 1
+    "padding": 1
 };
 
 Css.unitlessProperties =
@@ -1144,6 +1176,8 @@ Css.cssKeywords =
         "menupopup",
         "menuradio",
         "menuseparator",
+        "meterbar",
+        "meterchunk",
         "progressbar",
         "progressbar-vertical",
         "progresschunk",
@@ -2019,7 +2053,7 @@ Css.cssKeywords =
         "inset"
     ],
 
-    "mozBorderImageRepeat":
+    "borderImageRepeat":
     [
         "stretch",
         "round",
@@ -2030,20 +2064,24 @@ Css.cssKeywords =
     "image":
     [
         "url()",
-        "-moz-linear-gradient()", // FF 3.6
-        "-moz-radial-gradient()", // FF 3.6
-        "-moz-repeating-linear-gradient()", // FF 3.6
-        "-moz-repeating-radial-gradient()", // FF 3.6
-        "-moz-image-rect()", // FF 4.0
-        "-moz-element()", // FF 4.0
+        "linear-gradient()",
+        "radial-gradient()",
+        "repeating-linear-gradient()",
+        "repeating-radial-gradient()",
+        "-moz-linear-gradient()",
+        "-moz-radial-gradient()",
+        "-moz-repeating-linear-gradient()",
+        "-moz-repeating-radial-gradient()",
+        "-moz-image-rect()",
+        "-moz-element()",
     ],
 
     "length":
     [
-        "-moz-calc()"
+        "calc()"
     ],
 
-    "mozTransformFunction":
+    "transformFunction":
     [
         "matrix()",
         "matrix3d()",
@@ -2209,14 +2247,14 @@ Css.cssKeywords =
     ],
 
     // FF 10.0
-    "mozTransformStyle":
+    "transformStyle":
     [
         "preserve-3d",
         "flat"
     ],
 
     // FF 4.0
-    "mozTransitionProperty":
+    "transitionProperty":
     [
         "none",
         "all",
@@ -2267,6 +2305,8 @@ Css.cssKeywords =
         "text-indent",
         "text-shadow",
         "top",
+        "transform-origin",
+        "transform",
         "vertical-align",
         "visibility",
         "width",
@@ -2279,12 +2319,10 @@ Css.cssKeywords =
         "-moz-column-rule-width",
         "-moz-column-width",
         "-moz-image-region",
-        "-moz-outline-radius",
-        "-moz-transform-origin",
-        "-moz-transform"
+        "-moz-outline-radius"
     ],
 
-    "mozTimingFunction": // FF 4.0
+    "timingFunction": // FF 4.0
     [
         "cubic-bezier()",
         "ease",
@@ -2628,6 +2666,9 @@ Css.pseudoClasses =
     ":-moz-lwtheme-brighttext",
     ":-moz-lwtheme-darktext",
     ":-moz-math-increment-script-level",
+    ":-moz-meter-optimum",
+    ":-moz-meter-sub-optimum",
+    ":-moz-meter-sub-sub-optimum",
     ":-moz-only-whitespace",
     ":-moz-placeholder",
     ":-moz-read-only",
diff --git a/trace/FBTrace/chrome/firebug/content/lib/deprecated.js b/trace/FBTrace/chrome/firebug/content/lib/deprecated.js
index aed9992..8508846 100644
--- a/trace/FBTrace/chrome/firebug/content/lib/deprecated.js
+++ b/trace/FBTrace/chrome/firebug/content/lib/deprecated.js
@@ -17,7 +17,7 @@ var consoleService = Cc["@mozilla.org/consoleservice;1"].getService(Ci["nsIConso
 // Module implementation
 
 var Deprecated = {};
-Deprecated.deprecated = function(msg, fnc)
+Deprecated.deprecated = function(msg, fnc, args)
 {
     return function deprecationWrapper()
     {
@@ -43,9 +43,9 @@ Deprecated.deprecated = function(msg, fnc)
             this.nagged = true;
         }
 
-        return fnc.apply(this, arguments);
+        return fnc.apply(this, args || arguments);
     }
-}
+};
 
 // ********************************************************************************************* //
 // Local helpers
diff --git a/trace/FBTrace/chrome/firebug/content/lib/dom.js b/trace/FBTrace/chrome/firebug/content/lib/dom.js
index bc084eb..81e2f17 100644
--- a/trace/FBTrace/chrome/firebug/content/lib/dom.js
+++ b/trace/FBTrace/chrome/firebug/content/lib/dom.js
@@ -145,6 +145,12 @@ Dom.getBody = function(doc)
 // ********************************************************************************************* //
 // DOM Modification
 
+Dom.insertAfter = function(newNode, referenceNode)
+{
+    if (referenceNode.parentNode)
+        referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
+}
+
 Dom.addScript = function(doc, id, src)
 {
     var element = doc.createElementNS("http://www.w3.org/1999/xhtml", "html:script");
@@ -154,7 +160,7 @@ Dom.addScript = function(doc, id, src)
     if (!FBTrace.DBG_CONSOLE)
         Firebug.setIgnored(element);
 
-    element.innerHTML = src;
+    element.textContent = src;
 
     if (doc.documentElement)
     {
@@ -175,11 +181,8 @@ Dom.setOuterHTML = function(element, html)
 {
     try
     {
-        var doc = element.ownerDocument;
-        var range = doc.createRange();
-        range.selectNode(element || doc.documentElement);
+        var fragment = DOM.markupToDocFragment(html, element);
 
-        var fragment = range.createContextualFragment(html);
         var first = fragment.firstChild;
         var last = fragment.lastChild;
         element.parentNode.replaceChild(fragment, element);
@@ -191,6 +194,15 @@ Dom.setOuterHTML = function(element, html)
     }
 };
 
+Dom.markupToDocFragment = function(markup, parent)
+{
+    var doc = parent.ownerDocument;
+    var range = doc.createRange();
+    range.selectNode(parent || doc.documentElement);
+
+    return range.createContextualFragment(markup);
+};
+
 Dom.appendInnerHTML = function(element, html, referenceElement)
 {
     var doc = element.ownerDocument;
@@ -244,7 +256,7 @@ Dom.hide = function(elt, hidden)
 
 Dom.clearNode = function(node)
 {
-    node.innerHTML = "";
+    node.textContent = "";
 };
 
 Dom.eraseNode = function(node)
@@ -402,7 +414,7 @@ Dom.findPrevious = function(node, criteria, downOnly, maxRoot)
     }
 };
 
-// ************************************************************************************************
+// ********************************************************************************************* //
 // Graphics
 
 Dom.getClientOffset = function(elt)
@@ -424,7 +436,10 @@ Dom.getClientOffset = function(elt)
                 addOffset(p, coords, view);
         }
         else if (elt.ownerDocument.defaultView.frameElement)
-            addOffset(elt.ownerDocument.defaultView.frameElement, coords, elt.ownerDocument.defaultView);
+        {
+            addOffset(elt.ownerDocument.defaultView.frameElement, coords,
+                elt.ownerDocument.defaultView);
+        }
     }
 
     var coords = {x: 0, y: 0};
@@ -445,8 +460,8 @@ Dom.getClientOffset = function(elt)
  */
 Dom.getLTRBWH = function(elt)
 {
-    var bcrect,
-        dims = {"left": 0, "top": 0, "right": 0, "bottom": 0, "width": 0, "height": 0};
+    var bcrect;
+    var dims = {"left": 0, "top": 0, "right": 0, "bottom": 0, "width": 0, "height": 0};
 
     if (elt)
     {
@@ -487,7 +502,8 @@ Dom.getOffsetSize = function(elt)
  */
 Dom.getOverflowParent = function(element)
 {
-    for (var scrollParent = element.parentNode; scrollParent; scrollParent = scrollParent.offsetParent)
+    for (var scrollParent = element.parentNode; scrollParent;
+        scrollParent = scrollParent.offsetParent)
     {
         if (scrollParent.scrollHeight > scrollParent.offsetHeight)
             return scrollParent;
@@ -504,9 +520,11 @@ Dom.isScrolledToBottom = function(element)
     var onBottom = (element.scrollTop + element.offsetHeight) == element.scrollHeight;
 
     if (FBTrace.DBG_CONSOLE)
+    {
         FBTrace.sysout("Dom.isScrolledToBottom offsetHeight: " + element.offsetHeight +
             ", scrollTop: " + element.scrollTop + ", scrollHeight: " + element.scrollHeight +
             ", onBottom: " + onBottom);
+    }
 
     return onBottom;
 };
@@ -522,9 +540,14 @@ Dom.scrollToBottom = function(element)
 
     if (FBTrace.DBG_CONSOLE)
     {
-        FBTrace.sysout("scrollToBottom reset scrollTop "+element.scrollTop+" = "+element.scrollHeight);
+        FBTrace.sysout("scrollToBottom reset scrollTop " + element.scrollTop + " = " +
+            element.scrollHeight);
+
         if (element.scrollHeight == element.offsetHeight)
-            FBTrace.sysout("scrollToBottom attempt to scroll non-scrollable element "+element, element);
+        {
+            FBTrace.sysout("scrollToBottom attempt to scroll non-scrollable element " +
+                element, element);
+        }
     }
 
     return (element.scrollTop == element.scrollHeight);
@@ -565,8 +588,8 @@ Dom.linesIntoCenterView = function(element, scrollBox)  // {before: int, after:
     var offset = Dom.getClientOffset(element);
 
     var topSpace = offset.y - scrollBox.scrollTop;
-    var bottomSpace = (scrollBox.scrollTop + scrollBox.clientHeight)
-        - (offset.y + element.offsetHeight);
+    var bottomSpace = (scrollBox.scrollTop + scrollBox.clientHeight) -
+        (offset.y + element.offsetHeight);
 
     if (topSpace < 0 || bottomSpace < 0)
     {
@@ -574,7 +597,7 @@ Dom.linesIntoCenterView = function(element, scrollBox)  // {before: int, after:
         var centerY = offset.y - split;
         scrollBox.scrollTop = centerY;
         topSpace = split;
-        bottomSpace = split -  element.offsetHeight;
+        bottomSpace = split - element.offsetHeight;
     }
 
     return {
@@ -692,9 +715,40 @@ Dom.scrollTo = function(element, scrollBox, alignmentX, alignmentY, scrollWhenVi
  */
 Dom.scrollIntoCenterView = function(element, scrollBox, notX, notY)
 {
-    Dom.scrollTo(element, scrollBox, notX ? "none" : "centerOrLeft", notY ? "none" : "centerOrTop");
+    Dom.scrollTo(element, scrollBox, notX ? "none" : "centerOrLeft",
+        notY ? "none" : "centerOrTop");
 };
 
+Dom.scrollMenupopup = function(popup, item)
+{
+    var doc = popup.ownerDocument;
+    var box = doc.getAnonymousNodes(popup)[0];
+    var scrollBox = doc.getAnonymousNodes(box)[1];
+
+    if (item == undefined)
+    {
+        scrollBox.scrollTop = scrollBox.scrollHeight + 100;
+    }
+    else if (item == 0)
+    {
+        scrollBox.scrollTop = 0;
+    }
+    else
+    {
+        var popupRect = popup.getBoundingClientRect();
+        var itemRect = item.getBoundingClientRect();
+
+        if (itemRect.top < popupRect.top + itemRect.height)
+        {
+            scrollBox.scrollTop += itemRect.top - popupRect.top - itemRect.height;
+        }
+        else if (itemRect.bottom + itemRect.height > popupRect.bottom)
+        {
+            scrollBox.scrollTop -= popupRect.bottom - itemRect.bottom - itemRect.height;
+        }
+    }
+}
+
 // ********************************************************************************************* //
 // DOM Members
 
@@ -758,6 +812,8 @@ Dom.getDOMMembers = function(object)
         { return domMemberCache.Node; }
     else if (object instanceof Event || object instanceof Dom.EventCopy)
         { return domMemberCache.Event; }
+    else if (object instanceof Object)
+        { return domMemberCache.Object; }
 
     return null;
 };
@@ -777,12 +833,27 @@ Dom.isDOMConstant = function(object, name)
     if (name == "__proto__")
         return false;
 
-    if (!(object instanceof Window ||
-        object instanceof Node ||
-        object instanceof Location ||
-        object instanceof Event ||
-        object instanceof Dom.EventCopy))
+    // object isn't recognized as such when using ===,
+    // so use this as workaround
+    var str = Object.prototype.toString.call(object);
+    var isDOMProperty = ["[object Window]", "[object Node]", "[object Location]",
+        "[object Event]"].indexOf(str) !== -1;
+
+    if (!(object === window.Window ||
+        object === window.Object ||
+        object === window.Node ||
+        object === window.Location ||
+        object === window.Event ||
+        object === Dom.EventCopy ||
+        object instanceof window.Window ||
+        object instanceof window.Node ||
+        object instanceof window.Location ||
+        object instanceof window.Event ||
+        object instanceof Dom.EventCopy ||
+        isDOMProperty))
+    {
         return false;
+    }
 
     return Dom.domConstantMap.hasOwnProperty(name);
 }
@@ -834,7 +905,12 @@ domMemberMap.Window =
     "mozAnimationStartTime", //FF4.0
     "mozPaintCount", //FF4.0
     "mozRequestAnimationFrame", //FF4.0
-    "mozIndexedDB", //FF4.0
+    "mozCancelAnimationFrame",
+    "mozCancelRequestAnimationFrame",
+
+    "mozCancelAnimationFrame",
+    "mozCancelRequestAnimationFrame",
+    "indexedDB",
 
     "status",
     "defaultStatus",
@@ -860,7 +936,6 @@ domMemberMap.Window =
     "scrollbars",
     "fullScreen",
     "netscape",
-    "java",
     "console",
     "Components",
     "controllers",
@@ -873,7 +948,6 @@ domMemberMap.Window =
     "length",
 
     "sessionStorage",
-    "globalStorage",
 
     "setTimeout",
     "setInterval",
@@ -933,6 +1007,195 @@ domMemberMap.Window =
     "matchMedia", // https://developer.mozilla.org/en/DOM/window.matchMedia
 
     "getInterface",
+
+    "BarProp",
+    "Controllers",
+    "Crypto",
+    "DOMException",
+    "DOMStringList",
+    "EventTarget",
+    "History",
+    "MimeTypeArray",
+    "MozURLProperty",
+    "Navigator",
+    "NodeList",
+    "OfflineResourceList",
+    "Screen",
+    "Storage",
+    "XULControllers",
+    "Document",
+    "Element",
+    "Attr",
+    "CharacterData",
+    "DOMTokenList",
+    "Text",
+
+    "HTMLAnchorElement",
+    "HTMLAudioElement",
+    "HTMLBaseElement",
+    "HTMLButtonElement",
+    "HTMLCollection",
+    "HTMLCanvasElement",
+    "HTMLDataListElement",
+    "HTMLDListElement",
+    "HTMLDocument",
+    "HTMLElement",
+    "HTMLEmbedElement",
+    "HTMLHtmlElement",
+    "HTMLBRElement",
+    "HTMLBodyElement",
+    "HTMLCollection",
+    "HTMLDivElement",
+    "HTMLDocument",
+    "HTMLElement",
+    "HTMLFormElement",
+    "HTMLHRElement",
+    "HTMLHeadElement",
+    "HTMLHeadingElement",
+    "HTMLHtmlElement",
+    "HTMLIFrameElement",
+    "HTMLImageElement",
+    "HTMLInputElement",
+    "HTMLLabelElement",
+    "HTMLLegendElement",
+    "HTMLLinkElement",
+    "HTMLMapElement",
+    "HTMLMediaElement",
+    "HTMLMenuElement",
+    "HTMLMetaElement",
+    "HTMLMeterElement",
+    "HTMLModElement",
+    "HTMLObjectElement",
+    "HTMLOListElement",
+    "HTMLOptionElement",
+    "HTMLOptionsCollection",
+    "HTMLOutputElement",
+    "HTMLPreElement",
+    "HTMLProgressElement",
+    "HTMLQuoteElement",
+    "HTMLScriptElement",
+    "HTMLSelectElement",
+    "HTMLSourceElement",
+    "HTMLSpanElement",
+    "HTMLStyleElement",
+    "HTMLTableCellElement",
+    "HTMLTableElement",
+    "HTMLTableRowElement",
+    "HTMLTableSectionElement",
+    "HTMLTextAreaElement",
+    "HTMLTitleElement",
+    "HTMLUListElement",
+    "HTMLUnknownElement",
+    "HTMLVideoElement",
+
+    "Infinity",
+    "JSON",
+    "Location",
+    "Math",
+    "NaN",
+    "Node",
+    "StopIteration",
+    "Window",
+    "XULElement",
+    "undefined",
+    "CSS2Properties",
+    "CSSStyleDeclaration",
+    "Error",
+    "EvalError",
+    "InternalError",
+    "Namespace",
+    "QName",
+    "RangeError",
+    "ReferenceError",
+    "SyntaxError",
+    "TypeError",
+    "URIError",
+    "Array",
+    "ArrayBuffer",
+    "Boolean",
+    "DataView",
+    "Date",
+    "Float32Array",
+    "Float64Array",
+    "Function",
+    "Int16Array",
+    "Int32Array",
+    "Int8Array",
+    "Iterator",
+    "Map",
+    "Number",
+    "Object",
+    "ParallelArray",
+    "QueryInterface",
+    "RegExp",
+    "Set",
+    "String",
+    "Uint16Array",
+    "Uint32Array",
+    "Uint8Array",
+    "Uint8ClampedArray",
+    "WeakMap",
+    "XML",
+    "XMLList",
+    "decodeURI",
+    "decodeURIComponent",
+    "dumpProfile",
+    "encodeURI",
+    "encodeURIComponent",
+    "escape",
+    "isFinite",
+    "isNaN",
+    "isXMLName",
+    "parseFloat",
+    "parseInt",
+    "pauseProfilers",
+    "resumeProfilers",
+    "startProfiling",
+    "stopProfiling",
+    "unescape",
+    "uneval",
+    "Performance",
+    "PerformanceNavigation",
+    "PerformanceTiming"
+];
+
+domMemberMap.Object =
+[
+    "arguments",
+    "caller",
+    "length",
+    "name",
+    "__defineGetter__",
+    "__defineSetter__",
+    "__lookupGetter__",
+    "__lookupSetter__",
+    "apply",
+    "bind",
+    "call",
+    "constructor",
+    "create",
+    "defineProperties",
+    "defineProperty",
+    "freeze",
+    "getOwnPropertyDescriptor",
+    "getOwnPropertyNames",
+    "getPrototypeOf",
+    "hasOwnProperty",
+    "isExtensible",
+    "isFrozen",
+    "isGenerator",
+    "isPrototypeOf",
+    "isSealed",
+    "keys",
+    "preventExtensions",
+    "propertyIsEnumerable",
+    "seal",
+    "toLocaleString",
+    "toSource",
+    "toString",
+    "unwatch",
+    "valueOf",
+    "watch"
 ];
 
 domMemberMap.Location =
@@ -948,7 +1211,9 @@ domMemberMap.Location =
 
     "assign",
     "reload",
-    "replace"
+    "replace",
+
+    "QueryInterface"
 ];
 
 domMemberMap.Node =
@@ -999,7 +1264,9 @@ domMemberMap.Node =
     "isSupported",
     "getFeature",
     "getUserData",
-    "setUserData"
+    "setUserData",
+
+    "QueryInterface"
 ];
 
 domMemberMap.Document = Arr.extendArray(domMemberMap.Node,
@@ -1877,6 +2144,15 @@ Dom.domInlineEventHandlersMap =
     "onvolumechange": 1,
     "onwaiting": 1,
     "onmozfullscreenchange": 1,
+    "ondevicelight": 1,
+    "ondeviceproximity": 1,
+    "onmouseenter": 1,
+    "onmouseleave": 1,
+    "onmozfullscreenerror": 1,
+    "onmozpointerlockchange": 1,
+    "onmozpointerlockerror": 1,
+    "onuserproximity": 1,
+    "onwheel": 1
 }
 
 // ********************************************************************************************* //
diff --git a/trace/FBTrace/chrome/firebug/content/lib/domplate.js b/trace/FBTrace/chrome/firebug/content/lib/domplate.js
index 5131b9f..c2ba7f3 100644
--- a/trace/FBTrace/chrome/firebug/content/lib/domplate.js
+++ b/trace/FBTrace/chrome/firebug/content/lib/domplate.js
@@ -295,9 +295,9 @@ DomplateTag.prototype =
             {
                 for (var i = 0; i < child.parts.length; ++i)
                 {
-                    if (child.parts[i] instanceof Variable)
+                    if (child.parts[i] instanceof Variables)
                     {
-                        var name = child.parts[i].name;
+                        var name = child.parts[i].names[0];
                         var names = name.split(".");
                         args.push(names[0]);
                     }
@@ -422,10 +422,8 @@ DomplateTag.prototype =
         var nodeCount = this.generateDOM(path, blocks, this.domArgs);
 
         var fnBlock = ['(function (root, context, o'];
-
         for (var i = 0; i < path.staticIndex; ++i)
             fnBlock.push(', ', 's'+i);
-
         for (var i = 0; i < path.renderIndex; ++i)
             fnBlock.push(', ', 'd'+i);
 
@@ -442,10 +440,10 @@ DomplateTag.prototype =
 
         fnBlock.push(blocks.join(""));
 
-        if (this.subject)
-            fnBlock.push('}\n');
         if (this.context)
             fnBlock.push('}\n');
+        if (this.subject)
+            fnBlock.push('}\n');
 
         fnBlock.push('return ', nodeCount, ';\n');
         fnBlock.push('})\n');
@@ -499,6 +497,7 @@ DomplateTag.prototype =
             for (var i = 2; i < arguments.length; ++i)
             {
                 var index = arguments[i];
+
                 if (i == 3)
                     index += offset;
 
@@ -534,7 +533,6 @@ DomplateTag.prototype =
             chained.cause = {exc:exc, js: js};
             throw chained;
         }
-
     },
 
     generateDOM: function(path, blocks, args)
@@ -735,12 +733,25 @@ DomplateLoop.prototype = copyObject(DomplateTag.prototype,
     {
         this.addCode(topBlock, topOuts, blocks);
 
+        // We are in a FOR loop and our this.iter property contains
+        // either a simple function name as a string or a Parts object
+        // with only ONE Variables object. There is only one variables object
+        // as the FOR argument can contain only ONE valid function callback
+        // with optional arguments or just one variable. Allowed arguments are
+        // func or $var or $var.sub or $var|func or $var1,$var2|func or $var|func1|func2 or $var1,$var2|func1|func2
         var iterName;
         if (this.iter instanceof Parts)
         {
+            // We have a function with optional aruments or just one variable
             var part = this.iter.parts[0];
-            iterName = part.name;
-
+            
+            // Join our function arguments or variables
+            // If the user has supplied multiple variables without a function
+            // this will create an invalid result and we should probably add an
+            // error message here or just take the first variable
+            iterName = part.names.join(",");
+
+            // Nest our functions
             if (part.format)
             {
                 for (var i = 0; i < part.format.length; ++i)
@@ -749,12 +760,12 @@ DomplateLoop.prototype = copyObject(DomplateTag.prototype,
         }
         else
         {
+            // We have just a simple function name without any arguments
             iterName = this.iter;
         }
 
         blocks.push('__loop__.apply(this, [', iterName, ', __out__, function(',
             this.varName, ', __out__) {\n');
-
         this.generateChildMarkup(topBlock, topOuts, blocks, info);
         this.addCode(topBlock, topOuts, blocks);
 
@@ -809,9 +820,9 @@ DomplateLoop.prototype = copyObject(DomplateTag.prototype,
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
-function Variable(name, format)
+function Variables(names, format)
 {
-    this.name = name;
+    this.names = names;
     this.format = format;
 }
 
@@ -824,7 +835,8 @@ function Parts(parts)
 
 function parseParts(str)
 {
-    var re = /\$([_A-Za-z][_A-Za-z0-9.|]*)/g;
+    // Match $var or $var.sub or $var|func or $var1,$var2|func or $var|func1|func2 or $var1,$var2|func1|func2
+    var re = /\$([_A-Za-z][_A-Za-z0-9.]*(,\$[_A-Za-z][_A-Za-z0-9.]*)*([_A-Za-z0-9.|]*))/g;
     var index = 0;
     var parts = [];
 
@@ -835,14 +847,20 @@ function parseParts(str)
         if (pre)
             parts.push(pre);
 
-        var expr = m[1].split("|");
-        parts.push(new Variable(expr[0], expr.slice(1)));
+        var segs = m[1].split("|");
+        var vars = segs[0].split(",$");
+
+        // Assemble the variables object and append to buffer
+        parts.push(new Variables(vars, segs.slice(1)));
+
         index = re.lastIndex;
     }
 
+    // No matches found at all so we return the whole string
     if (!index)
         return str;
 
+    // If we have data after our last matched index we append it here as the final step
     var post = str.substr(index);
     if (post)
         parts.push(post);
@@ -872,8 +890,8 @@ function readPartNames(val, vars)
         for (var i = 0; i < val.parts.length; ++i)
         {
             var part = val.parts[i];
-            if (part instanceof Variable)
-                vars.push(part.name);
+            if (part instanceof Variables)
+                vars.push(part.names[0]);
         }
     }
 }
@@ -886,7 +904,7 @@ function generateArg(val, path, args)
         for (var i = 0; i < val.parts.length; ++i)
         {
             var part = val.parts[i];
-            if (part instanceof Variable)
+            if (part instanceof Variables)
             {
                 var varName = 'd'+path.renderIndex++;
                 if (part.format)
@@ -918,9 +936,9 @@ function addParts(val, delim, block, info, escapeIt)
         for (var i = 0; i < val.parts.length; ++i)
         {
             var part = val.parts[i];
-            if (part instanceof Variable)
+            if (part instanceof Variables)
             {
-                var partName = part.name;
+                var partName = part.names.join(",");
                 if (part.format)
                 {
                     for (var j = 0; j < part.format.length; ++j)
diff --git a/trace/FBTrace/chrome/firebug/content/lib/events.js b/trace/FBTrace/chrome/firebug/content/lib/events.js
index 35b09a4..5254f5f 100644
--- a/trace/FBTrace/chrome/firebug/content/lib/events.js
+++ b/trace/FBTrace/chrome/firebug/content/lib/events.js
@@ -326,6 +326,15 @@ const eventTypes =
         "cut",
         "copy",
         "paste"
+    ],
+
+    touch: [
+        "touchstart",
+        "touchend",
+        "touchmove",
+        "touchenter",
+        "touchleave",
+        "touchcancel"
     ]
 };
 
diff --git a/trace/FBTrace/chrome/firebug/content/lib/fonts.js b/trace/FBTrace/chrome/firebug/content/lib/fonts.js
index cc43de1..0e58257 100644
--- a/trace/FBTrace/chrome/firebug/content/lib/fonts.js
+++ b/trace/FBTrace/chrome/firebug/content/lib/fonts.js
@@ -78,7 +78,7 @@ Fonts.getFontsUsedInContext = function(context)
  * Retrieves the information about a font
  * @context: Context of the font
  * @win: Window the font is used in
- * @identifier: Either a URL in case of a Fonts font or the font name
+ * @identifier: Either a URL in case of a web font or the font name
  * @return Object with information about the font
  */
 Fonts.getFontInfo = function(context, win, identifier)
@@ -94,15 +94,15 @@ Fonts.getFontInfo = function(context, win, identifier)
     }
 
     var fonts = Fonts.getFonts(doc.documentElement);
-    var url = Url.splitURLBase(identifier);
 
     if (FBTrace.DBG_FONTS)
-        FBTrace.sysout("Fonts.getFontInfo;", {fonts:fonts, url:url});
+        FBTrace.sysout("Fonts.getFontInfo;", {fonts:fonts, identifier: identifier});
 
     for (var i=0; i<fonts.length; i++)
     {
-        if ((fonts[i].rule && url && identifier == fonts[i].URI) ||
-            identifier == fonts[i].CSSFamilyName || identifier == fonts[i].name)
+        if (identifier == fonts[i].URI ||
+            identifier.toLowerCase() == fonts[i].CSSFamilyName.toLowerCase() ||
+            identifier.toLowerCase() == fonts[i].name.toLowerCase())
         {
             return fonts[i];
         }
diff --git a/trace/FBTrace/chrome/firebug/content/lib/object.js b/trace/FBTrace/chrome/firebug/content/lib/object.js
index 1d367e1..5656d57 100644
--- a/trace/FBTrace/chrome/firebug/content/lib/object.js
+++ b/trace/FBTrace/chrome/firebug/content/lib/object.js
@@ -25,19 +25,21 @@ Obj.bindFixed = function() // fn, thisObject, args => thisObject.fn(args);
     return function() { return fn.apply(object, args); }
 };
 
-Obj.extend = function(l, r)
+Obj.extend = function()
 {
-    if (!l || !r)
+    if (arguments.length < 2)
     {
-        FBTrace.sysout("object.extend; ERROR", [l, r]);
+        FBTrace.sysout("object.extend; ERROR", arguments);
         throw new Error("Obj.extend on undefined object");
     }
 
     var newOb = {};
-    for (var n in l)
-        newOb[n] = l[n];
-    for (var n in r)
-        newOb[n] = r[n];
+    for (var i = 0, len = arguments.length; i < len; ++i)
+    {
+        for (var prop in arguments[i])
+            newOb[prop] = arguments[i][prop];
+    }
+
     return newOb;
 };
 
@@ -68,8 +70,7 @@ Obj.hasProperties = function(ob, nonEnumProps, ownPropsOnly)
             return false;
 
         var obString = Str.safeToString(ob);
-        if (obString === "[object StorageList]" ||
-            obString === "[xpconnect wrapped native prototype]")
+        if (obString === "[xpconnect wrapped native prototype]")
         {
             return true;
         }
diff --git a/trace/FBTrace/chrome/firebug/content/lib/options.js b/trace/FBTrace/chrome/firebug/content/lib/options.js
index 0f9b1aa..f1155f8 100644
--- a/trace/FBTrace/chrome/firebug/content/lib/options.js
+++ b/trace/FBTrace/chrome/firebug/content/lib/options.js
@@ -13,12 +13,11 @@ const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 const nsIPrefBranch = Ci.nsIPrefBranch;
-const nsIPrefBranch2 = Ci.nsIPrefBranch2;
 const PrefService = Cc["@mozilla.org/preferences-service;1"];
 
 const nsIPrefService = Ci.nsIPrefService;
 const prefService = PrefService.getService(nsIPrefService);
-const prefs = PrefService.getService(nsIPrefBranch2);
+const prefs = PrefService.getService(nsIPrefBranch);
 
 const prefNames =  // XXXjjb TODO distribute to modules
 [
@@ -97,6 +96,8 @@ var optionUpdateMap = {};
 var Options =
 /** @lends Options */
 {
+    prefDomain: "extensions.firebug",
+
     getPrefDomain: function()
     {
         return this.prefDomain;
@@ -347,7 +348,7 @@ var Options =
         if (prefs.prefHasUserValue(prefName))
             prefs.clearUserPref(prefName);
     },
-    
+
     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
     // Firebug UI text zoom
 
@@ -412,6 +413,11 @@ var Options =
             }
         }
     },
+
+    forceSave: function()
+    {
+        prefs.savePrefFile(null);
+    }
 };
 
 // ********************************************************************************************* //
diff --git a/trace/FBTrace/chrome/firebug/content/lib/string.js b/trace/FBTrace/chrome/firebug/content/lib/string.js
index f9e98c1..c638a18 100644
--- a/trace/FBTrace/chrome/firebug/content/lib/string.js
+++ b/trace/FBTrace/chrome/firebug/content/lib/string.js
@@ -22,7 +22,7 @@ const reNotWhitespace = /[^\s]/;
 
 var Str = {};
 
-// ************************************************************************************************
+// ********************************************************************************************* //
 // Whitespace and Entity conversions
 
 var entityConversionLists = Str.entityConversionLists =
@@ -111,7 +111,7 @@ e(0x200d, "zwj", attr, text, white, editor);
 e(0x200e, "lrm", attr, text, white, editor);
 e(0x200f, "rlm", attr, text, white, editor);
 
-//************************************************************************************************
+// ********************************************************************************************* //
 // Entity escaping
 
 var entityConversionRegexes =
@@ -356,7 +356,7 @@ function unescapeEntities(str, lists)
     return results.join('') || '';
 }
 
-// ************************************************************************************************
+// ********************************************************************************************* //
 // String escaping
 
 var escapeForTextNode = Str.escapeForTextNode = createSimpleEscape("text", "normal");
@@ -386,7 +386,7 @@ Str.unescapeForTextNode = function(str)
         str = escapeForElementAttribute(str);
 
     return str;
-}
+};
 
 Str.unescapeForURL = createSimpleEscape('text', 'reverse');
 
@@ -532,20 +532,29 @@ Str.splitLines = function(text)
 Str.trim = function(text)
 {
     return text.replace(/^\s*|\s*$/g, "");
-}
+};
 
 Str.trimLeft = function(text)
 {
     return text.replace(/^\s+/, "");
-}
+};
 
 Str.trimRight = function(text)
 {
     return text.replace(/\s+$/, "");
-}
+};
 
 Str.hasPrefix = function(hay, needle)
 {
+    // Passing empty string is ok, but null or undefined is not.
+    if (hay == null)
+    {
+        if (FBTrace.DBG_ERRORS)
+            FBTrace.sysout("Str.hasPrefix; string must not be null", {hay: hay, needle: needle});
+
+        return false;
+    }
+
     // This is the fastest way of testing for prefixes - (hay.indexOf(needle) === 0)
     // can be O(|hay|) in the worst case, and (hay.substr(0, needle.length) === needle)
     // unnecessarily creates a new string and might be O(|needle|) in some JavaScript
@@ -553,6 +562,14 @@ Str.hasPrefix = function(hay, needle)
     return hay.lastIndexOf(needle, 0) === 0;
 };
 
+Str.endsWith = function(str, suffix)
+{
+    return str.indexOf(suffix, str.length - suffix.length) !== -1;
+}
+
+// ********************************************************************************************* //
+// HTML Wrap
+
 Str.wrapText = function(text, noEscapeHTML)
 {
     var reNonAlphaNumeric = /[^A-Za-z_$0-9'"-]/;
@@ -591,15 +608,15 @@ Str.wrapText = function(text, noEscapeHTML)
     }
 
     return html;
-}
+};
 
 Str.insertWrappedText = function(text, textBox, noEscapeHTML)
 {
     var html = Str.wrapText(text, noEscapeHTML);
     textBox.innerHTML = "<pre role=\"list\">" + html.join("") + "</pre>";
-}
+};
 
-// ************************************************************************************************
+// ********************************************************************************************* //
 // Indent
 
 const reIndent = /^(\s+)/;
@@ -625,22 +642,16 @@ Str.cleanIndentation = function(text)
             lines[i] = line.substr(minIndent);
     }
     return lines.join("");
-}
+};
 
-// ************************************************************************************************
+// ********************************************************************************************* //
 // Formatting
 
-Str.formatNumber = function(number)
-{
-    number += "";
-    var x = number.split(".");
-    var x1 = x[0];
-    var x2 = x.length > 1 ? "." + x[1] : "";
-    var rgx = /(\d+)(\d{3})/;
-    while (rgx.test(x1))
-        x1 = x1.replace(rgx, "$1" + "," + "$2");
-    return x1 + x2;
-}
+//deprecated compatibility functions
+Str.deprecateEscapeHTML = createSimpleEscape("text", "normal");
+
+Str.formatNumber = Deprecated.deprecated("use <number>.toLocaleString() instead",
+    function(number) { return number.toLocaleString(); });
 
 Str.formatSize = function(bytes)
 {
@@ -670,16 +681,16 @@ Str.formatSize = function(bytes)
     if (bytes == -1 || bytes == undefined)
         return "?";
     else if (bytes == 0)
-        return "0";
+        return "0 B";
     else if (bytes < 1024)
-        result = bytes + " B";
+        result = bytes.toLocaleString() + " B";
     else if (bytes < (1024*1024))
-        result = Math.round((bytes/1024)*a)/a + " KB";
+        result = (Math.round((bytes/1024)*a)/a).toLocaleString() + " KB";
     else
-        result = Math.round((bytes/(1024*1024))*a)/a + " MB";
+        result = (Math.round((bytes/(1024*1024))*a)/a).toLocaleString() + " MB";
 
     return negative ? "-" + result : result;
-}
+};
 
 Str.formatTime = function(elapsed)
 {
@@ -697,10 +708,32 @@ Str.formatTime = function(elapsed)
         var sec = (elapsed % 60000);
         return min + "m " + (Math.round((elapsed/1000)%60)) + "s";
     }
-}
+};
+
+/**
+ * Formats an IPv4 or IPv6 address incl. port
+ * @param {String} address IP address to format
+ * @param {String} [port] IP port to format
+ * @returns {String} Formatted IP address
+ */
+Str.formatIP = function(address, port)
+{
+    if (!address || address == "")
+        return "";
 
-//********************************************************************************************* //
-//Conversions
+    var result = address;
+    var isIPv6Address = address.indexOf(":") != -1;
+    if (isIPv6Address)
+        result = "["+result+"]";
+
+    if (port && port != "")
+        result += ":"+port;
+
+    return result;
+};
+
+// ********************************************************************************************* //
+// Conversions
 
 Str.convertToUnicode = function(text, charset)
 {
diff --git a/trace/FBTrace/chrome/firebug/content/lib/system.js b/trace/FBTrace/chrome/firebug/content/lib/system.js
index e2e9686..8a3e075 100644
--- a/trace/FBTrace/chrome/firebug/content/lib/system.js
+++ b/trace/FBTrace/chrome/firebug/content/lib/system.js
@@ -37,7 +37,7 @@ System.launchProgram = function(exePath, args)
 {
     try
     {
-        var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
+        var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
         file.initWithPath(exePath);
         if (System.getPlatformName() == "Darwin" && file.isDirectory())
         {
@@ -62,19 +62,23 @@ System.launchProgram = function(exePath, args)
 
 System.getIconURLForFile = function(path)
 {
-    var fileHandler = ioService.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler);
+    var fileHandler = ioService.getProtocolHandler("file")
+        .QueryInterface(Ci.nsIFileProtocolHandler);
+
     try
     {
-        var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
+        var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
         file.initWithPath(path);
-        if ((System.getPlatformName() == "Darwin") && !file.isDirectory() && (path.indexOf(".app/") != -1))
+        if ((System.getPlatformName() == "Darwin") && !file.isDirectory() &&
+            (path.indexOf(".app/") != -1))
         {
             path = path.substr(0,path.lastIndexOf(".app/")+4);
             file.initWithPath(path);
         }
+
         return "moz-icon://" + fileHandler.getURLSpecFromFile(file) + "?size=16";
     }
-    catch(exc)
+    catch (exc)
     {
         if (FBTrace.DBG_ERRORS)
             FBTrace.sysout("getIconURLForFile ERROR "+exc+" for "+path, exc);
@@ -92,6 +96,44 @@ System.copyToClipboard = function(string)
         FBTrace.sysout("system.copyToClipboard; " + string, string);
 };
 
+System.getStringDataFromClipboard = function()
+{
+    // https://developer.mozilla.org/en-US/docs/Using_the_Clipboard#Pasting_Clipboard_Contents
+    var clip = Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard);
+    if (!clip)
+        return false;
+
+    var trans = Cc["@mozilla.org/widget/transferable;1"].createInstance(Ci.nsITransferable);
+    if (!trans)
+        return false;
+
+    if ("init" in trans)
+        trans.init(null);
+
+    trans.addDataFlavor("text/unicode");
+
+    clip.getData(trans, clip.kGlobalClipboard);
+
+    var str = {};
+    var strLength = {};
+
+    try
+    {
+        trans.getTransferData("text/unicode", str, strLength);
+
+        if (str)
+        {
+            str = str.value.QueryInterface(Ci.nsISupportsString);
+            return str.data.substring(0, strLength.value / 2);
+        }
+    }
+    catch (ex)
+    {
+    }
+
+    return false;
+}
+
 // ********************************************************************************************* //
 // Firebug Version Comparator
 
diff --git a/trace/FBTrace/chrome/firebug/content/lib/trace.js b/trace/FBTrace/chrome/firebug/content/lib/trace.js
index d34e2fa..e2e4322 100644
--- a/trace/FBTrace/chrome/firebug/content/lib/trace.js
+++ b/trace/FBTrace/chrome/firebug/content/lib/trace.js
@@ -2,38 +2,61 @@
 
 define([], function() {
 
-//********************************************************************************************* //
-//Constants
+// ********************************************************************************************* //
+// Constants
 
 const Cu = Components.utils;
 
-// ********************************************************************************************* //
-// Firebug Trace - FBTrace
-
 var scope = {};
+Cu["import"]("resource://firebug/fbtrace.js", scope);
 
-try
-{
-    Cu["import"]("resource://fbtrace/firebug-trace-service.js", scope);
-}
-catch (err)
+// ********************************************************************************************* //
+// Wrapper
+
+/**
+ * Wraps tracer for given option. Logs made through the wrapper will automatically
+ * be checked against the option and only displayed if the option is true.
+ * If FBTrace console isn't installed all options are false and there is no
+ * additional performance penalty.
+ */
+function TraceWrapper(tracer, option)
 {
-    scope.traceConsoleService =
+    function createMethodWrapper(method)
     {
-        getTracer: function(prefDomain)
+        return function()
         {
-            var TraceAPI = ["dump", "sysout", "setScope", "matchesNode", "time", "timeEnd"];
-            var TraceObj = {};
-            for (var i=0; i<TraceAPI.length; i++)
-                TraceObj[TraceAPI[i]] = function() {};
-            return TraceObj;
+            // Check the option before the log is passed to the tracing console.
+            if (tracer[option])
+                tracer[method].apply(tracer, arguments);
         }
-    };
+    }
+
+    for (var i=0; i<TraceAPI.length; i++)
+    {
+        var method = TraceAPI[i];
+        this[method] = createMethodWrapper(method);
+    }
 }
 
 // ********************************************************************************************* //
 
-return scope.traceConsoleService.getTracer("extensions.firebug");
+var tracer = scope.FBTrace;
+
+/**
+ * Support for scoped logging.
+ * 
+ * Example:
+ * FBTrace = FBTrace.to("DBG_NET");
+ * 
+ * // This log will be displayed only if DBG_NET option is on
+ * FBTrace.sysout("net.initialiaze");
+ */
+tracer.to = function(option)
+{
+    return new TraceWrapper(this, option);
+}
+
+return tracer;
 
 // ********************************************************************************************* //
-});
\ No newline at end of file
+});
diff --git a/trace/FBTrace/chrome/firebug/content/lib/url.js b/trace/FBTrace/chrome/firebug/content/lib/url.js
index 0878656..4ac4ef3 100644
--- a/trace/FBTrace/chrome/firebug/content/lib/url.js
+++ b/trace/FBTrace/chrome/firebug/content/lib/url.js
@@ -313,6 +313,20 @@ Url.getPrettyDomain = function(url)
     return m ? m[2] : "";
 };
 
+/**
+ * Returns the base URL for a given window
+ * @param {Object} win DOM window
+ * @returns {String} Base URL
+ */
+Url.getBaseURL = function(win)
+{
+    if (!win)
+        return;
+
+    var base = win.document.getElementsByTagName("base").item(0);
+    return base ? base.href : win.location.href;
+};
+
 Url.absoluteURL = function(url, baseURL)
 {
     // Replace "/./" with "/" using regular expressions (don't use string since /./
@@ -508,6 +522,17 @@ Url.reEncodeURL = function(file, text, noLimit)
     return url;
 };
 
+/**
+ * Extracts the URL from a CSS URL definition.
+ * Example: url(../path/to/file) => ../path/to/file
+ * @param {String} url CSS URL definition
+ * @returns {String} Extracted URL
+ */
+Url.extractFromCSS = function(url)
+{
+    return url.replace(/^url\(["']?(.*?)["']?\)$/, "$1");
+};
+
 Url.makeURI = function(urlString)
 {
     try
diff --git a/trace/FBTrace/chrome/firebug/content/lib/wrapper.js b/trace/FBTrace/chrome/firebug/content/lib/wrapper.js
index b4e71f1..232365a 100644
--- a/trace/FBTrace/chrome/firebug/content/lib/wrapper.js
+++ b/trace/FBTrace/chrome/firebug/content/lib/wrapper.js
@@ -19,11 +19,6 @@ Wrapper.getContentView = function(object)
     if (typeof(object) === "undefined" || object == null)
         return false;
 
-    // There is an exception when accessing StorageList.wrappedJSObject (which is
-    // instance of StorageObsolete)
-    if ("StorageList" in window && object instanceof window.StorageList)
-        return false;
-
     return (object.wrappedJSObject);
 }
 
@@ -33,11 +28,6 @@ Wrapper.unwrapObject = function(object)
     if (typeof(object) === 'undefined' || object == null)
         return object;
 
-    // There is an exception when accessing StorageList.wrappedJSObject (which is
-    // instance of StorageObsolete)
-    if ("StorageList" in window && object instanceof window.StorageList)
-        return object;
-
     if (object.wrappedJSObject)
         return object.wrappedJSObject;
 
@@ -88,10 +78,6 @@ Wrapper.unwrapIValueObject = function(scope, viewChrome)
         var prop = listValue.value[i];
         var name = Wrapper.unwrapIValue(prop.name);
 
-        // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=712289.
-        if (typeof name !== "string")
-            break;
-
         if (prop.value.jsType === prop.value.TYPE_NULL) // null is an object (!)
         {
             scopeVars[name] = null;
@@ -115,7 +101,6 @@ Wrapper.ignoreVars =
 
     // We are forced to ignore Java-related variables, because
     // trying to access them causes browser freeze
-    "java": 1,
     "sun": 1,
     "Packages": 1,
     "JavaArray": 1,
@@ -123,6 +108,7 @@ Wrapper.ignoreVars =
     "JavaObject": 1,
     "JavaClass": 1,
     "JavaPackage": 1,
+
     // internal firebug things XXXjjb todo we should privatize these
     "_firebug": 1,
     "_createFirebugConsole": 1,
diff --git a/trace/FBTrace/chrome/firebug/content/main.js b/trace/FBTrace/chrome/firebug/content/main.js
index d73ee9d..649450a 100644
--- a/trace/FBTrace/chrome/firebug/content/main.js
+++ b/trace/FBTrace/chrome/firebug/content/main.js
@@ -24,7 +24,7 @@ if (FBTrace.DBG_INITIALIZE || FBTrace.DBG_MODULES)
 try
 {
     // xxxHonza: temporary hack for Crossfire to provide custom set of modules.
-    var prefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch2);
+    var prefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
     var value = prefService.getCharPref("extensions.firebug.defaultModuleList");
     if (value)
     {
diff --git a/trace/FBTrace/chrome/firebug/content/moduleConfig.js b/trace/FBTrace/chrome/firebug/content/moduleConfig.js
index 6eb690c..2a28b70 100644
--- a/trace/FBTrace/chrome/firebug/content/moduleConfig.js
+++ b/trace/FBTrace/chrome/firebug/content/moduleConfig.js
@@ -59,6 +59,7 @@ Firebug.getModuleLoaderConfig = function(baseConfig)
         "firebug/css/computedPanel",
         "firebug/cookies/cookieModule",
         "firebug/cookies/cookiePanel",
+        "firebug/css/selectorPanel",
     ];
 
     return config;
@@ -84,14 +85,11 @@ Firebug.registerExtension = function(extName, extConfig)
     var tempConfig = this.getExtensionConfig(extName);
     if (tempConfig)
     {
-        FBTrace.sysout("firebug.registerExtension; ERROR An extension with the same ID " +
-            "already exists! - " + extName, tempConfig);
+        Components.utils.reportError("firebug.registerExtension; ERROR An extension " +
+            "with the same ID already exists! - " + extName, tempConfig);
         return;
     }
 
-    if (FBTrace.DBG_REGISTRATION)
-        FBTrace.sysout("Extension registered: " + extName);
-
     this.extensions[extName] = extConfig;
 
     var config = Firebug.getModuleLoaderConfig();
@@ -128,8 +126,8 @@ Firebug.registerExtension = function(extName, extConfig)
         }
         catch (err)
         {
-            if (FBTrace.DBG_ERRORS || FBTrace.DBG_REGISTRATION)
-                FBTrace.sysout("firebug.main; Extension: " + extName + " EXCEPTION " + err, err);
+            Components.utils.reportError("firebug.main; Extension: " + extName +
+                " EXCEPTION " + err, err);
         }
     });
 }
@@ -153,14 +151,11 @@ Firebug.unregisterExtension = function(extName)
             extConfig.app.shutdown();
 
         delete this.extensions[extName];
-
-        if (FBTrace.DBG_REGISTRATION)
-            FBTrace.sysout("Extension unregistered: " + extName);
     }
     catch (err)
     {
-        if (FBTrace.DBG_ERRORS || FBTrace.DBG_REGISTRATION)
-            FBTrace.sysout("unregisterExtension: " + extName + " EXCEPTION " + err, err);
+        Components.utils.reportError("unregisterExtension: " + extName +
+            " EXCEPTION " + err, err);
     }
 }
 
diff --git a/trace/FBTrace/chrome/firebug/content/net/fontViewer.js b/trace/FBTrace/chrome/firebug/content/net/fontViewer.js
index 2df5d16..0a8c47f 100644
--- a/trace/FBTrace/chrome/firebug/content/net/fontViewer.js
+++ b/trace/FBTrace/chrome/firebug/content/net/fontViewer.js
@@ -283,12 +283,12 @@ Firebug.FontViewerModel.Preview = domplate(
                 if (target.sourceDisplayed)
                 {
                     this.insertMetaDataFormatted(fontInfo, fontObject.metadata);
-                    target.innerHTML = Locale.$STR("fontviewer.view source");
+                    target.textContent = Locale.$STR("fontviewer.view source");
                 }
                 else
                 {
                     this.insertMetaDataSource(fontInfo, fontObject.metadata);
-                    target.innerHTML = Locale.$STR("fontviewer.pretty print");
+                    target.textContent = Locale.$STR("fontviewer.pretty print");
                 }
                 target.sourceDisplayed = !target.sourceDisplayed;
                 break;
@@ -300,13 +300,13 @@ Firebug.FontViewerModel.Preview = domplate(
                 {
                     sample.style.display = "block";
                     chars.style.display = "none";
-                    target.innerHTML = Locale.$STR("fontviewer.view characters");
+                    target.textContent = Locale.$STR("fontviewer.view characters");
                 }
                 else
                 {
                     sample.style.display = "none";
                     chars.style.display = "block";
-                    target.innerHTML = Locale.$STR("fontviewer.view sample");
+                    target.textContent = Locale.$STR("fontviewer.view sample");
                 }
                 target.lettersDisplayed = !target.lettersDisplayed;
                 break;
@@ -539,6 +539,7 @@ Firebug.FontViewerModel.Preview = domplate(
         var propValueTemplates = {
             vendor: Firebug.FontViewerModel.Preview.vendorTag,
             credits: Firebug.FontViewerModel.Preview.creditsTag,
+            description: Firebug.FontViewerModel.Preview.translatedInfoTag,
             copyright: Firebug.FontViewerModel.Preview.translatedInfoTag,
             trademark: Firebug.FontViewerModel.Preview.translatedInfoTag,
             license: Firebug.FontViewerModel.Preview.licenseTag
diff --git a/trace/FBTrace/chrome/firebug/content/net/netMonitor.js b/trace/FBTrace/chrome/firebug/content/net/netMonitor.js
index b22cb8b..de99f1a 100644
--- a/trace/FBTrace/chrome/firebug/content/net/netMonitor.js
+++ b/trace/FBTrace/chrome/firebug/content/net/netMonitor.js
@@ -32,6 +32,7 @@ const Cr = Components.results;
 var panelName = "net";
 
 var startFile = NetProgress.prototype.startFile;
+var openingFile = NetProgress.prototype.openingFile;
 var requestedFile = NetProgress.prototype.requestedFile;
 var respondedFile = NetProgress.prototype.respondedFile;
 var respondedCacheFile = NetProgress.prototype.respondedCacheFile;
@@ -399,6 +400,8 @@ var NetHttpObserver =
                 this.onExamineResponse(subject, win, tabId, context);
             else if (topic == "http-on-examine-cached-response")
                 this.onExamineCachedResponse(subject, win, tabId, context);
+            else if (topic == "http-on-opening-request")
+                this.openingFile(subject, win, tabId, context);
         }
         catch (err)
         {
@@ -517,6 +520,18 @@ var NetHttpObserver =
         networkContext.post(respondedCacheFile, [request, NetUtils.now(), info]);
     },
 
+    openingFile: function(request, win, tabId, context)
+    {
+        var networkContext = Firebug.NetMonitor.contexts[tabId];
+        if (!networkContext)
+            networkContext = context ? context.netProgress : null;
+
+        if (!networkContext)
+            return;
+
+        networkContext.post(openingFile, [request, win]);
+    },
+
     /* nsISupports */
     QueryInterface: function(iid)
     {
diff --git a/trace/FBTrace/chrome/firebug/content/net/netPanel.js b/trace/FBTrace/chrome/firebug/content/net/netPanel.js
index bbfd20c..6af088d 100644
--- a/trace/FBTrace/chrome/firebug/content/net/netPanel.js
+++ b/trace/FBTrace/chrome/firebug/content/net/netPanel.js
@@ -312,7 +312,7 @@ NetPanel.prototype = Obj.extend(Firebug.ActivablePanel,
             tooltiptext: "net.option.tip.Disable_Browser_Cache",
             command: function()
             {
-                BrowserCache.toggle(!this.getAttribute("checked"));
+                BrowserCache.toggle(!this.hasAttribute("checked"));
             }
         };
     },
@@ -963,10 +963,10 @@ NetPanel.prototype = Obj.extend(Firebug.ActivablePanel,
             }
 
             var remoteIPLabel = row.querySelector(".netRemoteAddressCol .netAddressLabel");
-            remoteIPLabel.innerHTML = NetRequestEntry.getRemoteAddress(file);
+            remoteIPLabel.textContent = NetRequestEntry.getRemoteAddress(file);
 
             var localIPLabel = row.querySelector(".netLocalAddressCol .netAddressLabel");
-            localIPLabel.innerHTML = NetRequestEntry.getLocalAddress(file);
+            localIPLabel.textContent = NetRequestEntry.getLocalAddress(file);
 
             if (file.requestHeaders)
                 Css.setClass(row, "hasHeaders");
@@ -988,7 +988,7 @@ NetPanel.prototype = Obj.extend(Firebug.ActivablePanel,
 
             var netBar = Dom.getChildByClass(row, "netTimeCol").childNodes[1];
             var timeLabel = Dom.getChildByClass(netBar, "netReceivingBar").firstChild;
-            timeLabel.innerHTML = NetRequestEntry.getElapsedTime({elapsed: this.elapsed});
+            timeLabel.textContent = NetRequestEntry.getElapsedTime({elapsed: this.elapsed});
 
             if (file.loaded)
                 Css.setClass(row, "loaded");
@@ -1189,7 +1189,7 @@ NetPanel.prototype = Obj.extend(Firebug.ActivablePanel,
             timeText += " (onload: " + NetRequestEntry.formatTime(loadTime) + ")";
         }
 
-        timeLabel.innerHTML = timeText;
+        timeLabel.textContent = timeText;
     },
 
     summarizePhase: function(phase, rightNow)
diff --git a/trace/FBTrace/chrome/firebug/content/net/netProgress.js b/trace/FBTrace/chrome/firebug/content/net/netProgress.js
index 8b1a22e..849f279 100644
--- a/trace/FBTrace/chrome/firebug/content/net/netProgress.js
+++ b/trace/FBTrace/chrome/firebug/content/net/netProgress.js
@@ -13,10 +13,11 @@ define([
     "firebug/lib/string",
     "firebug/lib/array",
     "firebug/lib/system",
-    "firebug/net/netUtils"
+    "firebug/net/netUtils",
+    "firebug/lib/xpcom"
 ],
 function(Obj, Firebug, Locale, Events, Url, SourceLink, Http, Css, Win, Str,
-    Arr, System, NetUtils) {
+    Arr, System, NetUtils, Xpcom) {
 
 // ********************************************************************************************* //
 // Constants
@@ -27,6 +28,10 @@ const Cr = Components.results;
 
 const CacheService = Cc["@mozilla.org/network/cache-service;1"];
 
+var versionChecker = Xpcom.CCSV("@mozilla.org/xpcom/version-comparator;1", "nsIVersionComparator");
+var appInfo = Xpcom.CCSV("@mozilla.org/xre/app-info;1", "nsIXULAppInfo");
+var fx18 = versionChecker.compare(appInfo.version, "18") >= 0;
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 const reIgnore = /about:|javascript:|resource:|chrome:|jar:/;
@@ -120,8 +125,28 @@ NetProgress.prototype =
 
     requestNumber: 1,
 
+    openingFile: function openingFile(request, win)
+    {
+        if (!fx18)
+            return;
+
+        var file = this.getRequestFile(request, win);
+        if (file)
+        {
+            // Parse URL params so, they are available for conditional breakpoints.
+            file.urlParams = Url.parseURLParams(file.href);
+            this.breakOnXHR(file);
+        }
+    },
+
     startFile: function startFile(request, win)
     {
+        // Called asynchronously since Fx17 so, can't be use for Break on XHR
+        // since JS stack is not available at the moment.
+        // See https://bugzilla.mozilla.org/show_bug.cgi?id=800799
+        if (fx18)
+            return;
+
         var file = this.getRequestFile(request, win);
         if (file)
         {
@@ -375,6 +400,20 @@ NetProgress.prototype =
             file.fromCache = true;
             file.aborted = false;
 
+            try
+            {
+                if (request instanceof Ci.nsIApplicationCacheChannel)
+                {
+                    if (request.loadedFromApplicationCache)
+                        file.fromAppCache = true;
+                }
+            }
+            catch (e)
+            {
+                if (FBTrace.DBG_ERRORS)
+                    FBTrace.sysout("net.respondedCacheFile ERROR " + e, e);
+            }
+
             if (request.contentLength >= 0)
                 file.size = request.contentLength;
 
diff --git a/trace/FBTrace/chrome/firebug/content/net/netReps.js b/trace/FBTrace/chrome/firebug/content/net/netReps.js
index 6a594ab..c0fd470 100644
--- a/trace/FBTrace/chrome/firebug/content/net/netReps.js
+++ b/trace/FBTrace/chrome/firebug/content/net/netReps.js
@@ -491,14 +491,14 @@ Firebug.NetMonitor.NetRequestEntry = domplate(Firebug.Rep, new Firebug.Listener(
             TD({"class": "netCol netProtocolCol a11yFocus", "role" : "gridcell"}),
             TD({"class": "netCol netDomainCol a11yFocus", "role" : "gridcell"}),
             TD({"class": "netTotalSizeCol netCol netSizeCol a11yFocus", "role": "gridcell"},
-                DIV({"class": "netTotalSizeLabel netSummaryLabel"}, "0KB")
+                DIV({"class": "netTotalSizeLabel netSummaryLabel"}, "0 B")
             ),
             TD({"class": "netTotalTimeCol netCol netTimeCol a11yFocus", "role":
                 "gridcell", colspan: "3"},
                 DIV({"class": "netSummaryBar", style: "width: 100%"},
                     DIV({"class": "netCacheSizeLabel netSummaryLabel", collapsed: "true"},
                         "(",
-                        SPAN("0KB"),
+                        SPAN("0 B"),
                         SPAN(" " + Locale.$STR("FromCache")),
                         ")"
                     ),
@@ -641,8 +641,11 @@ Firebug.NetMonitor.NetRequestEntry = domplate(Firebug.Rep, new Firebug.Listener(
 
     getHref: function(file)
     {
-        return (file.method ? file.method.toUpperCase() : "?") + " " +
-            Str.cropString(Url.getFileName(file.href), 40);
+        var fileName = Url.getFileName(file.href);
+        var limit = Options.get("stringCropLength");
+        if (limit > 0)
+            fileName = Str.cropString(fileName, limit);
+        return (file.method ? file.method.toUpperCase() : "?") + " " + fileName;
     },
 
     getProtocol: function(file)
@@ -665,10 +668,12 @@ Firebug.NetMonitor.NetRequestEntry = domplate(Firebug.Rep, new Firebug.Listener(
 
         text = text ? Str.cropString(text) : " ";
 
-        if (file.fromBFCache)
+        if (file.fromAppCache)
+            text += " (AppCache)";
+        else if (file.fromBFCache)
             text += " (BFCache)";
 
-        return text;
+        return text
     },
 
     getDomain: function(file)
@@ -684,24 +689,12 @@ Firebug.NetMonitor.NetRequestEntry = domplate(Firebug.Rep, new Firebug.Listener(
 
     getLocalAddress: function(file)
     {
-        var address = file.localAddress ? file.localAddress : "";
-        var port = file.localPort ? file.localPort : "";
-
-        var result = address;
-        result += result ? ":" : "";
-        result += port;
-        return result;
+        return Str.formatIP(file.localAddress, file.localPort);
     },
 
     getRemoteAddress: function(file)
     {
-        var address = file.remoteAddress ? file.remoteAddress : "";
-        var port = file.remotePort ? file.remotePort : "";
-
-        var result = address;
-        result += result ? ":" : "";
-        result += port;
-        return result;
+        return Str.formatIP(file.remoteAddress, file.remotePort);
     },
 
     getElapsedTime: function(file)
@@ -1240,8 +1233,7 @@ Firebug.NetMonitor.NetInfoBody = domplate(Firebug.Rep, new Firebug.Listener(),
             var object = {
                 text: Locale.$STR("net.responseSizeLimitMessage"),
                 onClickLink: function() {
-                    var panel = context.getPanel("net", true);
-                    panel.openResponseInTab(file);
+                    NetUtils.openResponseInTab(file);
                 }
             };
             Firebug.NetMonitor.ResponseSizeLimit.append(object, responseTextBox);
@@ -1641,13 +1633,13 @@ Firebug.NetMonitor.NetInfoHeaders = domplate(Firebug.Rep, new Firebug.Listener()
         {
             var headers = requestHeaders ? file.requestHeaders : file.responseHeaders;
             this.insertHeaderRows(netInfoBox, headers, target.rowName);
-            target.innerHTML = Locale.$STR("net.headers.view source");
+            target.textContent = Locale.$STR("net.headers.view source");
         }
         else
         {
             var source = requestHeaders ? file.requestHeadersText : file.responseHeadersText;
-            this.insertSource(netInfoBox, source, target.rowName);
-            target.innerHTML = Locale.$STR("net.headers.pretty print");
+            this.insertSource(netInfoBox, Str.escapeForTextNode(source), target.rowName);
+            target.textContent = Locale.$STR("net.headers.pretty print");
         }
 
         target.sourceDisplayed = !target.sourceDisplayed;
@@ -1965,7 +1957,7 @@ Firebug.NetMonitor.SizeInfoTip = domplate(Firebug.Rep,
 
     formatNumber: function(size)
     {
-        return size.size ? ("(" + Str.formatNumber(size.size) + ")") : "";
+        return size.size && size.size >= 1024 ? "(" + size.size.toLocaleString() + " B)" : "";
     },
 
     render: function(file, parentNode)
diff --git a/trace/FBTrace/chrome/firebug/content/net/netUtils.js b/trace/FBTrace/chrome/firebug/content/net/netUtils.js
index 2045d01..64a2f19 100644
--- a/trace/FBTrace/chrome/firebug/content/net/netUtils.js
+++ b/trace/FBTrace/chrome/firebug/content/net/netUtils.js
@@ -51,6 +51,8 @@ const mimeCategoryMap =
     "application/rss+xml": "html",
     "application/atom+xml": "html",
     "application/xhtml+xml": "html",
+    "application/mathml+xml": "html",
+    "application/rdf+xml": "html",
     "text/css": "css",
     "application/x-javascript": "js",
     "text/javascript": "js",
diff --git a/trace/FBTrace/chrome/firebug/content/net/requestObserver.js b/trace/FBTrace/chrome/firebug/content/net/requestObserver.js
index c6d3125..e885554 100644
--- a/trace/FBTrace/chrome/firebug/content/net/requestObserver.js
+++ b/trace/FBTrace/chrome/firebug/content/net/requestObserver.js
@@ -46,6 +46,7 @@ var HttpRequestObserver =
 
         if (!this.observing)
         {
+            observerService.addObserver(this, "http-on-opening-request", false);
             observerService.addObserver(this, "http-on-modify-request", false);
             observerService.addObserver(this, "http-on-examine-response", false);
             observerService.addObserver(this, "http-on-examine-cached-response", false);
@@ -62,6 +63,7 @@ var HttpRequestObserver =
 
         if (this.observing)
         {
+            observerService.removeObserver(this, "http-on-opening-request");
             observerService.removeObserver(this, "http-on-modify-request");
             observerService.removeObserver(this, "http-on-examine-response");
             observerService.removeObserver(this, "http-on-examine-cached-response");
@@ -83,7 +85,8 @@ var HttpRequestObserver =
             // Notify all registered observers.
             if (topic == "http-on-modify-request" ||
                 topic == "http-on-examine-response" ||
-                topic == "http-on-examine-cached-response")
+                topic == "http-on-examine-cached-response" ||
+                topic == "http-on-opening-request")
             {
                 this.notifyObservers(subject, topic, data);
             }
diff --git a/trace/FBTrace/chrome/firebug/content/net/responseObserver.js b/trace/FBTrace/chrome/firebug/content/net/responseObserver.js
index f742b83..9d3556c 100644
--- a/trace/FBTrace/chrome/firebug/content/net/responseObserver.js
+++ b/trace/FBTrace/chrome/firebug/content/net/responseObserver.js
@@ -15,7 +15,7 @@ const Ci = Components.interfaces;
 const Cr = Components.results;
 const Cu = Components.utils;
 
-const PrefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch2);
+const PrefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
 var redirectionLimit = PrefService.getIntPref("network.http.redirection-limit");
 
 // ********************************************************************************************* //
diff --git a/trace/FBTrace/chrome/firebug/content/net/spy.js b/trace/FBTrace/chrome/firebug/content/net/spy.js
index b6bc9c8..7387922 100644
--- a/trace/FBTrace/chrome/firebug/content/net/spy.js
+++ b/trace/FBTrace/chrome/firebug/content/net/spy.js
@@ -22,12 +22,13 @@ define([
     "firebug/trace/traceListener",
     "firebug/trace/traceModule",
     "firebug/lib/wrapper",
+    "firebug/lib/xpcom",
     "firebug/net/netPanel",
-    "firebug/console/errors"
+    "firebug/console/errors",
 ],
 function(Obj, Firebug, Domplate, FirebugReps, Events, HttpRequestObserver, StackFrame,
     Http, Css, Dom, Win, System, Str, Url, Arr, Debug, NetHttpActivityObserver, NetUtils,
-    TraceListener, TraceModule, Wrapper) {
+    TraceListener, TraceModule, Wrapper, Xpcom) {
 
 // ********************************************************************************************* //
 // Constants
@@ -35,9 +36,16 @@ function(Obj, Firebug, Domplate, FirebugReps, Events, HttpRequestObserver, Stack
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
+var eventListenerService = Cc["@mozilla.org/eventlistenerservice;1"].
+    getService(Ci.nsIEventListenerService);
+
 // List of contexts with XHR spy attached.
 var contexts = [];
 
+var versionChecker = Xpcom.CCSV("@mozilla.org/xpcom/version-comparator;1", "nsIVersionComparator");
+var appInfo = Xpcom.CCSV("@mozilla.org/xre/app-info;1", "nsIXULAppInfo");
+var fx18 = versionChecker.compare(appInfo.version, "18") >= 0;
+
 // ********************************************************************************************* //
 // Spy Module
 
@@ -86,14 +94,16 @@ Firebug.Spy = Obj.extend(Firebug.Module,
         // For any spies that are in progress, remove our listeners so that they don't leak
         this.detachObserver(context, null);
 
-        if (FBTrace.DBG_SPY && context.spies.length)
+        if (FBTrace.DBG_SPY && context.spies && context.spies.length)
+        {
             FBTrace.sysout("spy.destroyContext; ERROR There are spies in progress ("
                 + context.spies.length + ") " + context.getName());
+        }
 
         // Make sure that all Spies in progress are detached at this moment.
         // Clone the array beforehand since the spy object is removed from the
         // original array within detach.
-        var spies = Arr.cloneArray(context.spies);
+        var spies = context.spies ? Arr.cloneArray(context.spies) : [];
         for (var i=0; i<spies.length; i++)
             spies[i].detach(true);
 
@@ -276,16 +286,13 @@ var SpyHttpObserver =
     {
         try
         {
-            if (topic != "http-on-modify-request" &&
-                topic != "http-on-examine-response" &&
-                topic != "http-on-examine-cached-response")
+            if ((topic == "http-on-modify-request" && !fx18) ||
+                topic == "http-on-opening-request" ||
+                topic == "http-on-examine-response" ||
+                topic == "http-on-examine-cached-response")
             {
-                if (FBTrace.DBG_ERRORS || FBTrace.DBG_SPY)
-                    FBTrace.sysout("spy.SpyHttpObserver.observe; ERROR Unknown topic: " + topic);
-                return;
+                this.observeRequest(request, topic);
             }
-
-            this.observeRequest(request, topic);
         }
         catch (exc)
         {
@@ -313,7 +320,9 @@ var SpyHttpObserver =
                 var requestName = request.URI.asciiSpec;
                 var requestMethod = request.requestMethod;
 
-                if (topic == "http-on-modify-request")
+                if (topic == "http-on-modify-request" && !fx18)
+                    this.requestStarted(request, xhr, spyContext, requestMethod, requestName);
+                if (topic == "http-on-opening-request")
                     this.requestStarted(request, xhr, spyContext, requestMethod, requestName);
                 else if (topic == "http-on-examine-response")
                     this.requestStopped(request, xhr, spyContext, requestMethod, requestName);
@@ -526,6 +535,16 @@ function getSpyForXHR(request, xhrRequest, context, noCreate)
 {
     var spy = null;
 
+    if (!context.spies)
+    {
+        if (FBTrace.DBG_ERRORS)
+        {
+            FBTrace.sysout("spy.getSpyForXHR; ERROR no spies array " +
+                Http.safeGetRequestName(request));
+        }
+        return;
+    }
+
     // Iterate all existing spy objects in this context and look for one that is
     // already created for this request.
     var length = context.spies.length;
@@ -587,26 +606,45 @@ Firebug.Spy.XMLHttpRequestSpy.prototype =
     attach: function()
     {
         var spy = this;
+
         this.onReadyStateChange = function(event) { onHTTPSpyReadyStateChange(spy, event); };
         this.onLoad = function() { onHTTPSpyLoad(spy); };
         this.onError = function() { onHTTPSpyError(spy); };
         this.onAbort = function() { onHTTPSpyAbort(spy); };
 
-        // xxxHonza: #502959 is still failing on Fx 3.5
-        // Use activity distributor to identify 3.6
-        if (SpyHttpActivityObserver.getActivityDistributor())
+        this.onEventListener = function(event)
+        {
+            switch (event.type)
+            {
+                case "readystatechange":
+                    onHTTPSpyReadyStateChange(spy, event);
+                break;
+                case "load":
+                    onHTTPSpyLoad(spy);
+                break;
+                case "error":
+                    onHTTPSpyError(spy);
+                break;
+                case "abort":
+                    onHTTPSpyAbort(spy);
+                break;
+            }
+        };
+
+        if (typeof(eventListenerService.addListenerForAllEvents) == "function")
+        {
+            eventListenerService.addListenerForAllEvents(this.xhrRequest,
+                this.onEventListener, true, false, false);
+        }
+        else
         {
             this.onreadystatechange = this.xhrRequest.onreadystatechange;
             this.xhrRequest.onreadystatechange = this.onReadyStateChange;
-        }
 
-        this.xhrRequest.addEventListener("load", this.onLoad, false);
-        this.xhrRequest.addEventListener("error", this.onError, false);
-        this.xhrRequest.addEventListener("abort", this.onAbort, false);
-
-        // xxxHonza: should be removed from FB 3.6
-        if (!SpyHttpActivityObserver.getActivityDistributor())
-            this.context.sourceCache.addListener(this);
+            this.xhrRequest.addEventListener("load", this.onLoad, false);
+            this.xhrRequest.addEventListener("error", this.onError, false);
+            this.xhrRequest.addEventListener("abort", this.onAbort, false);
+        }
 
         if (FBTrace.DBG_SPY)
             FBTrace.sysout("spy.attach; " + Http.safeGetRequestName(this.request));
@@ -615,7 +653,7 @@ Firebug.Spy.XMLHttpRequestSpy.prototype =
     detach: function(force)
     {
         // Bubble out if already detached.
-        if (!this.onLoad)
+        if (!this.onEventListener)
             return;
 
         // If the activity distributor is available, let's detach it when the XHR
@@ -637,21 +675,27 @@ Firebug.Spy.XMLHttpRequestSpy.prototype =
         // Remove itself from the list of active spies.
         Arr.remove(this.context.spies, this);
 
-        if (this.onreadystatechange)
-            this.xhrRequest.onreadystatechange = this.onreadystatechange;
+        if (typeof(eventListenerService.addListenerForAllEvents) == "function")
+        {
+            eventListenerService.removeListenerForAllEvents(this.xhrRequest,
+                this.onEventListener, true, false);
+        }
+        else
+        {
+            if (this.onreadystatechange)
+                this.xhrRequest.onreadystatechange = this.onreadystatechange;
 
-        try { this.xhrRequest.removeEventListener("load", this.onLoad, false); } catch (e) {}
-        try { this.xhrRequest.removeEventListener("error", this.onError, false); } catch (e) {}
-        try { this.xhrRequest.removeEventListener("abort", this.onAbort, false); } catch (e) {}
+            try { this.xhrRequest.removeEventListener("load", this.onLoad, false); } catch (e) {}
+            try { this.xhrRequest.removeEventListener("error", this.onError, false); } catch (e) {}
+            try { this.xhrRequest.removeEventListener("abort", this.onAbort, false); } catch (e) {}
+        }
 
         this.onreadystatechange = null;
         this.onLoad = null;
         this.onError = null;
         this.onAbort = null;
 
-        // xxxHonza: shouuld be removed from FB 1.6
-        if (!SpyHttpActivityObserver.getActivityDistributor())
-            this.context.sourceCache.removeListener(this);
+        this.onEventListener = null;
     },
 
     getURL: function()
@@ -680,8 +724,10 @@ Firebug.Spy.XMLHttpRequestSpy.prototype =
 function onHTTPSpyReadyStateChange(spy, event)
 {
     if (FBTrace.DBG_SPY)
+    {
         FBTrace.sysout("spy.onHTTPSpyReadyStateChange " + spy.xhrRequest.readyState +
             " (multipart: " + spy.xhrRequest.multipart + ")");
+    }
 
     // Remember just in case spy is detached (readyState == 4).
     var originalHandler = spy.onreadystatechange;
@@ -710,16 +756,7 @@ function onHTTPSpyReadyStateChange(spy, event)
     if (spy.xhrRequest.readyState == 4)
     {
         // Cumulate response so that multipart response content is properly displayed.
-        if (SpyHttpActivityObserver.getActivityDistributor())
-        {
-            spy.responseText += Http.safeGetXHRResponseText(spy.xhrRequest);
-        }
-        else
-        {
-            // xxxHonza: remove from FB 1.6
-            if (!spy.responseText)
-                spy.responseText = Http.safeGetXHRResponseText(spy.xhrRequest);
-        }
+        spy.responseText += Http.safeGetXHRResponseText(spy.xhrRequest);
 
         // The XHR is loaded now (used also by the activity observer).
         spy.loaded = true;
@@ -740,7 +777,44 @@ function onHTTPSpyReadyStateChange(spy, event)
     }
 
     // Pass the event to the original page handler.
-    callPageHandler(spy, event, originalHandler);
+    if (typeof(eventListenerService.addListenerForAllEvents) == "undefined")
+        callPageHandler(spy, event, originalHandler);
+}
+
+function callPageHandler(spy, event, originalHandler)
+{
+    try
+    {
+        // Calling the page handler throwed an exception (see #502959)
+        // This should be fixed in Firefox 3.5
+        if (originalHandler && event)
+        {
+            if (originalHandler.handleEvent)
+                originalHandler.handleEvent(event);
+            else
+                originalHandler.call(spy.xhrRequest, event);
+        }
+    }
+    catch (exc)
+    {
+        if (FBTrace.DBG_ERRORS)
+            FBTrace.sysout("spy.onHTTPSpyReadyStateChange: EXCEPTION " + exc, [exc, event]);
+
+        var xpcError = Firebug.Errors.reparseXPC(exc, spy.context);
+        if (xpcError)
+        {
+            // TODO attach trace
+            if (FBTrace.DBG_ERRORS)
+                FBTrace.sysout("spy.onHTTPSpyReadyStateChange: reparseXPC", xpcError);
+
+            // Make sure the exception is displayed in both Firefox & Firebug console.
+            throw new Error(xpcError.message, xpcError.href, xpcError.lineNo);
+        }
+        else
+        {
+            throw exc;
+        }
+    }
 }
 
 function onHTTPSpyLoad(spy)
@@ -752,10 +826,6 @@ function onHTTPSpyLoad(spy)
     // onAbort would not be handled.
     spy.detach(false);
 
-    // xxxHonza: Still needed for Fx 3.5 (#502959)
-    if (!SpyHttpActivityObserver.getActivityDistributor())
-        onHTTPSpyReadyStateChange(spy, null);
-
     // If the spy is not loaded yet (and so, the response was not cached), do it now.
     // This can happen since synchronous XHRs don't fire onReadyStateChange event (issue 2868).
     if (!spy.loaded)
@@ -812,44 +882,6 @@ function onHTTPSpyAbort(spy)
 
 // ********************************************************************************************* //
 
-function callPageHandler(spy, event, originalHandler)
-{
-    try
-    {
-        // Calling the page handler throwed an exception (see #502959)
-        // This should be fixed in Firefox 3.5
-        if (originalHandler && event)
-        {
-            if (originalHandler.handleEvent)
-                originalHandler.handleEvent(event);
-            else
-                originalHandler.call(spy.xhrRequest, event);
-        }
-    }
-    catch (exc)
-    {
-        if (FBTrace.DBG_ERRORS)
-            FBTrace.sysout("spy.onHTTPSpyReadyStateChange: EXCEPTION " + exc, [exc, event]);
-
-        var xpcError = Firebug.Errors.reparseXPC(exc, spy.context);
-        if (xpcError) //
-        {
-            // TODO attach trace
-            if (FBTrace.DBG_ERRORS)
-                FBTrace.sysout("spy.onHTTPSpyReadyStateChange: reparseXPC", xpcError);
-
-            // Make sure the exception is displayed in both Firefox & Firebug console.
-            throw new Error(xpcError.message, xpcError.href, xpcError.lineNo);
-        }
-        else
-        {
-            throw exc;
-        }
-    }
-}
-
-// ********************************************************************************************* //
-
 /**
  * @domplate Represents a template for XHRs logged in the Console panel. The body of the
  * log (displayed when expanded) is rendered using {@link Firebug.NetMonitor.NetInfoBody}.
diff --git a/trace/FBTrace/chrome/firebug/content/net/xmlViewer.js b/trace/FBTrace/chrome/firebug/content/net/xmlViewer.js
index 499b32b..d6664e7 100644
--- a/trace/FBTrace/chrome/firebug/content/net/xmlViewer.js
+++ b/trace/FBTrace/chrome/firebug/content/net/xmlViewer.js
@@ -24,6 +24,7 @@ var xmlContentTypes =
     "application/rss+xml",
     "application/atom+xml",,
     "application/vnd.mozilla.maybe.feed",
+    "application/mathml+xml",
     "application/rdf+xml",
     "application/vnd.mozilla.xul+xml"
 ];
diff --git a/trace/FBTrace/chrome/firebug/content/trace.js b/trace/FBTrace/chrome/firebug/content/trace.js
index b9c12f9..494fdae 100644
--- a/trace/FBTrace/chrome/firebug/content/trace.js
+++ b/trace/FBTrace/chrome/firebug/content/trace.js
@@ -14,22 +14,22 @@ var FBTrace = {};
 try
 {
     var scope = {};
-    Components.utils["import"]("resource://firebug/firebug-trace-service.js", scope);
-    FBTrace = scope.traceConsoleService.getTracer("extensions.firebug");
+    Components.utils["import"]("resource://firebug/fbtrace.js", scope);
+    FBTrace = scope.FBTrace;
     FBTrace.setScope(window);
 
     function clearFBTraceScope()
     {
-        window.removeEventListener('unload', clearFBTraceScope, true);
+        window.removeEventListener("unload", clearFBTraceScope, true);
         FBTrace.setScope(null);
     }
 
-    window.addEventListener('unload', clearFBTraceScope, true);
+    window.addEventListener("unload", clearFBTraceScope, true);
     FBTrace.time("SCRIPTTAG_TIME");
 }
 catch (err)
 {
-    dump("FBTrace; " + err);
+    Components.utils.reportError(err);
 }
 
 // ********************************************************************************************* //
diff --git a/trace/FBTrace/chrome/firebug/modules/firebug-http-observer.js b/trace/FBTrace/chrome/firebug/modules/firebug-http-observer.js
index 9e7aee6..304b629 100644
--- a/trace/FBTrace/chrome/firebug/modules/firebug-http-observer.js
+++ b/trace/FBTrace/chrome/firebug/modules/firebug-http-observer.js
@@ -1,21 +1,22 @@
 /* See license.txt for terms of usage */
 
-// ************************************************************************************************
+// ********************************************************************************************* //
 // Constants
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
+const Cu = Components.utils;
 
 var EXPORTED_SYMBOLS = ["httpRequestObserver"];
 
 var observerService = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
 var categoryManager = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
 
-// ************************************************************************************************
-// HTTP Request Observer implementation
+Cu["import"]("resource://firebug/fbtrace.js");
 
-var FBTrace = null;
+// ********************************************************************************************* //
+// HTTP Request Observer implementation
 
 /**
  * @service This service is intended as the only HTTP observer registered by Firebug.
@@ -33,12 +34,6 @@ var httpRequestObserver =
     {
         this.observers = [];
         this.observing = 0;
-
-        // Get firebug-trace service for logging (the service should be already
-        // registered at this moment).
-        Components.utils["import"]("resource://firebug/firebug-trace-service.js");
-        FBTrace = traceConsoleService.getTracer("extensions.firebug");
-
         this.initialize();
     },
 
@@ -66,6 +61,7 @@ var httpRequestObserver =
 
         if (!this.observing)
         {
+            observerService.addObserver(this, "http-on-opening-request", false);
             observerService.addObserver(this, "http-on-modify-request", false);
             observerService.addObserver(this, "http-on-examine-response", false);
             observerService.addObserver(this, "http-on-examine-cached-response", false);
@@ -82,6 +78,7 @@ var httpRequestObserver =
 
         if (this.observing)
         {
+            observerService.removeObserver(this, "http-on-opening-request");
             observerService.removeObserver(this, "http-on-modify-request");
             observerService.removeObserver(this, "http-on-examine-response");
             observerService.removeObserver(this, "http-on-examine-cached-response");
@@ -109,7 +106,8 @@ var httpRequestObserver =
                     ", " + safeGetName(subject));
 
             // Notify all registered observers.
-            if (topic == "http-on-modify-request" ||
+            if (topic == "http-on-opening-request" ||
+                topic == "http-on-modify-request" ||
                 topic == "http-on-examine-response" ||
                 topic == "http-on-examine-cached-response")
             {
@@ -185,7 +183,7 @@ var httpRequestObserver =
     }
 }
 
-// ************************************************************************************************
+// ********************************************************************************************* //
 // Request helpers
 
 function safeGetName(request)
@@ -201,9 +199,9 @@ function safeGetName(request)
     return null;
 }
 
-// ************************************************************************************************
+// ********************************************************************************************* //
+// Debugging Helpers
 
-// Debugging helper.
 function dumpStack(message)
 {
     dump(message + "\n");
@@ -220,7 +218,9 @@ function dumpStack(message)
     }
 }
 
-// ************************************************************************************************
+// ********************************************************************************************* //
 // Initialization
 
 httpRequestObserver.preInitialize();
+
+// ********************************************************************************************* //
diff --git a/trace/FBTrace/chrome/firebug/modules/firebug-service.js b/trace/FBTrace/chrome/firebug/modules/firebug-service.js
index 4299987..3ecc89f 100644
--- a/trace/FBTrace/chrome/firebug/modules/firebug-service.js
+++ b/trace/FBTrace/chrome/firebug/modules/firebug-service.js
@@ -30,7 +30,6 @@ const jsdIErrorHook = Ci.jsdIErrorHook;
 const jsdIFilter = Components.interfaces.jsdIFilter;
 const nsISupports = Ci.nsISupports;
 const nsIPrefBranch = Ci.nsIPrefBranch;
-const nsIPrefBranch2 = Ci.nsIPrefBranch2;
 const nsIComponentRegistrar = Ci.nsIComponentRegistrar;
 const nsIFactory = Ci.nsIFactory;
 const nsIConsoleService = Ci.nsIConsoleService;
@@ -147,7 +146,7 @@ var errorInfo = null;
 var timer = Timer.createInstance(nsITimer);
 var waitingForTimer = false;
 
-var FBTrace = null;
+Cu.import("resource://firebug/fbtrace.js");
 
 // ********************************************************************************************* //
 
@@ -729,10 +728,6 @@ var fbs =
 {
     initialize: function()
     {
-        Components.utils.import("resource://firebug/firebug-trace-service.js");
-
-        FBTrace = traceConsoleService.getTracer("extensions.firebug");
-
         if (FBTrace.DBG_FBS_ERRORS)
             FBTrace.sysout("fbs.FirebugService Starting");
 
@@ -754,7 +749,7 @@ var fbs =
 
         this.profiling = false;
 
-        prefs = PrefService.getService(nsIPrefBranch2);
+        prefs = PrefService.getService(nsIPrefBranch);
         fbs.prefDomain = "extensions.firebug";
         prefs.addObserver(fbs.prefDomain, fbs, false);
 
@@ -1576,61 +1571,8 @@ var fbs =
 
     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
-    /**
-     * Do not activate JSD, which is broken in Firefox 9 on Mac and Linux 32 bit
-     * This method is checking the current platform & browser configuration and 
-     * return false for Mac/Linux 32 bit
-     *
-     * See: https://bugzilla.mozilla.org/show_bug.cgi?id=712289
-     *
-     * Can be removed when the min Firefox version is 10
-     * 
-     * Search for 'bug712289' within the source code to remove all find all related
-     * parts of this workaround.
-     */
-    isJSDAvailable: function()
-    {
-        if (typeof(this._isJSDAvailable) == "undefined")
-        {
-            var systemInfo = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime);
-
-            // Check the current OS, must not be Mac or Linux 32 bit
-            var os = systemInfo.XPCOMABI == "x86-gcc3";
-
-            // Check the current Firefox version, must not be 9
-            systemInfo = systemInfo.QueryInterface(Ci.nsIXULAppInfo);
-            var ff = systemInfo.version.indexOf("9.") == 0;
-
-            // If one or another is false, JSD is available.
-            this._isJSDAvailable = !(os && ff);
-
-            if (!this._isJSDAvailable)
-            {
-                try
-                {
-                    consoleService = ConsoleService.getService(nsIConsoleService);
-                    consoleService.logStringMessage(
-                        "WARNING: Firebug Script panel is disabled in Firefox " +
-                        systemInfo.version + " running on 32 bit Mac or Linux (" +
-                        systemInfo.XPCOMABI + ")");
-                }
-                catch (err)
-                {
-                }
-            }
-        }
-
-        return this._isJSDAvailable;
-    },
-
-    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
     enableDebugger: function()
     {
-        // bug712289
-        if (!this.isJSDAvailable())
-            return;
-
         if (waitingForTimer)
         {
             timer.cancel();
@@ -3816,7 +3758,7 @@ var fbs =
             var bps = breakpointStore.getItem(url);
 
             // Do not restore "Run unit this line" breakpoints. This should solve complaints
-            // about Firebug braking in the sourece even if there are no breakpoints in
+            // about Firebug breaking in the source even if there are no breakpoints in
             // Firebug UI.
             if (bps.type == BP_UNTIL)
                 continue;
@@ -4096,7 +4038,7 @@ var fbs =
 
                     // stack empty
                     if (unhookAtBottom && hookFrameCount == 0)
-                       this.unhookFunctions();
+                       fbs.unhookFunctions();
 
                     contextCached = callBack(contextCached, frame, hookFrameCount, false);
                     break;
diff --git a/trace/FBTrace/chrome/firebug/modules/firebug-trace-service.js b/trace/FBTrace/chrome/firebug/modules/firebug-trace-service.js
index 830dd61..413f63f 100644
--- a/trace/FBTrace/chrome/firebug/modules/firebug-trace-service.js
+++ b/trace/FBTrace/chrome/firebug/modules/firebug-trace-service.js
@@ -1,37 +1,290 @@
 /* See license.txt for terms of usage */
 
-// ************************************************************************************************
+// ********************************************************************************************* //
 // Constants
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
+const Cu = Components.utils;
 
 var EXPORTED_SYMBOLS = ["traceConsoleService"];
 
-// ************************************************************************************************
-// Service implementation
+const PrefService = Cc["@mozilla.org/preferences-service;1"];
+const prefs = PrefService.getService(Ci.nsIPrefBranch);
+const prefService = PrefService.getService(Ci.nsIPrefService);
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/AddonManager.jsm");
+
+// xxxHonza: could we remove some of them?
+var TraceAPI = ["dump", "sysout", "setScope", "matchesNode", "time", "timeEnd"];
+
+// ********************************************************************************************* //
+// Service Implementation
 
-/**
- * This implementation serves as a proxy to the FBTrace extension. All logs are forwarded
- * to the FBTrace service.
- */
 try
 {
-    Components.utils["import"]("resource://fbtrace/firebug-trace-service.js");
+    Cu["import"]("resource://fbtrace/firebug-trace-service.js");
 }
 catch (err)
 {
+    // Tracing Console is not available yet, let's use a fake one.
     var traceConsoleService =
     {
+        tracers: {},
+
         getTracer: function(prefDomain)
         {
-            var TraceAPI = ["dump", "sysout", "setScope", "matchesNode", "time", "timeEnd"];
-            var TraceObj = {};
-            for (var i=0; i<TraceAPI.length; i++)
-                TraceObj[TraceAPI[i]] = function() {};
-            return TraceObj;
+            var tracer = this.tracers[prefDomain];
+            if (tracer)
+                return tracer;
+
+            var enabledAddons = decodeURIComponent(getCharPref("extensions", "enabledAddons"));
+            if (enabledAddons.indexOf("fbtrace at getfirebug.com:") >= 0)
+            {
+                // Solution with built-in buffer for logs created before console is ready.
+                var wrapper = new TracerWrapper(prefDomain);
+                tracer = wrapper.createTracer();
+            }
+            else
+            {
+                // Simple empty implementation for cases where Firebug Tracing Console
+                // is not even installed or 'alwaysOpenTraceConsole' is set to false.
+                tracer = {};
+                for (var i=0; i<TraceAPI.length; i++)
+                    tracer[TraceAPI[i]] = function() {};
+            }
+
+            this.tracers[prefDomain] = tracer;
+            return tracer;
+        },
+    }
+}
+
+// ********************************************************************************************* //
+// Tracer Wrapper
+
+/**
+ * Trace Wrapper represents a temporary Trace object that is used till the real Tracing
+ * Console is opened and available to use. Trace Wrapper implements a buffer that
+ * collects all logs and flushes them as intot the real console as soon as it's ready.
+ *
+ * In order to use this functionality, you need to set:
+ *    'extensions.firebug.alwaysOpenTraceConsole' to true
+ *
+ * @param {Object} prefDomain Associated pref domain. Usually 'extensions.firebug'
+ */
+function TracerWrapper(prefDomain)
+{
+    this.prefDomain = prefDomain;
+}
+
+TracerWrapper.prototype =
+{
+    // Temporary trace object
+    tracer: null,
+
+    // Buffer with logs used till the Tracing Console UI is available
+    queue: [],
+
+    // The real tracing console tracer object.
+    FBTrace: null,
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+    // Tracer
+
+    createTracer: function()
+    {
+        var self = this;
+
+        this.addObserver();
+
+        // Default FBTrace implementation puts all calls in a buffer.
+        // It'll be used as soon as the console is ready.
+        function createHandler(method)
+        {
+            return function() {
+                self.push(method, arguments);
+            }
+        };
+
+        // Fake FBTrace object
+        this.tracer = {};
+
+        // Dynamically create APIs.
+        for (var i=0; i<TraceAPI.length; i++)
+        {
+            var method = TraceAPI[i];
+            this.tracer[method] = createHandler(method);
+        }
+
+        var branch = prefService.getBranch(this.prefDomain);
+        var arrayDesc = {};
+
+        // Set options from preferences.
+        var children = branch.getChildList("", arrayDesc);
+        for (var i=0; i<children.length; i++)
+        {
+            var name = children[i];
+            var m = name.indexOf("DBG_");
+            if (m != -1)
+            {
+                var optionName = name.substr(1); // drop leading .
+                this.tracer[optionName] = getBoolPref(this.prefDomain, optionName);
+            }
+        }
+
+        // Create FBTrace proxy. As soon as FBTrace console is available it'll forward
+        // all calls to it.
+        return Proxy.create(
+        {
+            get: function(target, name)
+            {
+                if (self.FBTrace)
+                    return self.FBTrace[name];
+
+                return self.FBTrace ? self.FBTrace[name] : self.tracer[name];
+            },
+
+            set: function(target, name, value)
+            {
+                if (self.FBTrace)
+                    self.FBTrace[name] = value;
+
+                return true;
+            },
+        });
+    },
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+    // Buffer
+
+    push: function(method, args)
+    {
+        if (!this.queue)
+            return;
+
+        this.queue.push({
+            method: method,
+            args: args,
+        });
+
+        // Size of the buffer is limited.
+        while (this.queue.length > 1000)
+            this.queue.pop();
+    },
+
+    clearBuffer: function()
+    {
+        this.queue = null;
+    },
+
+    flush: function()
+    {
+        if (!this.FBTrace || !this.queue)
+            return;
+
+        if (this.queue.length > 0)
+            this.FBTrace.sysout("FBTrace: flush " + this.queue.length + " buffered logs:");
+
+        for (var i=0; i<this.queue.length; i++)
+        {
+            var call = this.queue[i];
+            this.FBTrace[call.method].apply(this.FBTrace, call.args);
+        }
+
+        this.clearBuffer();
+    },
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+    // FBTrace Console Observer
+
+    addObserver: function()
+    {
+        // Listen for new windows, Firebug must be loaded into them too.
+        Services.obs.addObserver(this, "chrome-document-global-created", false);
+    },
+
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
+    observe: function windowWatcher(win, topic, data)
+    {
+        // xxxHonza: the window should be associated with the same prefDomain.
+        if (win.location.href == "chrome://fbtrace/content/traceLogFrame.html")
+        {
+            var self = this;
+
+            // https://bugzil.la/795961 ?
+            win.addEventListener("load", function onLoad(evt)
+            { 
+                // load listener not necessary once https://bugzil.la/800677 is fixed
+                var win = evt.currentTarget;
+                win.removeEventListener("load", onLoad, false);
+
+                self.initFBTrace(self.prefDomain);
+            }, false);
+        }
+    },
+
+    initFBTrace: function()
+    {
+        if (this.FBTrace)
+            return this.FBTrace;
+
+        try
+        {
+            var scope = {};
+            Cu.import("resource://fbtrace/firebug-trace-service.js", scope);
+            this.FBTrace = scope.traceConsoleService.getTracer(this.prefDomain);
+
+            // FBTrace Console is ready let's flush the log buffer.
+            this.flush();
+        }
+        catch (err)
+        {
         }
-    };
+    }
+}
+
+// ********************************************************************************************* //
+// Helpers
+
+function getStackDump()
+{
+    var lines = [];
+    for (var frame = Components.stack; frame; frame = frame.caller)
+        lines.push(frame.filename + " (" + frame.lineNumber + ")");
+
+    return lines.join("\n");
+};
+
+function getBoolPref(prefDomain, name)
+{
+    try
+    {
+        var prefName = prefDomain + "." + name;
+        return prefs.getBoolPref(prefName);
+    }
+    catch (err)
+    {
+    }
+
+    return false;
+}
+
+function getCharPref(prefDomain, name)
+{
+    try
+    {
+        var prefName = prefDomain + "." + name;
+        return prefs.getCharPref(prefName);
+    }
+    catch (err)
+    {
+    }
+
+    return false;
 }
 
+// ********************************************************************************************* //
diff --git a/trace/FBTrace/chrome/firebug/modules/gcli.js b/trace/FBTrace/chrome/firebug/modules/gcli.js
index c8210af..ac06469 100644
--- a/trace/FBTrace/chrome/firebug/modules/gcli.js
+++ b/trace/FBTrace/chrome/firebug/modules/gcli.js
@@ -7,7 +7,7 @@ var Cc = Components.classes;
 var Ci = Components.interfaces;
 var Cu = Components.utils;
 
-var EXPORTED_SYMBOLS = [];
+var EXPORTED_SYMBOLS = ["FirebugGCLICommands"];
 
 // ********************************************************************************************* //
 // GCLI
@@ -24,12 +24,28 @@ catch (err)
         FBTrace.sysout("GCLI not available");
 }
 
+// Load the Locale module and make sure Firebug string bundle is registered
+// (GCLI commands needs to be localized)
+var Locale = Cu.import("resource://firebug/locale.js").Locale;
+Locale.registerStringBundle("chrome://firebug/locale/firebug.properties");
+
 if (scope.gcli) {
 
 // ********************************************************************************************* //
-// Services
+// FirebugGCLICommands
 
-var Locale = Cu.import("resource://firebug/locale.js").Locale;
+var FirebugGCLICommands =
+{
+    startup: function()
+    {
+        registerCommands();
+    },
+
+    shutdown: function()
+    {
+        unregisterCommands();
+    }
+}
 
 // ********************************************************************************************* //
 // Command Implementation
@@ -90,7 +106,7 @@ var FirebugController =
         if (!Firebug)
             return;
 
-        Firebug.GlobalUI.startFirebug(function(Firebug) {
+        Firebug.browserOverlay.startFirebug(function(Firebug) {
             callback(Firebug);
         });
     },
@@ -99,40 +115,59 @@ var FirebugController =
 // ********************************************************************************************* //
 // Registration
 
-scope.gcli.addCommand({
-    name: "firebug",
-    description: "Web Development Evolved"
-});
-
-scope.gcli.addCommand({
-    name: "firebug open",
-    description: Locale.$STR("firebug.menu.tip.Open_Firebug"),
-    exec: FirebugController.openFirebug.bind(FirebugController)
-});
-
-scope.gcli.addCommand({
-    name: "firebug hide",
-    description: Locale.$STR("firebug.menu.tip.Minimize_Firebug"),
-    exec: FirebugController.hideFirebug.bind(FirebugController)
-});
-
-scope.gcli.addCommand({
-    name: "firebug close",
-    description: Locale.$STR("firebug.shortcut.tip.closeFirebug"),
-    exec: FirebugController.closeFirebug.bind(FirebugController)
-});
-
-scope.gcli.addCommand({
-    name: "firebug detach",
-    description: Locale.$STR("firebug.DetachFirebug"),
-    exec: FirebugController.detachFirebug.bind(FirebugController)
-});
-
-scope.gcli.addCommand({
-    name: "firebug attach",
-    description: Locale.$STR("firebug.AttachFirebug"),
-    exec: FirebugController.attachFirebug.bind(FirebugController)
-});
+var commands = [];
+
+function addCommand(command)
+{
+    scope.gcli.addCommand(command);
+    commands.push(command);
+}
+
+function registerCommands()
+{
+    addCommand({
+        name: "firebug",
+        description: "Web Development Evolved"
+    });
+
+    addCommand({
+        name: "firebug open",
+        description: Locale.$STR("firebug.menu.tip.Open_Firebug"),
+        exec: FirebugController.openFirebug.bind(FirebugController)
+    });
+
+    addCommand({
+        name: "firebug hide",
+        description: Locale.$STR("firebug.menu.tip.Minimize_Firebug"),
+        exec: FirebugController.hideFirebug.bind(FirebugController)
+    });
+
+    addCommand({
+        name: "firebug close",
+        description: Locale.$STR("firebug.shortcut.tip.closeFirebug"),
+        exec: FirebugController.closeFirebug.bind(FirebugController)
+    });
+
+    addCommand({
+        name: "firebug detach",
+        description: Locale.$STR("firebug.DetachFirebug"),
+        exec: FirebugController.detachFirebug.bind(FirebugController)
+    });
+
+    addCommand({
+        name: "firebug attach",
+        description: Locale.$STR("firebug.AttachFirebug"),
+        exec: FirebugController.attachFirebug.bind(FirebugController)
+    });
+}
+
+function unregisterCommands()
+{
+    for (var i=0; i<commands.length; i++)
+        scope.gcli.removeCommand(commands[i]);
+
+    commands = [];
+}
 
 // ********************************************************************************************* //
 }
diff --git a/trace/FBTrace/chrome/firebug/modules/loader.js b/trace/FBTrace/chrome/firebug/modules/loader.js
index 0e0653a..7b9fd9e 100644
--- a/trace/FBTrace/chrome/firebug/modules/loader.js
+++ b/trace/FBTrace/chrome/firebug/modules/loader.js
@@ -10,10 +10,7 @@ var Ci = Components.interfaces;
 var Cu = Components.utils;
 
 Cu.import("resource://gre/modules/Services.jsm");
-
-// xxxHonza: this breaks tracing, needs to be fixed.
-//Components.utils.import("resource://firebug/fbtrace.js");
-var FBTrace = {};
+Cu.import("resource://firebug/fbtrace.js");
 
 // ********************************************************************************************* //
 
@@ -118,28 +115,50 @@ var FirebugLoader =
         }
 
         [getRoots(win.document), getRoots(win.gNavToolbox.palette),
-            fbug.GlobalUI.nodesToRemove].forEach(function(list)
+            fbug.browserOverlay.nodesToRemove].forEach(function(list)
         {
             for each(var el in list)
                 if (el && el.parentNode)
                     el.parentNode.removeChild(el);
         });
 
+        win.Firebug.browserOverlay.unloadContextMenuOverlay(win);
+
         delete win.Firebug;
         delete win.FBTrace;
         delete win.FBL;
     },
 
-    loadIntoWindow: function(win)
+    loadIntoWindow: function(win, reason)
     {
         // This is the place where the global Firebug object is created. This object represents
         // the entire application and all consequently created namespaces and variables should be
         // injected into it.
         // In the future, there should *not* be any other globals except of the Firebug object.
+        // xxxHonza: properties from this object are copied into the new Firebug obect that is
+        // created within "firebug/firebug" module (a hack).
         win.Firebug = {};
 
-        // Apply all Firefox/SeaMonkey overlays to the browser window.
-        loadSubscript("chrome://firebug/content/firefox/browserOverlay.js", win);
+        var requireScope = {};
+        Cu.import("resource://firebug/mini-require.js", requireScope);
+        var require = requireScope.require;
+
+        var config = {
+            baseUrl: "resource://",
+            paths: {"firebug": "chrome://firebug/content"}
+        };
+
+        require(config, [
+            "firebug/firefox/browserOverlay"
+        ],
+        function(BrowserOverlay)
+        {
+            var overlay = win.Firebug.browserOverlay = new BrowserOverlay(win);
+            overlay.initialize(reason);
+        });
+
+        if (FBTrace.DBG_MODULES)
+            FBTrace.sysout("Basic loader dependencies: " + require.Loader.getDepDesc());
 
         // Firebug extensions should initialize here.
         this.dispatchToScopes("topWindowLoad", [win]);
diff --git a/trace/FBTrace/chrome/firebug/modules/locale.js b/trace/FBTrace/chrome/firebug/modules/locale.js
index 751e914..d3baede 100644
--- a/trace/FBTrace/chrome/firebug/modules/locale.js
+++ b/trace/FBTrace/chrome/firebug/modules/locale.js
@@ -14,23 +14,9 @@ var EXPORTED_SYMBOLS = [];
 // ********************************************************************************************* //
 // Services
 
-// xxxHonza: FBTrace console doesn't have to exist at this point (Firebug is bootstrapped).
-// In such case an empty object is created and all consequent logs are not visible in the
-// console window.
-// Cu.import("resource://firebug/fbtrace.js");
-
-var consoleService = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
-
-// Just workaround for this module.
-var FBTrace = {sysout: function(msg)
-{
-    consoleService.logStringMessage(msg);
-}};
-
+Cu.import("resource://firebug/fbtrace.js");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://firebug/prefLoader.js");
-
-// Import of PluralForm object.
 Cu.import("resource://gre/modules/PluralForm.jsm");
 
 // ********************************************************************************************* //
diff --git a/trace/FBTrace/chrome/firebug/modules/mini-require.js b/trace/FBTrace/chrome/firebug/modules/mini-require.js
index e05c73c..318da68 100644
--- a/trace/FBTrace/chrome/firebug/modules/mini-require.js
+++ b/trace/FBTrace/chrome/firebug/modules/mini-require.js
@@ -3,6 +3,8 @@
 // ********************************************************************************************* //
 // Module Loader Implementation
 
+var EXPORTED_SYMBOLS = ["require", "define"];
+
 var require, define;
 
 (function() {
@@ -15,6 +17,7 @@ var Cc = Components.classes;
 var Ci = Components.interfaces;
 
 Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://firebug/fbtrace.js");
 
 // ********************************************************************************************* //
 // Module Loader implementation
@@ -196,7 +199,16 @@ var Loader =
         }
 
         return deps;
-    }
+    },
+
+    getDepDesc: function()
+    {
+        var desc = "";
+        var deps = this.getDeps();
+        for (var p in deps)
+            desc += p + "\n";
+        return desc;
+    },
 }
 
 // ********************************************************************************************* //
@@ -205,6 +217,7 @@ var Loader =
 require = Loader.require.bind(Loader);
 define = Loader.define.bind(Loader);
 require.load = Loader.load.bind(Loader);
+require.Loader = Loader;
 
 // ********************************************************************************************* //
 })();
diff --git a/trace/FBTrace/chrome/firebug/modules/observer-service.js b/trace/FBTrace/chrome/firebug/modules/observer-service.js
index 58881d7..64f8bad 100644
--- a/trace/FBTrace/chrome/firebug/modules/observer-service.js
+++ b/trace/FBTrace/chrome/firebug/modules/observer-service.js
@@ -6,11 +6,11 @@
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
+const Cu = Components.utils;
 
 var EXPORTED_SYMBOLS = ["fbObserverService"];
 
-Components.utils.import("resource://firebug/firebug-trace-service.js");
-var FBTrace = traceConsoleService.getTracer("extensions.firebug");
+Cu.import("resource://firebug/fbtrace.js");
 
 // ********************************************************************************************* //
 // Observer implementation
diff --git a/trace/FBTrace/chrome/firebug/modules/prefLoader.js b/trace/FBTrace/chrome/firebug/modules/prefLoader.js
index 01238f2..e40ff59 100644
--- a/trace/FBTrace/chrome/firebug/modules/prefLoader.js
+++ b/trace/FBTrace/chrome/firebug/modules/prefLoader.js
@@ -144,6 +144,11 @@ function setPref(name, value)
     return value;
 }
 
+function forceSave()
+{
+    Services.prefs.savePrefFile(null);
+}
+
 // ********************************************************************************************* //
 // Registration
 
@@ -151,5 +156,6 @@ PrefLoader.loadDefaultPrefs = loadDefaultPrefs;
 PrefLoader.clearDefaultPrefs = clearDefaultPrefs;
 PrefLoader.getPref = getPref;
 PrefLoader.setPref = setPref;
+PrefLoader.forceSave = forceSave;
 
 // ********************************************************************************************* //
diff --git a/trace/FBTrace/chrome/firebug/modules/require-debug.js b/trace/FBTrace/chrome/firebug/modules/require-debug.js
index 91c7169..10efe4f 100644
--- a/trace/FBTrace/chrome/firebug/modules/require-debug.js
+++ b/trace/FBTrace/chrome/firebug/modules/require-debug.js
@@ -1,37 +1,7 @@
-/*Software License Agreement (BSD License)
-
-Copyright (c) 2007, Parakey Inc.
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of Parakey Inc. nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of Parakey Inc.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
-IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
-IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
-OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-*/
-// johnjbarton at johnjbarton.com May 2011 IBM Corp.
+/* See license.txt for terms of usage */
 
+// ********************************************************************************************* //
+// johnjbarton at johnjbarton.com May 2011 IBM Corp.
 // Extend require.js to add debugging information
 // Include this file immediately after require.js
 // ********************************************************************************************* //
diff --git a/trace/FBTrace/chrome/firebug/modules/storageService.js b/trace/FBTrace/chrome/firebug/modules/storageService.js
index 9f98065..1465b3d 100644
--- a/trace/FBTrace/chrome/firebug/modules/storageService.js
+++ b/trace/FBTrace/chrome/firebug/modules/storageService.js
@@ -6,14 +6,15 @@
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
+const Cu = Components.utils;
 
 const dirService = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
 
 // https://developer.mozilla.org/en/Using_JavaScript_code_modules
 var EXPORTED_SYMBOLS = ["Storage", "StorageService", "TextService"];
 
-Components.utils["import"]("resource://firebug/firebug-trace-service.js");
-var FBTrace = traceConsoleService.getTracer("extensions.firebug");
+Cu.import("resource://firebug/fbtrace.js");
+Cu.import("resource://gre/modules/FileUtils.jsm");
 
 // ********************************************************************************************* //
 // Implementation
@@ -92,7 +93,7 @@ Storage.prototype =
     {
         this.objectTable = {};
         StorageService.setStorage(this, now);
-    },
+    }
 };
 
 // ********************************************************************************************* //
@@ -139,7 +140,7 @@ var StorageService =
     removeStorage: function(leafName)
     {
         ObjectPersister.deleteObject(leafname);
-    },
+    }
 };
 
 // ********************************************************************************************* //
@@ -150,39 +151,12 @@ var StorageService =
  */
 var ObjectPersister =
 {
-    getProfileDirectory: function()
-    {
-        var file = dirService.get("ProfD", Ci.nsIFile);
-        return file;
-    },
-
-    getFileInDirectory: function(file, path)  // forward slash separated
-    {
-        var segs = path.split('/');
-        for (var i = 0; i < segs.length; i++)
-        {
-            file.append(segs[i]);
-        }
-        return file;
-    },
-
-    getFileInProfileDirectory: function(path)
-    {
-        // Get persistence file stored within the profile directory.
-        var file = ObjectPersister.getProfileDirectory();
-        file = ObjectPersister.getFileInDirectory(file, path);
-        if (FBTrace.DBG_STORAGE)
-            FBTrace.sysout("ObjectPersister getFileInProfileDirectory("+path+")="+file.path);
-
-        return file;
-    },
-
     readObject: function(leafName)
     {
         if (FBTrace.DBG_STORAGE)
             FBTrace.sysout("ObjectPersister read from leafName "+leafName);
 
-        var file = ObjectPersister.getFileInProfileDirectory("firebug/"+leafName);
+        var file = FileUtils.getFile("ProfD", ["firebug", leafName]);
 
         if (!file.exists())
         {
@@ -283,7 +257,7 @@ var ObjectPersister =
         {
             // Convert data to JSON.
             var jsonString = JSON.stringify(obj);
-            var file = ObjectPersister.getFileInProfileDirectory("firebug/"+leafName);
+            var file = FileUtils.getFile("ProfD", ["firebug", leafName]);
             ObjectPersister.writeTextToFile(file, jsonString);
         }
         catch(exc)
@@ -345,9 +319,7 @@ var ObjectPersister =
 var TextService =
 {
     readText: ObjectPersister.readTextFromFile,
-    writeText: ObjectPersister.writeTextToFile,
-    getProfileDirectory: ObjectPersister.getProfileDirectory,
-    getFileInDirectory: ObjectPersister.getFileInDirectory,
+    writeText: ObjectPersister.writeTextToFile
 };
 
 // ********************************************************************************************* //
diff --git a/trace/FBTrace/chrome/firebug/skin/classic/callstack.css b/trace/FBTrace/chrome/firebug/skin/classic/callstack.css
index 159e388..46633dd 100644
--- a/trace/FBTrace/chrome/firebug/skin/classic/callstack.css
+++ b/trace/FBTrace/chrome/firebug/skin/classic/callstack.css
@@ -69,3 +69,11 @@
     display: none;
 }
 
+/*************************************************************************************************/
+/* FunctionCall log */
+
+.objectBox-functionCall {
+    padding-left: 17px;
+    cursor: default;
+    position: relative;
+}
diff --git a/trace/FBTrace/chrome/firebug/skin/classic/console.css b/trace/FBTrace/chrome/firebug/skin/classic/console.css
index ed9cd04..289cfaf 100644
--- a/trace/FBTrace/chrome/firebug/skin/classic/console.css
+++ b/trace/FBTrace/chrome/firebug/skin/classic/console.css
@@ -1,4 +1,3 @@
-/* See license.txt for terms of usage */
 
 .panelNode-console {
     overflow-x: hidden;
@@ -18,7 +17,7 @@
 }
 
 .logGroup {
-    background: #FFFFFF -moz-linear-gradient(top, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1) 18px, transparent 51px) repeat-x;
+    background: #FFFFFF linear-gradient(to bottom, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1) 18px, transparent 51px) repeat-x;
     padding: 0;
     border: none;
 }
@@ -57,6 +56,7 @@
 .logRow-error,
 .logRow-assert,
 .logRow-warningMessage,
+.logRow-loading,
 .logRow-errorMessage {
     padding-left: 22px;
     background-repeat: no-repeat;
@@ -100,6 +100,10 @@
     background-image: url(chrome://firebug/skin/info.svg);
 }
 
+.logRow-loading {
+    background-image: url(chrome://firebug/skin/loading.svg);
+}
+
 .logRow-warn,
 .logRow-warningMessage {
     background-image: url(chrome://firebug/skin/warning.svg);
@@ -156,6 +160,7 @@
 
 .objectBox-null,
 .objectBox-undefined,
+.objectBox-hint,
 .logRowHint {
     font-style: italic;
     color: #787878;
@@ -349,7 +354,7 @@
     border-bottom: 1px solid #9C9C9C;
     padding: 0 !important;
     font-weight: bold;
-    background: #C8C8C8 -moz-linear-gradient(top, rgba(255, 255, 255, 0.3), rgba(0, 0, 0, 0.2));
+    background: #C8C8C8 linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(0, 0, 0, 0.2));
 }
 
 .headerCellBox {
@@ -448,9 +453,9 @@
 
 /*************************************************************************************************/
 
+.objectLink-event,
+.objectLink-eventLog,
 .objectLink-regexp,
-.objectLink-Storage,
-.objectLink-StorageList,
 .objectLink-object,
 .objectLink-Date {
     font-family: Lucida Grande, sans-serif;
@@ -643,11 +648,16 @@
     padding-left: 18px;
 }
 
+.objectBox-array > .objectTitle {
+    font-weight: bold;
+    color: DarkGreen;
+}
+
 /*****************************************************************************************/
 
 .logRow-spy,
 .logRow-spy .objectLink-sourceLink {
-    background: #FFFFFF -moz-linear-gradient(top, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1) 18px, transparent 51px) repeat-x;
+    background: #FFFFFF linear-gradient(to bottom, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1) 18px, transparent 51px) repeat-x;
     padding-right: 4px;
     right: 0;
 }
@@ -783,3 +793,28 @@
     color: gray;
     padding-left: 5px;
 }
+
+
+/************************************************************************************************/
+/* include */
+.tableCommandLineInclude td{
+    height: 17px;
+}
+.tableCommandLineInclude .closeButton{
+    display: none;
+}
+
+.tableCommandLineInclude tr:hover .closeButton{
+    display: block;
+}
+.tableCommandLineInclude .url{ float: left; }
+
+.tableCommandLineInclude .commands{ 
+    float: right;
+    height:100%;
+}
+.tableCommandLineInclude td:last-child
+{
+    width: 75%;
+    padding-right: 0 !important; 
+}
diff --git a/trace/FBTrace/chrome/firebug/skin/classic/cookies/cookies.css b/trace/FBTrace/chrome/firebug/skin/classic/cookies/cookies.css
index 06dc2bc..5caf3f8 100644
--- a/trace/FBTrace/chrome/firebug/skin/classic/cookies/cookies.css
+++ b/trace/FBTrace/chrome/firebug/skin/classic/cookies/cookies.css
@@ -87,7 +87,7 @@
     border-bottom: 1px solid #9C9C9C;
     padding: 0 !important;
     font-weight: bold;
-    background: #C8C8C8 -moz-linear-gradient(top, rgba(255, 255, 255, 0.3), rgba(0, 0, 0, 0.2)) repeat-x;
+    background: #C8C8C8 linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(0, 0, 0, 0.2)) repeat-x;
     white-space: nowrap;
 }
 
@@ -345,7 +345,7 @@
 
 .cookieInfoCol {
     border-top: 1px solid #EEEEEE;
-    background: #FFFFFF -moz-linear-gradient(top, rgba(0, 0, 0, 0.1), transparent 33px) repeat-x;
+    background: #FFFFFF linear-gradient(to bottom, rgba(0, 0, 0, 0.1), transparent 33px) repeat-x;
 }
 
 .cookieInfoBody {
diff --git a/trace/FBTrace/chrome/firebug/skin/classic/css.css b/trace/FBTrace/chrome/firebug/skin/classic/css.css
index 661d75e..d84e34f 100644
--- a/trace/FBTrace/chrome/firebug/skin/classic/css.css
+++ b/trace/FBTrace/chrome/firebug/skin/classic/css.css
@@ -128,15 +128,13 @@
     padding-bottom: 2px;
 }
 
-.computedStyleRow > td:first-child {
-    width: 160px;
-}
-
 .selectorName {
+    width: 160px;
     -moz-padding-start: 24px;
 }
 
 .stylePropName {
+    width: 160px;
     vertical-align: top;
     font-weight: bold;
     padding: 0 4px 0 24px;
@@ -146,11 +144,7 @@
     padding-left: 3px;
 }
 
-.styleSelector > td:first-child {
-    width: 160px;
-}
-
-.styleSelector > td:n-th-child(2) {
+.propValue {
     width: 140px;
 }
 
@@ -170,7 +164,7 @@
     text-align: right;
 }
 
-.cssRule .objectLink-sourceLink {
+.cssElementRuleContainer > .objectLink-sourceLink {
     top: 0;
 }
 
@@ -200,10 +194,6 @@
     display: none;
 }
 
-.cssPropValue.editing {
-    white-space: nowrap;
-}
-
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 .useA11y .a11yCSSView .focusRow:focus {
@@ -228,10 +218,10 @@
 .infoTipColorBox {
     background-color: #C8C8C8;
     background-image:
-        -moz-linear-gradient(45deg, #A0A0A0 25%, transparent 25%),
-        -moz-linear-gradient(-45deg, #A0A0A0 25%, transparent 25%),
-        -moz-linear-gradient(45deg, transparent 75%, #A0A0A0 75%),
-        -moz-linear-gradient(-45deg, transparent 75%, #A0A0A0 75%);
+        linear-gradient(45deg, #A0A0A0 25%, transparent 25%),
+        linear-gradient(135deg, #A0A0A0 25%, transparent 25%),
+        linear-gradient(45deg, transparent 75%, #A0A0A0 75%),
+        linear-gradient(135deg, transparent 75%, #A0A0A0 75%);
     background-size: 16px 16px;
     background-position:0 0, 8px 0, 8px -8px, 0px 8px;
 }
diff --git a/trace/FBTrace/chrome/firebug/skin/classic/debugger.css b/trace/FBTrace/chrome/firebug/skin/classic/debugger.css
index d4b9ac1..8ea158c 100644
--- a/trace/FBTrace/chrome/firebug/skin/classic/debugger.css
+++ b/trace/FBTrace/chrome/firebug/skin/classic/debugger.css
@@ -136,7 +136,7 @@
     margin-top: 0;
     left: 5px;
     width: 90%;
-    background: -moz-linear-gradient(top, #00CEFD, #00BAF6) no-repeat;
+    background: linear-gradient(to bottom, #00CEFD, #00BAF6) no-repeat;
     border-style: solid;
     border-width: 19px 25px 33px 33px;
     -moz-border-image: url(condCorners.png) 19 25 33 33 stretch;
@@ -164,7 +164,7 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 .upsideDown {
-    background: -moz-linear-gradient(top, #00D1FE, #00ADE6) no-repeat;
+    background: linear-gradient(to bottom, #00D1FE, #00ADE6) no-repeat;
     border-style: solid;
     border-width: 28px 25px 19px 33px;
     -moz-border-image: url(condCornersUps.png) 28 25 19 33 stretch;
diff --git a/trace/FBTrace/chrome/firebug/skin/classic/dom.css b/trace/FBTrace/chrome/firebug/skin/classic/dom.css
index 12f2a0e..406e45c 100644
--- a/trace/FBTrace/chrome/firebug/skin/classic/dom.css
+++ b/trace/FBTrace/chrome/firebug/skin/classic/dom.css
@@ -94,25 +94,32 @@
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
+.userLabel,
+.userClassLabel,
+.userFunctionLabel {
+    font-weight: bold;
+}
+
 .userLabel {
     color: #000000;
-    font-weight: bold;
 }
 
 .userClassLabel {
     color: #E90000;
-    font-weight: bold;
 }
 
 .userFunctionLabel {
     color: #025E2A;
-    font-weight: bold;
 }
 
 .domLabel {
     color: #000000;
 }
 
+.domClassLabel {
+    color: #E90000;
+}
+
 .domFunctionLabel {
     color: #025E2A;
 }
diff --git a/trace/FBTrace/chrome/firebug/skin/classic/firebug.css b/trace/FBTrace/chrome/firebug/skin/classic/firebug.css
index b7496e9..783fd15 100644
--- a/trace/FBTrace/chrome/firebug/skin/classic/firebug.css
+++ b/trace/FBTrace/chrome/firebug/skin/classic/firebug.css
@@ -75,7 +75,7 @@
 
 .fbCommandLine {
     -moz-appearance: none;
-    margin: 4px 0 0 0;
+    margin: 2px 0 0 0;
     padding: 0 4px;
     border: none;
     font-family: monospace;
@@ -87,6 +87,16 @@
     z-index: 3;
 }
 
+#fbCommandLineMeasurer {
+    margin: 0;
+    padding: 0;
+    border: none;
+    position: absolute;
+    z-index: -1;
+    visibility: hidden;
+    width: auto;
+}
+
 #fbCommandEditor {
     margin: 0;
     font-family: monospace;
@@ -123,10 +133,6 @@
     width: auto;
 }
 
-#misspell {
-    display: none !important;
-}
-
 /*************************************************************************************************/
 /* Toolbar */
 
@@ -154,7 +160,7 @@
 
 .fbsearch-textbox[status="wraparound"] {
     background-image: url(chrome://global/skin/icons/wrap.png);
-    background-position: -moz-calc(100% - 5px) center;
+    background-position: calc(100% - 5px) center;
     background-repeat: no-repeat;
 }
 
@@ -365,6 +371,24 @@ textbox[type="fbSearchBox"] > panel {
     list-style-image: url(chrome://firebug/skin/commandLineDisabled.png);
 }
 
+/************************************************************************************************/
+/* Command History panel */
+
+#fbCommandHistory {
+    min-width: 200px;
+    max-height: 400px;
+    cursor: default;
+    font-family: monospace;
+    white-space: pre;
+    -moz-appearance: none;
+    background-color: -moz-dialog;
+}
+
+.commandHistoryItem.selected {
+    background-color: highlight;
+    color: highlighttext;
+}
+
 /*************************************************************************************************/
 
 #fbBreakOnErrors {
diff --git a/trace/FBTrace/chrome/firebug/skin/classic/html.css b/trace/FBTrace/chrome/firebug/skin/classic/html.css
index 70b17ed..3daed71 100644
--- a/trace/FBTrace/chrome/firebug/skin/classic/html.css
+++ b/trace/FBTrace/chrome/firebug/skin/classic/html.css
@@ -58,6 +58,7 @@
 .nodeComment {
     margin: 0 2px;
     vertical-align: top;
+    unicode-bidi: embed;
 }
 
 .nodeText {
@@ -165,7 +166,11 @@
 .nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox,
 .nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeTag,
 .nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
-.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeText {
+.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeText,
+.nodeBox.nodeHidden .nodeBox.selected > .nodeLabel > .nodeLabelBox,
+.nodeBox.nodeHidden .nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeTag,
+.nodeBox.nodeHidden .nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
+.nodeBox.nodeHidden .nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText {
     color: SkyBlue !important;
 }
 
diff --git a/trace/FBTrace/chrome/firebug/skin/classic/layout.css b/trace/FBTrace/chrome/firebug/skin/classic/layout.css
index 63ba9fc..4a4a3d2 100644
--- a/trace/FBTrace/chrome/firebug/skin/classic/layout.css
+++ b/trace/FBTrace/chrome/firebug/skin/classic/layout.css
@@ -82,7 +82,7 @@
     position: absolute;
 }
 
-.layoutLabel.v0 {
+.layoutLabel.invisible {
     opacity: 0.2;
 }
 
diff --git a/trace/FBTrace/chrome/firebug/skin/classic/linux/firebug.css b/trace/FBTrace/chrome/firebug/skin/classic/linux/firebug.css
new file mode 100644
index 0000000..1b30596
--- /dev/null
+++ b/trace/FBTrace/chrome/firebug/skin/classic/linux/firebug.css
@@ -0,0 +1,6 @@
+ at import "chrome://firebug/skin/win/firebug.css";
+
+/* Add some basic padding to the completion popup (missing on Linux). */
+.userTypedText {
+    margin-left: 1px;
+}
diff --git a/trace/FBTrace/chrome/firebug/skin/classic/mac/debugger.css b/trace/FBTrace/chrome/firebug/skin/classic/mac/debugger.css
index 7ac6313..b9b47bf 100644
--- a/trace/FBTrace/chrome/firebug/skin/classic/mac/debugger.css
+++ b/trace/FBTrace/chrome/firebug/skin/classic/mac/debugger.css
@@ -135,7 +135,7 @@
     margin-top: 0;
     left: 5px;
     width: 90%;
-    background: -moz-linear-gradient(top, #00CEFD, #00BAF6) no-repeat;
+    background: linear-gradient(to bottom, #00CEFD, #00BAF6) no-repeat;
     border-style: solid;
     border-width: 19px 25px 33px 33px;
     -moz-border-image: url(condCorners.png) 19 25 33 33 stretch;
@@ -163,7 +163,7 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 .upsideDown {
-    background: -moz-linear-gradient(top, #00D1FE, #00ADE6) no-repeat;
+    background: linear-gradient(to bottom, #00D1FE, #00ADE6) no-repeat;
     border-style: solid;
     border-width: 28px 25px 19px 33px;
     -moz-border-image: url(condCornersUps.png) 28 25 19 33 stretch;
diff --git a/trace/FBTrace/chrome/firebug/skin/classic/mac/firebug.css b/trace/FBTrace/chrome/firebug/skin/classic/mac/firebug.css
index 19ba75f..fc50f76 100644
--- a/trace/FBTrace/chrome/firebug/skin/classic/mac/firebug.css
+++ b/trace/FBTrace/chrome/firebug/skin/classic/mac/firebug.css
@@ -10,17 +10,23 @@
 #fbCommandToolbar {
     border-top: 1px solid #BBB9BA;
     border-bottom: 1px solid #BBB9BA;
-    background: #F6F6F6 -moz-linear-gradient(bottom, #FFFFFF, #E9E9E9 55%, #F2F2F2 55%, #FAFAFA) repeat-x;
+    background: #F6F6F6 linear-gradient(to top, #FFFFFF, #E9E9E9 55%, #F2F2F2 55%, #FAFAFA) repeat-x;
 }
 
 #fbCommandArrow,
 #fbCommandLine,
 #fbCommandEditor,
 #fbCommandLineCompletion,
+#fbCommandLineMeasurer,
 .fbCommandLineCompletions {
     font-family: Monaco, monospace;
 }
 
+/* Add some more padding to the completion popup */
+.userTypedText {
+    margin-left: 1px;
+}
+
 #fbCommandEditor {
     -moz-appearance: none;
     border: none;
@@ -53,7 +59,7 @@
 
 #fbToolbar {
     padding-left: 4px;
-    background: #F6F6F6 -moz-linear-gradient(bottom, #FFFFFF, #E9E9E9 55%, #F2F2F2 55%, #FAFAFA) repeat-x;
+    background: #F6F6F6 linear-gradient(to top, #FFFFFF, #E9E9E9 55%, #F2F2F2 55%, #FAFAFA) repeat-x;
     border-bottom: none;
 }
 
@@ -107,8 +113,8 @@
 
 .fbsearch-options-buttons {
     -moz-appearance: none;
-    background: #464646 -moz-linear-gradient(
-        bottom,
+    background: #464646 linear-gradient(
+        to top,
         rgba(255, 255, 255, 0.3),
         rgba(255, 255, 255, 0) 55%,
         rgba(255, 255, 255, 0.1) 55%,
@@ -235,10 +241,17 @@
     font-family: Monaco, monospace;
 }
 
+/************************************************************************************************/
+/* Command History panel */
+
+#fbCommandHistory {
+    font-family: Monaco, monospace;
+}
+
 /********************************************************************************************/
 
 .panelTabBox {
-    background: #e0e0e0 -moz-linear-gradient(bottom, #D7D7D7, #EDEDED) repeat-x;
+    background: #e0e0e0 linear-gradient(to top, #D7D7D7, #EDEDED) repeat-x;
     border-bottom: 1px solid #BBB9BA;
     padding: 0;
     overflow: hidden;
@@ -263,14 +276,14 @@ panelTab {
 panelTab[selected="true"] {
     border: 1px solid #A0A0A0;
     border-bottom: none;
-    background: -moz-linear-gradient(top, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0.7)) no-repeat 0 0;
+    background: linear-gradient(to bottom, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0.7)) no-repeat 0 0;
     color: inherit;
 }
 
 panelTab:not([selected="true"]):hover {
     border: 1px solid #C8C8C8;
     border-bottom: none;
-    background: -moz-linear-gradient(top, rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0.2)) no-repeat 0 0;
+    background: linear-gradient(to bottom, rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0.2)) no-repeat 0 0;
 }
 
 .panelTab-text {
@@ -441,7 +454,7 @@ panelTab[selected="true"] > panelTabMenu {
 
 /* ensure the inner toolbar background looks the same as the other toolbars */
 #fbToolbarInner.innerToolbar {
-    background: #F6F6F6 -moz-linear-gradient(bottom, #DCDCDC 1px, #FFFFFF 1px, #E9E9E9 55%, #F2F2F2 55%, #FAFAFA) repeat-x;
+    background: #F6F6F6 linear-gradient(to top, #DCDCDC 1px, #FFFFFF 1px, #E9E9E9 55%, #F2F2F2 55%, #FAFAFA) repeat-x;
     margin-left: -5px;
     margin-right: 0px;
 }
@@ -507,4 +520,4 @@ panelTab[selected="true"] > panelTabMenu {
 
 #fbMigrationOk {
     font-family: Monaco, monospace;
-}
\ No newline at end of file
+}
diff --git a/trace/FBTrace/chrome/firebug/skin/classic/mac/panel.css b/trace/FBTrace/chrome/firebug/skin/classic/mac/panel.css
index 9cbf3c2..8834637 100644
--- a/trace/FBTrace/chrome/firebug/skin/classic/mac/panel.css
+++ b/trace/FBTrace/chrome/firebug/skin/classic/mac/panel.css
@@ -19,6 +19,7 @@ body {
 .memberRow.hasChildren > .memberLabelCell > .memberLabel,
 .hasHeaders .netHrefLabel,
 .objectBox-stackFrame.hasTwisty,
+.objectBox-functionCall.hasTwisty,
 .netPageRow > .netCol > .netPageTitle,
 .computedStyle.hasSelectors > .stylePropName,
 .cookieRow > .cookieNameCol > .cookieNameLabel {
@@ -36,6 +37,8 @@ body {
 .nodeBox.open > .nodeLabel > .twisty,
 .netRow.opened > .netCol > .netHrefLabel,
 .objectBox-stackFrame.hasTwisty.opened,
+.objectBox-functionCall.hasTwisty.opened,
+.computedStylesGroup.opened > .cssComputedHeader > .twisty,
 .netPageRow.opened > .netCol > .netPageTitle,
 .computedStyle.hasSelectors.opened > .stylePropName,
 .cookieRow.opened > .cookieNameCol > .cookieNameLabel {
diff --git a/trace/FBTrace/chrome/firebug/skin/classic/net.css b/trace/FBTrace/chrome/firebug/skin/classic/net.css
index e86b21f..91e0e8c 100644
--- a/trace/FBTrace/chrome/firebug/skin/classic/net.css
+++ b/trace/FBTrace/chrome/firebug/skin/classic/net.css
@@ -32,7 +32,7 @@
     border-bottom: 1px solid #9C9C9C;
     padding: 0 !important;
     font-weight: bold;
-    background: #C4C4C4 -moz-linear-gradient(top, rgba(255, 255, 255, 0.3), rgba(0, 0, 0, 0.2));
+    background: #C4C4C4 linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(0, 0, 0, 0.2));
     color: #000000;
     white-space: nowrap;
 }
@@ -311,7 +311,7 @@
     left: 0;
     top: 1px;
     bottom: 1px;
-    background-image: -moz-linear-gradient(top, rgba(255, 255, 255, 0.3), rgba(0, 0, 0, 0.2));
+    background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(0, 0, 0, 0.2));
 }
 
 .netBlockingBar {
@@ -397,7 +397,7 @@
  */
 .fromCache .netReceivingBar,
 .fromCache.netReceivingBar {
-    background-image: -moz-linear-gradient(top, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.1));
+    background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.1));
 }
 
 .netSummaryRow .netTimeLabel,
@@ -414,7 +414,7 @@
 
 .netTable.showBFCacheResponses .netRow.fromBFCache {
     display: table-row;
-    background-image: -moz-repeating-linear-gradient(-45deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05) 5px, transparent 5px, transparent 10px);
+    background-image: repeating-linear-gradient(135deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05) 5px, transparent 5px, transparent 10px);
     background-repeat: repeat;
 }
 
@@ -492,10 +492,6 @@
     font-size: 11px;
 }
 
-.sizeInfoSizeCol {
-    font-weight: bold;
-}
-
 .sizeInfoDetailCol {
     color: gray;
     text-align: right;
@@ -595,7 +591,7 @@
 
 .netInfoCol {
     border-top: 1px solid #EEEEEE;
-    background: #FFFFFF -moz-linear-gradient(top, rgba(0, 0, 0, 0.1), transparent 33px) repeat-x;
+    background: #FFFFFF linear-gradient(to bottom, rgba(0, 0, 0, 0.1), transparent 33px) repeat-x;
 }
 
 .netInfoBody {
diff --git a/trace/FBTrace/chrome/firebug/skin/classic/panel.css b/trace/FBTrace/chrome/firebug/skin/classic/panel.css
index 1e56f16..6a28118 100644
--- a/trace/FBTrace/chrome/firebug/skin/classic/panel.css
+++ b/trace/FBTrace/chrome/firebug/skin/classic/panel.css
@@ -13,5 +13,6 @@
 @import "chrome://firebug/skin/callstack.css";
 @import "chrome://firebug/skin/layout.css";
 @import "chrome://firebug/skin/dom.css";
+ at import "chrome://firebug/skin/performanceTiming.css";
 @import "chrome://firebug/skin/tableRep.css";
- at import "chrome://firebug-os/skin/panel.css";
\ No newline at end of file
+ at import "chrome://firebug-os/skin/panel.css";
diff --git a/trace/FBTrace/chrome/firebug/skin/classic/panelbase.css b/trace/FBTrace/chrome/firebug/skin/classic/panelbase.css
index 2179837..f714ca5 100644
--- a/trace/FBTrace/chrome/firebug/skin/classic/panelbase.css
+++ b/trace/FBTrace/chrome/firebug/skin/classic/panelbase.css
@@ -252,7 +252,7 @@ h1.groupHeader {
     margin: 0 0 4px 0;
     border-top: 1px solid #CCCCCC;
     border-bottom: 1px solid #CCCCCC;
-    background: #FFFFFF -moz-linear-gradient(bottom, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.1) 60%, rgba(0, 0, 0, 0.05) 60%, transparent) repeat-x;
+    background: #FFFFFF linear-gradient(to top, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.1) 60%, rgba(0, 0, 0, 0.05) 60%, transparent) repeat-x;
     font-size: inherit;
 }
 
diff --git a/trace/FBTrace/chrome/firebug/skin/classic/performanceTiming.css b/trace/FBTrace/chrome/firebug/skin/classic/performanceTiming.css
new file mode 100644
index 0000000..8ccf0d3
--- /dev/null
+++ b/trace/FBTrace/chrome/firebug/skin/classic/performanceTiming.css
@@ -0,0 +1,192 @@
+/* See license.txt for terms of usage */
+
+/*************************************************************************************************/
+
+.logRow-perfTiming {
+}
+
+/*************************************************************************************************/
+
+.perfTimingBox {
+    position: relative;
+    height: 17px;
+    border-right: 130px solid transparent;
+}
+
+.perfTimingBar {
+    position: absolute;
+    top: 1px;
+    bottom: 1px;
+    background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(0, 0, 0, 0.2));
+    min-width: 2px;
+    z-index: 10;
+}
+
+.perfTimingBarLabel {
+    -moz-box-sizing: padding-box;
+    position: absolute;
+    top: 1px;
+    left: 100%;
+    padding-left: 6px;
+    color: #808080;
+    min-width: 16px;
+    white-space: nowrap;
+    z-index: 30;
+}
+
+/*************************************************************************************************/
+/* Info Tip */
+
+.timeInfoTipRow .timeInfoTipBar {
+    background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(0, 0, 0, 0.2));
+}
+
+/*************************************************************************************************/
+/* Bars */
+
+.perfTimingBar.pageLoad,
+.timeInfoTipBar.pageLoad {
+    background-color: rgb(217, 179, 147);
+}
+
+.perfTimingBar.redirect,
+.timeInfoTipBar.redirect {
+    background-color: rgb(0, 148, 87);
+}
+
+.perfTimingBar.dns,
+.timeInfoTipBar.dns {
+    background-color: #91D2DC;
+}
+
+.perfTimingBar.connecting,
+.timeInfoTipBar.connecting {
+    background-color: #B9E164;
+}
+
+.perfTimingBar.waiting,
+.timeInfoTipBar.waiting {
+    background-color: #B4A5D2;
+}
+
+.perfTimingBar.response,
+.timeInfoTipBar.response {
+    background-color: #78E17D;
+}
+
+.perfTimingBar.processing,
+.timeInfoTipBar.processing {
+    background-color: rgb(202, 206, 168);
+}
+
+.perfTimingBar.DOMContentLoaded,
+.timeInfoTipBar.DOMContentLoaded {
+    background-color: rgb(179, 184, 118);
+}
+
+.perfTimingBar.onLoad,
+.timeInfoTipBar.onLoad {
+    background-color: rgb(168, 194, 196);
+}
+
+/*************************************************************************************************/
+/* DOM Events */
+
+.perfTimingBar.event {
+    width: 1px;
+}
+
+.perfTimingEvent {
+    position: absolute;
+    width: 1px;
+    z-index: 20;
+    top: 0;
+    bottom: 0;
+}
+
+.perfTimingTable TR:first-child .perfTimingEvent {
+    top: 1px;
+}
+
+.perfTimingTable TR:last-child .perfTimingEvent {
+    bottom: 1px;
+}
+
+.perfTimingEvent.domInteractive,
+.timeInfoTipEventBar.domInteractive {
+    background-color: rgb(126, 146, 126);
+}
+
+.perfTimingEvent.domLoading,
+.timeInfoTipEventBar.domLoading {
+    background-color: rgb(155, 133, 155);
+}
+
+.perfTimingEvent.domContentLoaded,
+.timeInfoTipEventBar.domContentLoaded {
+    background-color: rgb(152, 152, 255);
+}
+
+.perfTimingEvent.onLoad,
+.timeInfoTipEventBar.onLoad {
+    background-color: rgb(255, 152, 152);
+}
+
+/*************************************************************************************************/
+/* Details */
+
+.logRow-perfTimingDetails .logGroupBody {
+    border-bottom: 1px solid #D7D7D7;
+    overflow-y: auto;
+    height: 200px;
+}
+
+.logRow-perfTimingDetails .logGroupLabel {
+    text-decoration: none !important;
+}
+
+.logRow-perfTimingDetails > .logRow {
+    background-position: 2px 3px !important;
+}
+
+.logRow-perfTimingDetails .timingCaptionDesc {
+    color: gray;
+    font-weight: normal;
+    padding-left: 10px;
+}
+
+.logRow-perfTimingDetails .timingTable {
+    margin-bottom: 4px;
+    cursor: pointer;
+}
+
+.logRow-perfTimingDetails .timingCell {
+    padding: 2px 4px 2px 4px;
+}
+
+.logRow-perfTimingDetails .timingTable tr:nth-child(even) {
+    background-color: #EFEFEF;
+}
+
+.logRow-perfTimingDetails .timingName {
+    color: green;
+    font-family: monospace;
+}
+
+.logRow-perfTimingDetails .timingRow:hover .timingName {
+    text-decoration: underline;
+}
+
+.logRow-perfTimingDetails .timingDesc {
+    color: gray
+}
+
+/*************************************************************************************************/
+/* Cursor */
+
+.perfTimingEvent.cursor {
+    background-color: gray;
+    visibility: hidden;
+    width: 2px;
+    z-index: 40;
+}
diff --git a/trace/FBTrace/chrome/firebug/skin/classic/selector.css b/trace/FBTrace/chrome/firebug/skin/classic/selector.css
new file mode 100644
index 0000000..bbfb3b0
--- /dev/null
+++ b/trace/FBTrace/chrome/firebug/skin/classic/selector.css
@@ -0,0 +1,42 @@
+/* Rules for Selector panel elements */
+
+.cssSelectionTable {
+    width: 100%;
+}
+.selectionElement {
+    padding: 0 0 0 1ex;
+}
+
+.selectorWarning {
+    font-size: 11px;
+    color: gray;
+    padding: 2px 0 0 1ex;
+}
+
+.selectionErrorText  {
+    color: black;
+    padding: 1em;
+    background-color: #FFEBEB;
+}
+
+/* Rules for select panel's effect on CSS stylesheet panel */
+.selectedSelectorRule {
+    border-color: Highlight !important;
+    background-color: #EBF5FF !important;
+    color: #000000 !important;
+    cursor: pointer;
+}
+
+.cssSelector,
+.cssPropName,
+.cssPropValue {
+    cursor: text;
+}
+
+.lockedSelectorRule {
+    background-color: Highlight;
+}
+
+.lockedSelectorRule * {
+    color: HighlightText !important;
+}
\ No newline at end of file
diff --git a/trace/FBTrace/chrome/firebug/skin/classic/tableRep.css b/trace/FBTrace/chrome/firebug/skin/classic/tableRep.css
index b93fcda..719097e 100644
--- a/trace/FBTrace/chrome/firebug/skin/classic/tableRep.css
+++ b/trace/FBTrace/chrome/firebug/skin/classic/tableRep.css
@@ -14,6 +14,7 @@
 
 .dataTableSizer {
     width: 100%;
+    overflow-x: auto;
 }
 
 .dataTableSizer:focus {
diff --git a/trace/FBTrace/chrome/firebug/skin/classic/win/firebug.css b/trace/FBTrace/chrome/firebug/skin/classic/win/firebug.css
index 96106de..8a17cb7 100644
--- a/trace/FBTrace/chrome/firebug/skin/classic/win/firebug.css
+++ b/trace/FBTrace/chrome/firebug/skin/classic/win/firebug.css
@@ -144,18 +144,6 @@
 
 /************************************************************************************************/
 
-#fbCommandHistory {
-    min-width: 200px;
-    cursor: default;
-    font-family: monospace;
-    white-space: pre;
-}
-
-.commandHistoryItem.selected {
-    background-color: highlight;
-    color: highlighttext;
-}
-
 #fbCommandEditor {
     -moz-appearance: none;
     border: none;
@@ -182,8 +170,8 @@
 /************************************************************************************************/
 
 .panelTabBox {
-    background: -moz-linear-gradient(
-        bottom,
+    background: linear-gradient(
+        to top,
         rgba(0, 0, 0, 0.25) 1px,
         rgba(0, 0, 0, 0.15) 1px,
         rgba(0, 0, 0, 0));
@@ -211,8 +199,8 @@ panelTab {
 panelTab[selected="true"] {
     border: 1px solid #A0A0A0;
     border-bottom: none;
-    background: -moz-linear-gradient(
-        top,
+    background: linear-gradient(
+        to bottom,
         rgba(255, 255, 255, 0.7),
         rgba(255, 255, 255, 0.9) 40%,
         rgba(255, 255, 255, 0.4) 40%,
@@ -223,8 +211,8 @@ panelTab[selected="true"] {
 panelTab:not([selected="true"]):hover {
     border: 1px solid #C8C8C8;
     border-bottom: none;
-    background: -moz-linear-gradient(
-        top,
+    background: linear-gradient(
+        to bottom,
         rgba(255, 255, 255, 0.2),
         rgba(255, 255, 255, 0.4) 40%,
         rgba(255, 255, 255, 0) 40%,
diff --git a/trace/FBTrace/chrome/firebug/skin/classic/win/linux.css b/trace/FBTrace/chrome/firebug/skin/classic/win/linux.css
new file mode 100644
index 0000000..e69de29
diff --git a/trace/FBTrace/chrome/firebug/skin/classic/win/panel.css b/trace/FBTrace/chrome/firebug/skin/classic/win/panel.css
index 03adec6..238de0e 100644
--- a/trace/FBTrace/chrome/firebug/skin/classic/win/panel.css
+++ b/trace/FBTrace/chrome/firebug/skin/classic/win/panel.css
@@ -11,6 +11,7 @@
 .memberRow.hasChildren > .memberLabelCell > .memberLabel,
 .hasHeaders .netHrefLabel,
 .objectBox-stackFrame.hasTwisty,
+.objectBox-functionCall.hasTwisty,
 .netPageRow > .netCol > .netPageTitle,
 .cssComputedHeader > .twisty,
 .breakpointHeader > .twisty,
@@ -32,6 +33,7 @@
 .netRow.opened > .netCol > .netHrefLabel,
 .netPageRow.opened > .netCol > .netPageTitle,
 .objectBox-stackFrame.hasTwisty.opened,
+.objectBox-functionCall.hasTwisty.opened,
 .computedStylesGroup.opened > .cssComputedHeader > .twisty,
 .breakpointBlock.opened > .breakpointHeader > .twisty,
 .computedStyle.hasSelectors.opened > .stylePropName,

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/firebug.git



More information about the Pkg-mozext-commits mailing list