Merge mozilla-central into services-central
authorGregory Szorc <gps@mozilla.com>
Sun, 06 Jan 2013 10:06:07 -0800
changeset 126941 dccd490f15326234dd40d487928b3379dacb86ce
parent 126940 4ac2babbafecf33fc72228cd5d343c3ab1211841 (current diff)
parent 126862 c4abfca219e5c438a69f65533dcb364ba9604c55 (diff)
child 126942 7647b05aa3f0bfbc53a940a61a461ff9a9fdcdcd
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone20.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central into services-central
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/setup.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/tasks.js
browser/devtools/commandline/CmdAddon.jsm
browser/devtools/commandline/CmdBreak.jsm
browser/devtools/commandline/CmdCalllog.jsm
browser/devtools/commandline/CmdCalllogChrome.jsm
browser/devtools/commandline/CmdCmd.jsm
browser/devtools/commandline/CmdConsole.jsm
browser/devtools/commandline/CmdCookie.jsm
browser/devtools/commandline/CmdDbg.jsm
browser/devtools/commandline/CmdEcho.jsm
browser/devtools/commandline/CmdExport.jsm
browser/devtools/commandline/CmdJsb.jsm
browser/devtools/commandline/CmdPagemod.jsm
browser/devtools/commandline/CmdRestart.jsm
browser/devtools/commandline/CmdScreenshot.jsm
browser/devtools/profiler/cleopatra/images/filter.png
browser/devtools/profiler/cleopatra/images/showall.png
browser/themes/gnomestripe/downloads/download-notification.png
browser/themes/pinstripe/downloads/download-notification.png
browser/themes/winstripe/downloads/download-notification.png
content/html/content/public/HTMLCanvasElement.h
content/html/content/public/nsHTMLCanvasElement.h
content/html/content/src/HTMLCanvasElement.cpp
content/html/content/src/nsHTMLAnchorElement.cpp
content/html/content/src/nsHTMLCanvasElement.cpp
content/html/content/src/nsHTMLLIElement.cpp
content/html/content/src/nsHTMLOListElement.cpp
content/html/content/src/nsHTMLParagraphElement.cpp
content/html/content/src/nsHTMLPreElement.cpp
content/html/content/src/nsHTMLScriptElement.cpp
content/html/content/src/nsHTMLSpanElement.cpp
content/html/content/src/nsHTMLTableCaptionElement.cpp
content/html/content/src/nsHTMLTableCellElement.cpp
content/html/content/src/nsHTMLTableColElement.cpp
content/html/content/src/nsHTMLTableElement.cpp
content/html/content/src/nsHTMLTableElement.h
content/html/content/src/nsHTMLTableRowElement.cpp
content/html/content/src/nsHTMLTableSectionElement.cpp
content/svg/content/src/nsSVGDescElement.cpp
content/svg/content/src/nsSVGMetadataElement.cpp
content/svg/content/src/nsSVGMpathElement.cpp
content/svg/content/src/nsSVGMpathElement.h
content/svg/content/src/nsSVGScriptElement.cpp
content/svg/content/src/nsSVGStopElement.cpp
content/svg/content/src/nsSVGStyleElement.cpp
content/svg/content/src/nsSVGTitleElement.cpp
dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_interfaces.html.json
dom/interfaces/html/nsIDOMHTMLTableSectionElem.idl
mobile/android/base/resources/drawable-hdpi/ic_menu_synced_tabs.png
mobile/android/base/resources/drawable-xhdpi/ic_menu_synced_tabs.png
mobile/android/base/resources/drawable/ic_menu_synced_tabs.png
view/public/nsIViewManager.h
view/public/nsViewsCID.h
view/src/nsViewManager.h
--- a/accessible/src/generic/DocAccessible.cpp
+++ b/accessible/src/generic/DocAccessible.cpp
@@ -30,17 +30,17 @@
 #include "nsIDOMXULPopupElement.h"
 #include "nsIEditingSession.h"
 #include "nsEventStateManager.h"
 #include "nsIFrame.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsINameSpaceManager.h"
 #include "nsIPresShell.h"
 #include "nsIServiceManager.h"
-#include "nsIViewManager.h"
+#include "nsViewManager.h"
 #include "nsIScrollableFrame.h"
 #include "nsUnicharUtils.h"
 #include "nsIURI.h"
 #include "nsIWebNavigation.h"
 #include "nsFocusManager.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/dom/Element.h"
 
@@ -1248,17 +1248,17 @@ DocAccessible::HandleAccEvent(AccEvent* 
 // Public members
 
 void*
 DocAccessible::GetNativeWindow() const
 {
   if (!mPresShell)
     return nullptr;
 
-  nsIViewManager* vm = mPresShell->GetViewManager();
+  nsViewManager* vm = mPresShell->GetViewManager();
   if (!vm)
     return nullptr;
 
   nsCOMPtr<nsIWidget> widget;
   vm->GetRootWidget(getter_AddRefs(widget));
   if (widget)
     return widget->GetNativeData(NS_NATIVE_WINDOW);
 
--- a/accessible/src/generic/HyperTextAccessible.cpp
+++ b/accessible/src/generic/HyperTextAccessible.cpp
@@ -524,32 +524,42 @@ HyperTextAccessible::DOMPointToHypertext
     nsresult rv = ContentToRenderedOffset(frame, aNodeOffset, &addTextOffset);
     NS_ENSURE_SUCCESS(rv, nullptr);
     // Get the child node and 
     findNode = aNode;
 
   } else {
     // findNode could be null if aNodeOffset == # of child nodes, which means
     // one of two things:
-    // 1) we're at the end of the children, keep findNode = null, so that we get
-    //    the last possible offset
+    // 1) there are no children, and the passed-in node is not mContent -- use
+    //    parentContent for the node to find
     // 2) there are no children and the passed-in node is mContent, which means
-    //    we're an aempty nsIAccessibleText
-    // 3) there are no children, and the passed-in node is not mContent -- use
-    //    parentContent for the node to find
+    //    we're an empty nsIAccessibleText
+    // 3) there are children and we're at the end of the children
 
     findNode = aNode->GetChildAt(aNodeOffset);
-    if (!findNode && !aNodeOffset) {
-      if (aNode == GetNode()) {
-        // There are no children, which means this is an empty nsIAccessibleText, in which
-        // case we can only be at hypertext offset 0
-        *aHyperTextOffset = 0;
-        return nullptr;
+    if (!findNode) {
+      if (aNodeOffset == 0) {
+        if (aNode == GetNode()) {
+          // Case #1: this accessible has no children and thus has empty text,
+          // we can only be at hypertext offset 0.
+          *aHyperTextOffset = 0;
+          return nullptr;
+        }
+
+        // Case #2: there are no children, we're at this node.
+        findNode = aNode;
+      } else if (aNodeOffset == aNode->GetChildCount()) {
+        // Case #3: we're after the last child, get next node to this one.
+        for (nsINode* tmpNode = aNode;
+             !findNode && tmpNode && tmpNode != mContent;
+             tmpNode = tmpNode->GetParent()) {
+          findNode = tmpNode->GetNextSibling();
+        }
       }
-      findNode = aNode; // Case #2: there are no children
     }
   }
 
   // Get accessible for this findNode, or if that node isn't accessible, use the
   // accessible for the next DOM node which has one (based on forward depth first search)
   Accessible* descendantAcc = nullptr;
   if (findNode) {
     nsCOMPtr<nsIContent> findContent(do_QueryInterface(findNode));
--- a/accessible/src/html/HTMLTableAccessible.cpp
+++ b/accessible/src/html/HTMLTableAccessible.cpp
@@ -23,17 +23,17 @@
 #include "nsIDOMRange.h"
 #include "nsISelectionPrivate.h"
 #include "nsINameSpaceManager.h"
 #include "nsIDOMNodeList.h"
 #include "nsIDOMHTMLCollection.h"
 #include "nsIDOMHTMLTableCellElement.h"
 #include "nsIDOMHTMLTableElement.h"
 #include "nsIDOMHTMLTableRowElement.h"
-#include "nsIDOMHTMLTableSectionElem.h"
+#include "nsIDOMHTMLTableSectionElement.h"
 #include "nsIDocument.h"
 #include "nsIMutableArray.h"
 #include "nsIPresShell.h"
 #include "nsITableCellLayout.h"
 #include "nsFrameSelection.h"
 #include "nsError.h"
 #include "nsArrayUtils.h"
 #include "nsComponentManagerUtils.h"
--- a/accessible/src/mac/RootAccessibleWrap.mm
+++ b/accessible/src/mac/RootAccessibleWrap.mm
@@ -5,17 +5,17 @@
 
 #include "RootAccessibleWrap.h"
 
 #include "mozDocAccessible.h"
 
 #include "nsCOMPtr.h"
 #include "nsObjCExceptions.h"
 #include "nsIWidget.h"
-#include "nsIViewManager.h"
+#include "nsViewManager.h"
 
 using namespace mozilla::a11y;
 
 RootAccessibleWrap::
   RootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
                      nsIPresShell* aPresShell) :
   RootAccessible(aDocument, aRootContent, aPresShell)
 {
--- a/accessible/src/msaa/AccessibleWrap.cpp
+++ b/accessible/src/msaa/AccessibleWrap.cpp
@@ -29,17 +29,17 @@
 #include "nsIMutableArray.h"
 #include "nsIFrame.h"
 #include "nsIScrollableFrame.h"
 #include "nsINameSpaceManager.h"
 #include "nsINodeInfo.h"
 #include "nsIServiceManager.h"
 #include "nsTextFormatter.h"
 #include "nsView.h"
-#include "nsIViewManager.h"
+#include "nsViewManager.h"
 #include "nsEventMap.h"
 #include "nsArrayUtils.h"
 #include "mozilla/Preferences.h"
 
 #include "Accessible2_i.c"
 #include "AccessibleRole.h"
 #include "AccessibleStates.h"
 #include "oleacc.h"
@@ -1648,17 +1648,17 @@ AccessibleWrap::GetHWNDFor(Accessible* a
     // Popup lives in own windows, use its HWND until the popup window is
     // hidden to make old JAWS versions work with collapsed comboboxes (see
     // discussion in bug 379678).
     nsIFrame* frame = aAccessible->GetFrame();
     if (frame) {
       nsIWidget* widget = frame->GetNearestWidget();
       if (widget && widget->IsVisible()) {
         nsIPresShell* shell = document->PresShell();
-        nsIViewManager* vm = shell->GetViewManager();
+        nsViewManager* vm = shell->GetViewManager();
         if (vm) {
           nsCOMPtr<nsIWidget> rootWidget;
           vm->GetRootWidget(getter_AddRefs(rootWidget));
           // Make sure the accessible belongs to popup. If not then use
           // document HWND (which might be different from root widget in the
           // case of window emulation).
           if (rootWidget != widget)
             return static_cast<HWND>(widget->GetNativeData(NS_NATIVE_WINDOW));
--- a/accessible/src/msaa/DocAccessibleWrap.cpp
+++ b/accessible/src/msaa/DocAccessibleWrap.cpp
@@ -16,17 +16,17 @@
 #include "Statistics.h"
 
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeNode.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsISelectionController.h"
 #include "nsIServiceManager.h"
 #include "nsIURI.h"
-#include "nsIViewManager.h"
+#include "nsViewManager.h"
 #include "nsIWebNavigation.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 /* For documentation of the accessibility architecture, 
  * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
  */
--- a/accessible/tests/mochitest/events.js
+++ b/accessible/tests/mochitest/events.js
@@ -1262,16 +1262,48 @@ function synthSelectAll(aNodeOrID, aChec
 
   this.getID = function synthSelectAll_getID()
   {
     return aNodeOrID + " selectall";
   }
 }
 
 /**
+ * Move the caret in text accessible.
+ */
+function moveCaretToDOMPoint(aID, aNode, aOffset, aExpectedOffset,
+                             aFocusTargetID)
+{
+  this.target = getAccessible(aID, [nsIAccessibleText]);
+  this.focus = aFocusTargetID ? getAccessible(aFocusTargetID) : null;
+  this.focusNode = this.focus ? this.focus.DOMNode : null;
+
+  this.invoke = function moveCaretToDOMPoint_invoke()
+  {
+    if (this.focusNode)
+      this.focusNode.focus();
+
+    window.getSelection().getRangeAt(0).setStart(aNode, aOffset);
+  }
+
+  this.getID = function moveCaretToDOMPoint_getID()
+  {
+   return "Set caret on " + prettyName(aID) + " at point: " +
+     prettyName(aNode) + " node with offset " + aOffset;
+  }
+
+  this.eventSeq = [
+    new caretMoveChecker(aExpectedOffset, this.target)
+  ];
+
+  if (this.focus)
+    this.eventSeq.push(new asyncInvokerChecker(EVENT_FOCUS, this.focus));
+}
+
+/**
  * Set caret offset in text accessible.
  */
 function setCaretOffset(aID, aOffset, aFocusTargetID)
 {
   this.target = getAccessible(aID, [nsIAccessibleText]);
   this.offset = aOffset == -1 ? this.target.characterCount: aOffset;
   this.focus = aFocusTargetID ? getAccessible(aFocusTargetID) : null;
 
--- a/accessible/tests/mochitest/events/test_caretmove.html
+++ b/accessible/tests/mochitest/events/test_caretmove.html
@@ -72,36 +72,58 @@
 
       id = "p";
       gQueue.push(new synthShiftTab(id, new caretMoveChecker(0, id)));
       id = "textarea";
       gQueue.push(new synthShiftTab(id, new caretMoveChecker(12, id)));
       id = "p";
       gQueue.push(new synthTab(id, new caretMoveChecker(0, id)));
 
+      // Set caret after a child of span element, i.e. after 'text' text.
+      gQueue.push(new moveCaretToDOMPoint("test1", getNode("test1_span"), 1,
+                                           4, "test1"));
+      gQueue.push(new moveCaretToDOMPoint("test2", getNode("test2_span"), 1,
+                                           4, "test2"));
+
+      // empty text element
+      gQueue.push(new moveCaretToDOMPoint("test3", getNode("test3"), 0,
+                                           0, "test3"));
+      gQueue.push(new moveCaretToDOMPoint("test4", getNode("test4_span"), 0,
+                                           0, "test4"));
+
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTests);
   </script>
 </head>
 
 <body>
 
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=454377"
      title="Accessible caret move events testing">
-    Mozilla Bug 454377
+    Bug 454377
+  </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=824901"
+     title="HyperTextAccessible::DOMPointToHypertextOffset fails for node and offset equal to node child count">
+    Bug 824901
   </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <input id="textbox" value="hello"/>
   <textarea id="textarea">text<br>text</textarea>
   <p id="p" contentEditable="true"><span>text</span><br/>text</p>
   <div id="div" contentEditable="true"><p id="p1_in_div">text</p><p id="p2_in_div">text</p></div>
 
+  <p contentEditable="true" id="test1"><span id="test1_span">text</span>ohoho</p>
+  <p contentEditable="true" id="test2"><span><span id="test2_span">text</span></span>ohoho</p>
+  <p contentEditable="true" id="test3"></p>
+  <p contentEditable="true" id="test4"><span id="test4_span"></span></p>
+
   <div id="eventdump"></div>
 </body>
 </html>
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -278,20 +278,24 @@ pref("widget.ime.android.landscape_fulls
 pref("widget.ime.android.fullscreen_threshold", 250); // in hundreths of inches
 
 // optimize images' memory usage
 pref("image.mem.decodeondraw", true);
 pref("content.image.allow_locking", true);
 pref("image.mem.min_discard_timeout_ms", 10000);
 pref("image.mem.max_decoded_image_kb", 5120); /* 5MB */
 
+// XXX this isn't a good check for "are touch events supported", but
+// we don't really have a better one at the moment.
+#ifdef MOZ_WIDGET_GONK
 // enable touch events interfaces
 pref("dom.w3c_touch_events.enabled", 1);
 pref("dom.w3c_touch_events.safetyX", 0); // escape borders in units of 1/240"
 pref("dom.w3c_touch_events.safetyY", 120); // escape borders in units of 1/240"
+#endif
 
 #ifdef MOZ_SAFE_BROWSING
 // Safe browsing does nothing unless this pref is set
 pref("browser.safebrowsing.enabled", true);
 
 // Prevent loading of pages identified as malware
 pref("browser.safebrowsing.malware.enabled", true);
 
@@ -539,16 +543,18 @@ pref("dom.ipc.processPriorityManager.ena
 pref("dom.ipc.processPriorityManager.gracePeriodMS", 1000);
 
 // Kernel parameters for how processes are killed on low-memory.
 pref("gonk.systemMemoryPressureRecoveryPollMS", 5000);
 pref("hal.processPriorityManager.gonk.masterOomScoreAdjust", 0);
 pref("hal.processPriorityManager.gonk.masterKillUnderMB", 1);
 pref("hal.processPriorityManager.gonk.foregroundOomScoreAdjust", 67);
 pref("hal.processPriorityManager.gonk.foregroundKillUnderMB", 4);
+pref("hal.processPriorityManager.gonk.backgroundPerceivableOomScoreAdjust", 134);
+pref("hal.processPriorityManager.gonk.backgroundPerceivebleKillUnderMB", 5);
 pref("hal.processPriorityManager.gonk.backgroundHomescreenOomScoreAdjust", 200);
 pref("hal.processPriorityManager.gonk.backgroundHomescreenKillUnderMB", 5);
 pref("hal.processPriorityManager.gonk.backgroundOomScoreAdjust", 400);
 pref("hal.processPriorityManager.gonk.backgroundKillUnderMB", 8);
 pref("hal.processPriorityManager.gonk.notifyLowMemUnderMB", 10);
 
 // Niceness values (i.e., CPU priorities) for B2G processes.
 pref("hal.processPriorityManager.gonk.masterNice", -1);
--- a/b2g/build.mk
+++ b/b2g/build.mk
@@ -13,18 +13,16 @@ endif
 endif
 
 TIERS += app
 
 ifdef MOZ_EXTENSIONS
 tier_app_dirs += extensions
 endif
 
-tier_app_dirs += services
-
 tier_app_dirs += \
   $(MOZ_BRANDING_DIRECTORY) \
   b2g \
   $(NULL)
 
 
 installer: 
 	@$(MAKE) -C b2g/installer installer
--- a/b2g/chrome/content/forms.js
+++ b/b2g/chrome/content/forms.js
@@ -20,22 +20,169 @@ XPCOMUtils.defineLazyServiceGetter(Servi
 
 XPCOMUtils.defineLazyGetter(this, "domWindowUtils", function () {
   return content.QueryInterface(Ci.nsIInterfaceRequestor)
                 .getInterface(Ci.nsIDOMWindowUtils);
 });
 
 const RESIZE_SCROLL_DELAY = 20;
 
+let HTMLDocument = Ci.nsIDOMHTMLDocument;
+let HTMLHtmlElement = Ci.nsIDOMHTMLHtmlElement;
+let HTMLBodyElement = Ci.nsIDOMHTMLBodyElement;
+let HTMLIFrameElement = Ci.nsIDOMHTMLIFrameElement;
 let HTMLInputElement = Ci.nsIDOMHTMLInputElement;
 let HTMLTextAreaElement = Ci.nsIDOMHTMLTextAreaElement;
 let HTMLSelectElement = Ci.nsIDOMHTMLSelectElement;
 let HTMLOptGroupElement = Ci.nsIDOMHTMLOptGroupElement;
 let HTMLOptionElement = Ci.nsIDOMHTMLOptionElement;
 
+let FormVisibility = {
+  /**
+   * Searches upwards in the DOM for an element that has been scrolled.
+   *
+   * @param {HTMLElement} node element to start search at.
+   * @return {Window|HTMLElement|Null} null when none are found window/element otherwise.
+   */
+  findScrolled: function fv_findScrolled(node) {
+    let win = node.ownerDocument.defaultView;
+
+    while (!(node instanceof HTMLBodyElement)) {
+
+      // We can skip elements that have not been scrolled.
+      // We only care about top now remember to add the scrollLeft
+      // check if we decide to care about the X axis.
+      if (node.scrollTop !== 0) {
+        // the element has been scrolled so we may need to adjust
+        // where we think the root element is located.
+        //
+        // Otherwise it may seem visible but be scrolled out of the viewport
+        // inside this scrollable node.
+        return node;
+      } else {
+        // this node does not effect where we think
+        // the node is even if it is scrollable it has not hidden
+        // the element we are looking for.
+        node = node.parentNode;
+        continue;
+      }
+    }
+
+    // we also care about the window this is the more
+    // common case where the content is larger then
+    // the viewport/screen.
+    if (win.scrollMaxX || win.scrollMaxY) {
+      return win;
+    }
+
+    return null;
+  },
+
+  /**
+   * Checks if "top  and "bottom" points of the position is visible.
+   *
+   * @param {Number} top position.
+   * @param {Number} height of the element.
+   * @param {Number} maxHeight of the window.
+   * @return {Boolean} true when visible.
+   */
+  yAxisVisible: function fv_yAxisVisible(top, height, maxHeight) {
+    return (top > 0 && (top + height) < maxHeight);
+  },
+
+  /**
+   * Searches up through the dom for scrollable elements
+   * which are not currently visible (relative to the viewport).
+   *
+   * @param {HTMLElement} element to start search at.
+   * @param {Object} pos .top, .height and .width of element.
+   */
+  scrollablesVisible: function fv_scrollablesVisible(element, pos) {
+    while ((element = this.findScrolled(element))) {
+      if (element.window && element.self === element)
+        break;
+
+      // remember getBoundingClientRect does not care
+      // about scrolling only where the element starts
+      // in the document.
+      let offset = element.getBoundingClientRect();
+
+      // the top of both the scrollable area and
+      // the form element itself are in the same document.
+      // We  adjust the "top" so if the elements coordinates
+      // are relative to the viewport in the current document.
+      let adjustedTop = pos.top - offset.top;
+
+      let visible = this.yAxisVisible(
+        adjustedTop,
+        pos.height,
+        pos.width
+      );
+
+      if (!visible)
+        return false;
+
+      element = element.parentNode;
+    }
+
+    return true;
+  },
+
+  /**
+   * Verifies the element is visible in the viewport.
+   * Handles scrollable areas, frames and scrollable viewport(s) (windows).
+   *
+   * @param {HTMLElement} element to verify.
+   * @return {Boolean} true when visible.
+   */
+  isVisible: function fv_isVisible(element) {
+    // scrollable frames can be ignored we just care about iframes...
+    let rect = element.getBoundingClientRect();
+    let parent = element.ownerDocument.defaultView;
+
+    // used to calculate the inner position of frames / scrollables.
+    // The intent was to use this information to scroll either up or down.
+    // scrollIntoView(true) will _break_ some web content so we can't do
+    // this today. If we want that functionality we need to manually scroll
+    // the individual elements.
+    let pos = {
+      top: rect.top,
+      height: rect.height,
+      width: rect.width
+    };
+
+    let visible = true;
+
+    do {
+      let frame = parent.frameElement;
+      visible = visible &&
+                this.yAxisVisible(pos.top, pos.height, parent.innerHeight) &&
+                this.scrollablesVisible(element, pos);
+
+      // nothing we can do about this now...
+      // In the future we can use this information to scroll
+      // only the elements we need to at this point as we should
+      // have all the details we need to figure out how to scroll.
+      if (!visible)
+        return false;
+
+      if (frame) {
+        let frameRect = frame.getBoundingClientRect();
+
+        pos.top += frameRect.top + frame.clientTop;
+      }
+    } while (
+      (parent !== parent.parent) &&
+      (parent = parent.parent)
+    );
+
+    return visible;
+  }
+};
+
 let FormAssistant = {
   init: function fa_init() {
     addEventListener("focus", this, true, false);
     addEventListener("blur", this, true, false);
     addEventListener("resize", this, true, false);
     addMessageListener("Forms:Select:Choice", this);
     addMessageListener("Forms:Input:Value", this);
     addMessageListener("Forms:Select:Blur", this);
@@ -84,18 +231,20 @@ let FormAssistant = {
   },
 
   handleEvent: function fa_handleEvent(evt) {
     let focusedElement = this.focusedElement;
     let target = evt.target;
 
     switch (evt.type) {
       case "focus":
-        if (this.isTextInputElement(target) && this.isIMEDisabled())
-          return;
+        if (target && isContentEditable(target)) {
+          this.showKeyboard(this.getTopLevelEditable(target));
+          break;
+        }
 
         if (target && this.isFocusableElement(target))
           this.showKeyboard(target);
         break;
 
       case "blur":
         if (this.focusedElement)
           this.hideKeyboard();
@@ -128,17 +277,17 @@ let FormAssistant = {
           this.scrollIntoViewTimeout = null;
         }
 
         // We may receive multiple resize events in quick succession, so wait
         // a bit before scrolling the input element into view.
         if (this.focusedElement) {
           this.scrollIntoViewTimeout = content.setTimeout(function () {
             this.scrollIntoViewTimeout = null;
-            if (this.focusedElement) {
+            if (this.focusedElement && !FormVisibility.isVisible(this.focusedElement)) {
               this.focusedElement.scrollIntoView(false);
             }
           }.bind(this), RESIZE_SCROLL_DELAY);
         }
         break;
     }
   },
 
@@ -188,32 +337,19 @@ let FormAssistant = {
       case "Forms:Select:Blur": {
         this.setFocusedElement(null);
         break;
       }
     }
   },
 
   observe: function fa_observe(subject, topic, data) {
-    switch (topic) {
-      case "xpcom-shutdown":
-        Services.obs.removeObserver(this, "xpcom-shutdown");
-        removeMessageListener("Forms:Select:Choice", this);
-        removeMessageListener("Forms:Input:Value", this);
-        break;
-    }
-  },
-
-  isIMEDisabled: function fa_isIMEDisabled() {
-    let disabled = false;
-    try {
-      disabled = domWindowUtils.IMEStatus == domWindowUtils.IME_STATUS_DISABLED;
-    } catch (e) {}
-
-    return disabled;
+    Services.obs.removeObserver(this, "xpcom-shutdown");
+    removeMessageListener("Forms:Select:Choice", this);
+    removeMessageListener("Forms:Input:Value", this);
   },
 
   showKeyboard: function fa_showKeyboard(target) {
     if (this.isKeyboardOpened)
       return;
 
     if (target instanceof HTMLOptionElement)
       target = target.parentNode;
@@ -227,36 +363,56 @@ let FormAssistant = {
 
   hideKeyboard: function fa_hideKeyboard() {
     sendAsyncMessage("Forms:Input", { "type": "blur" });
     this.isKeyboardOpened = false;
     this.setFocusedElement(null);
   },
 
   isFocusableElement: function fa_isFocusableElement(element) {
-    if (element.contentEditable && element.contentEditable == "true") {
-      return true;
-    }
-
     if (element instanceof HTMLSelectElement ||
         element instanceof HTMLTextAreaElement)
       return true;
 
     if (element instanceof HTMLOptionElement &&
         element.parentNode instanceof HTMLSelectElement)
       return true;
 
     return (element instanceof HTMLInputElement &&
             !this.ignoredInputTypes.has(element.type));
   },
 
   isTextInputElement: function fa_isTextInputElement(element) {
     return element instanceof HTMLInputElement ||
            element instanceof HTMLTextAreaElement ||
-           (element.contentEditable && element.contentEditable == "true");
+           isContentEditable(element);
+  },
+
+  getTopLevelEditable: function fa_getTopLevelEditable(element) {
+    function retrieveTopLevelEditable(element) {
+      // Retrieve the top element that is editable
+      if (element instanceof HTMLHtmlElement)
+        element = element.ownerDocument.body;
+      else if (element instanceof HTMLDocument)
+        element = element.body;
+
+      while (element && !isContentEditable(element))
+        element = element.parentNode;
+
+      // Return the container frame if we are into a nested editable frame
+      if (element &&
+          element instanceof HTMLBodyElement &&
+          element.ownerDocument.defaultView != content.document.defaultView)
+        return element.ownerDocument.defaultView.frameElement;
+    }
+
+    if (element instanceof HTMLIFrameElement)
+      return element;
+
+    return retrieveTopLevelEditable(element) || element;
   },
 
   sendKeyboardState: function(element) {
     // FIXME/bug 729623: work around apparent bug in the IME manager
     // in gecko.
     let readonly = element.getAttribute("readonly");
     if (readonly) {
       return false;
@@ -265,22 +421,37 @@ let FormAssistant = {
     sendAsyncMessage("Forms:Input", getJSON(element));
     return true;
   }
 };
 
 FormAssistant.init();
 
 
+function isContentEditable(element) {
+  if (element.isContentEditable || element.designMode == "on")
+    return true;
+
+  // If a body element is editable and the body is the child of an
+  // iframe we can assume this is an advanced HTML editor
+  if (element instanceof HTMLIFrameElement &&
+      element.contentDocument &&
+      (element.contentDocument.body.isContentEditable ||
+       element.contentDocument.designMode == "on"))
+    return true;
+
+  return element.ownerDocument && element.ownerDocument.designMode == "on";
+}
+
 function getJSON(element) {
   let type = element.type || "";
   let value = element.value || ""
 
   // Treat contenteditble element as a special text field
-  if (element.contentEditable && element.contentEditable == "true") {
+  if (isContentEditable(element)) {
     type = "text";
     value = element.textContent;
   }
 
   // Until the input type=date/datetime/time have been implemented
   // let's return their real type even if the platform returns 'text'
   // Related to Bug 777279 - Implement <input type=time>
   let attributeType = element.getAttribute("type") || "";
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -76,18 +76,22 @@ function getContentWindow() {
 function debug(str) {
   dump(' -*- Shell.js: ' + str + '\n');
 }
 
 var shell = {
 
   get CrashSubmit() {
     delete this.CrashSubmit;
+#ifdef MOZ_CRASHREPORTER
     Cu.import("resource://gre/modules/CrashSubmit.jsm", this);
     return this.CrashSubmit;
+#else
+    return this.CrashSubmit = null;
+#endif
   },
 
   onlineForCrashReport: function shell_onlineForCrashReport() {
     let wifiManager = navigator.mozWifiManager;
     let onWifi = (wifiManager &&
                   (wifiManager.connection.status == 'connected'));
     return !Services.io.offline && onWifi;
   },
@@ -98,17 +102,17 @@ var shell = {
       // For chrome crashes, we want to report the lastRunCrashID.
       if (isChrome) {
         crashID = Cc["@mozilla.org/xre/app-info;1"]
                     .getService(Ci.nsIXULRuntime).lastRunCrashID;
       }
     } catch(e) { }
 
     // Bail if there isn't a valid crashID.
-    if (!crashID && !this.CrashSubmit.pendingIDs().length) {
+    if (!this.CrashSubmit || !crashID && !this.CrashSubmit.pendingIDs().length) {
       return;
     }
 
     // purge the queue.
     this.CrashSubmit.pruneSavedDumps();
 
     try {
       // Check if we should automatically submit this crash.
--- a/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -1,10 +1,10 @@
 <?xml version="1.0"?>
-<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1356125617000">
+<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1357164966000">
   <emItems>
       <emItem  blockID="i58" id="webmaster@buzzzzvideos.info">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i41" id="{99079a25-328f-4bd4-be04-00955acaa0a7}">
                         <versionRange  minVersion="0.1" maxVersion="4.3.1.00" severity="1">
                     </versionRange>
@@ -374,17 +374,17 @@
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i84" id="pink@rosaplugin.info">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i220" id="pricepeep@getpricepeep.com">
-                        <versionRange  minVersion="0" maxVersion="*" severity="1">
+                        <versionRange  minVersion="0" maxVersion="2.1.0.19.99" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i226" id="{462be121-2b54-4218-bf00-b9bf8135b23f}">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i218" id="ffxtlbr@claro.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
@@ -571,24 +571,24 @@
                                 <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="4.0" maxVersion="16.*" />
                           </targetApplication>
                   </versionRange>
                   </pluginItem>
       <pluginItem  blockID="p176">
                   <match name="filename" exp="(NPSWF32\.dll)|(Flash\ Player\.plugin)" />                                    <versionRange  minVersion="0" maxVersion="10.3.183.18.999" severity="0" vulnerabilitystatus="1">
                                 <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="18.0a1" maxVersion="*" />
+                              <versionRange  minVersion="19.0a1" maxVersion="*" />
                           </targetApplication>
                   </versionRange>
                   </pluginItem>
       <pluginItem  blockID="p178">
                   <match name="filename" exp="(NPSWF[0-9_]*\.dll)|(Flash\ Player\.plugin)" />                                    <versionRange  minVersion="11.0" maxVersion="11.4.402.286.999" severity="0" vulnerabilitystatus="1">
                                 <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="18.0a1" maxVersion="*" />
+                              <versionRange  minVersion="19.0a1" maxVersion="*" />
                           </targetApplication>
                   </versionRange>
                   </pluginItem>
       <pluginItem  blockID="p180">
                   <match name="filename" exp="JavaAppletPlugin\.plugin" />                                    <versionRange  minVersion="Java 7 Update 07" maxVersion="Java 7 Update 08" severity="0" vulnerabilitystatus="1">
                                 <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="17.0" maxVersion="*" />
                           </targetApplication>
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -106,27 +106,29 @@ XRE_GetFileFromPathType XRE_GetFileFromP
 XRE_CreateAppDataType XRE_CreateAppData;
 XRE_FreeAppDataType XRE_FreeAppData;
 #ifdef XRE_HAS_DLL_BLOCKLIST
 XRE_SetupDllBlocklistType XRE_SetupDllBlocklist;
 #endif
 XRE_TelemetryAccumulateType XRE_TelemetryAccumulate;
 XRE_StartupTimelineRecordType XRE_StartupTimelineRecord;
 XRE_mainType XRE_main;
+XRE_DisableWritePoisoningType XRE_DisableWritePoisoning;
 
 static const nsDynamicFunctionLoad kXULFuncs[] = {
     { "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
     { "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
     { "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData },
 #ifdef XRE_HAS_DLL_BLOCKLIST
     { "XRE_SetupDllBlocklist", (NSFuncPtr*) &XRE_SetupDllBlocklist },
 #endif
     { "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate },
     { "XRE_StartupTimelineRecord", (NSFuncPtr*) &XRE_StartupTimelineRecord },
     { "XRE_main", (NSFuncPtr*) &XRE_main },
+    { "XRE_DisableWritePoisoning", (NSFuncPtr*) &XRE_DisableWritePoisoning },
     { nullptr, nullptr }
 };
 
 static int do_main(int argc, char* argv[], nsIFile *xreDirectory)
 {
   nsCOMPtr<nsIFile> appini;
   nsresult rv;
 
@@ -382,10 +384,24 @@ int main(int argc, char* argv[])
 
   int result;
   {
     ScopedLogging log;
     result = do_main(argc, argv, xreDirectory);
   }
 
   XPCOMGlueShutdown();
+
+
+#ifdef XP_MACOSX
+  // Allow writes again. While we would like to catch writes from static
+  // destructors to allow early exits to use _exit, we know that there is
+  // at least one such write that we don't control (see bug 826029). For
+  // now we enable writes again and early exits will have to use exit instead
+  // of _exit.
+
+  // Currently write poisoning is only available on OS X. Since on OS X we never
+  // unload XUL, it is safe to call this function after XPCOMGlueShutdown.
+  XRE_DisableWritePoisoning();
+#endif
+
   return result;
 }
rename from browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/setup.js
rename to browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/setup.js.in
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/setup.js
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/setup.js.in
@@ -167,18 +167,20 @@ let TestPilotSetup = {
 
     // Set up observation for task state changes
     var self = this;
     this._obs.add("testpilot:task:changed", this.onTaskStatusChanged, self);
     this._obs.add(
       "testpilot:task:dataAutoSubmitted", this._onTaskDataAutoSubmitted, self);
     // Set up observation for application shutdown.
     this._obs.add("quit-application", this.globalShutdown, self);
+#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
     // Set up observation for enter/exit private browsing:
     this._obs.add("private-browsing", this.onPrivateBrowsingMode, self);
+#endif
 
     // Set up timers to remind user x minutes after startup
     // and once per day thereafter.  Use nsITimer so it doesn't belong to
     // any one window.
     logger.trace("Setting interval for showing reminders...");
 
     this._shortTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
     this._shortTimer.initWithCallback(
@@ -238,39 +240,43 @@ let TestPilotSetup = {
       self.taskList[i].onExperimentShutdown();
     }
     this.taskList = [];
     this._loader.unload();
     this._obs.remove("testpilot:task:changed", this.onTaskStatusChanged, self);
     this._obs.remove(
       "testpilot:task:dataAutoSubmitted", this._onTaskDataAutoSubmitted, self);
     this._obs.remove("quit-application", this.globalShutdown, self);
+#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
     this._obs.remove("private-browsing", this.onPrivateBrowsingMode, self);
+#endif
     this._loader.unload();
     this._shortTimer.cancel();
     this._longTimer.cancel();
     logger.trace("Done unregistering everything.");
   },
 
   _getFrontBrowserWindow: function TPS__getFrontWindow() {
     let wm = Cc["@mozilla.org/appshell/window-mediator;1"].
                getService(Ci.nsIWindowMediator);
     // TODO Is "most recent" the same as "front"?
     return wm.getMostRecentWindow("navigator:browser");
   },
 
+#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
   onPrivateBrowsingMode: function TPS_onPrivateBrowsingMode(topic, data) {
     for (let i = 0; i < this.taskList.length; i++) {
       if (data == "enter") {
         this.taskList[i].onEnterPrivateBrowsing();
       } else if (data == "exit") {
         this.taskList[i].onExitPrivateBrowsing();
       }
     }
   },
+#endif
 
   onWindowUnload: function TPS__onWindowRegistered(window) {
     this._logger.trace("Called TestPilotSetup.onWindow unload!");
     for (let i = 0; i < this.taskList.length; i++) {
       this.taskList[i].onWindowClosed(window);
     }
   },
 
rename from browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/tasks.js
rename to browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/tasks.js.in
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/tasks.js
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/tasks.js.in
@@ -157,21 +157,23 @@ var TestPilotTask = {
   onAppStartup: function TestPilotTask_onAppStartup() {
     // Called by extension core when Firefox startup is complete.
   },
 
   onAppShutdown: function TestPilotTask_onAppShutdown() {
     // Called by extension core when Firefox is shutting down.
   },
 
+#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
   onEnterPrivateBrowsing: function TestPilotTask_onEnterPrivate() {
   },
 
   onExitPrivateBrowsing: function TestPilotTask_onExitPrivate() {
   },
+#endif
 
   onNewWindow: function TestPilotTask_onNewWindow(window) {
   },
 
   onWindowClosed: function TestPilotTask_onWindowClosed(window) {
   },
 
   onUrlLoad: function TestPilotTask_onUrlLoad(url) {
@@ -527,16 +529,17 @@ TestPilotExperiment.prototype = {
       try {
         this._handlers.doExperimentCleanup();
       } catch(e) {
         this._dataStore.logException("doExperimentCleanup: " + e);
       }
     }
   },
 
+#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
   onEnterPrivateBrowsing: function TestPilotExperiment_onEnterPrivate() {
     this._logger.trace("Task is entering private browsing.");
     if (this.experimentIsRunning()) {
       try {
         this._handlers.onEnterPrivateBrowsing();
       } catch(e) {
         this._dataStore.logException("onEnterPrivateBrowsing: " + e);
       }
@@ -548,16 +551,17 @@ TestPilotExperiment.prototype = {
     if (this.experimentIsRunning()) {
       try {
         this._handlers.onExitPrivateBrowsing();
       } catch(e) {
         this._dataStore.logException("onExitPrivateBrowsing: " + e);
       }
     }
   },
+#endif
 
   getStudyMetadata: function TestPilotExperiment_getStudyMetadata() {
     try {
       if (this._handlers.getStudyMetadata) {
         let metadata = this._handlers.getStudyMetadata();
         if (metadata.length) {
           // getStudyMetadata must return an array, otherwise it is invalid.
           return metadata;
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -531,16 +531,21 @@ pref("browser.gesture.tap", "cmd_fullZoo
 // scrolling to shift+wheel.
 pref("mousewheel.with_alt.action", 2);
 pref("mousewheel.with_shift.action", 1);
 // On MacOS X, control+wheel is typically handled by system and we don't
 // receive the event.  So, command key which is the main modifier key for
 // acceleration is the best modifier for zoom-in/out.  However, we should keep
 // the control key setting for backward compatibility.
 pref("mousewheel.with_meta.action", 3); // command key on Mac
+// Disable control-/meta-modified horizontal mousewheel events, since
+// those are used on Mac as part of modified swipe gestures (e.g.
+// Left swipe+Cmd = go back in a new tab).
+pref("mousewheel.with_control.action.override_x", 0);
+pref("mousewheel.with_meta.action.override_x", 0);
 #else
 pref("mousewheel.with_alt.action", 1);
 pref("mousewheel.with_shift.action", 2);
 pref("mousewheel.with_meta.action", 1); // win key on Win, Super/Hyper on Linux
 #endif
 pref("mousewheel.with_control.action",3);
 pref("mousewheel.with_win.action", 1);
 
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -560,17 +560,17 @@
 #endif
               <menuseparator id="devToolsSeparator"/>
               <menu id="webDeveloperMenu"
                     label="&webDeveloperMenu.label;"
                     accesskey="&webDeveloperMenu.accesskey;">
                 <menupopup id="menuWebDeveloperPopup">
                   <menuitem id="menu_devToolbox"
                             observes="devtoolsMenuBroadcaster_DevToolbox"
-                            accesskey="&devToolbox.accesskey;"/>
+                            accesskey="&devToolboxMenuItem.accesskey;"/>
                   <menuseparator id="menu_devtools_separator"/>
                   <menuitem id="menu_devToolbar"
                             observes="devtoolsMenuBroadcaster_DevToolbar"
                             accesskey="&devToolbarMenu.accesskey;"/>
                   <menuitem id="menu_chromeDebugger"
                             observes="devtoolsMenuBroadcaster_ChromeDebugger"/>
                   <menuitem id="menu_responsiveUI"
                             observes="devtoolsMenuBroadcaster_ResponsiveUI"
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -59,35 +59,35 @@ var StarUI = {
       case "popuphidden":
         if (aEvent.originalTarget == this.panel) {
           if (!this._element("editBookmarkPanelContent").hidden)
             this.quitEditMode();
 
           this._restoreCommandsState();
           this._itemId = -1;
           if (this._batching) {
-            PlacesUtils.transactionManager.endBatch();
+            PlacesUtils.transactionManager.endBatch(false);
             this._batching = false;
           }
 
           switch (this._actionOnHide) {
             case "cancel": {
               PlacesUtils.transactionManager.undoTransaction();
               break;
             }
             case "remove": {
               // Remove all bookmarks for the bookmark's url, this also removes
               // the tags for the url.
-              PlacesUtils.transactionManager.beginBatch();
+              PlacesUtils.transactionManager.beginBatch(null);
               let itemIds = PlacesUtils.getBookmarksForURI(this._uriForRemoval);
               for (let i = 0; i < itemIds.length; i++) {
                 let txn = new PlacesRemoveItemTransaction(itemIds[i]);
                 PlacesUtils.transactionManager.doTransaction(txn);
               }
-              PlacesUtils.transactionManager.endBatch();
+              PlacesUtils.transactionManager.endBatch(false);
               break;
             }
           }
           this._actionOnHide = "";
         }
         break;
       case "keypress":
         if (aEvent.defaultPrevented) {
@@ -230,17 +230,17 @@ var StarUI = {
   removeBookmarkButtonCommand: function SU_removeBookmarkButtonCommand() {
     this._uriForRemoval = PlacesUtils.bookmarks.getBookmarkURI(this._itemId);
     this._actionOnHide = "remove";
     this.panel.hidePopup();
   },
 
   beginBatch: function SU_beginBatch() {
     if (!this._batching) {
-      PlacesUtils.transactionManager.beginBatch();
+      PlacesUtils.transactionManager.beginBatch(null);
       this._batching = true;
     }
   }
 }
 
 var PlacesCommandHook = {
   /**
    * Adds a bookmark to the page loaded in the given browser.
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -169,17 +169,17 @@
     <broadcaster id="sync-syncnow-state"/>
 #endif
     <broadcaster id="workOfflineMenuitemState"/>
     <broadcaster id="socialSidebarBroadcaster" hidden="true"/>
     <broadcaster id="socialActiveBroadcaster" hidden="true"/>
 
     <!-- DevTools broadcasters -->
     <broadcaster id="devtoolsMenuBroadcaster_DevToolbox"
-                 label="&devToolbarToolsButton.label;"
+                 label="&devToolboxMenuItem.label;"
                  type="checkbox" autocheck="false"
                  command="Tools:DevToolbox"/>
     <broadcaster id="devtoolsMenuBroadcaster_DevToolbar"
                  label="&devToolbarMenu.label;"
                  type="checkbox" autocheck="false"
                  command="Tools:DevToolbar"
                  key="key_devToolbar"/>
     <broadcaster id="devtoolsMenuBroadcaster_ChromeDebugger"
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1511,16 +1511,21 @@ var gBrowserInit = {
     // In certain scenarios it's possible for unload to be fired before onload,
     // (e.g. if the window is being closed after browser.js loads but before the
     // load completes). In that case, there's nothing to do here.
     if (!this._loadHandled)
       return;
 
     gDevToolsBrowser.forgetBrowserWindow(window);
 
+    let desc = Object.getOwnPropertyDescriptor(window, "DeveloperToolbar");
+    if (desc && !desc.get) {
+      DeveloperToolbar.destroy();
+    }
+
     // First clean up services initialized in gBrowserInit.onLoad (or those whose
     // uninit methods don't depend on the services having been initialized).
     allTabs.uninit();
 
     CombinedStopReload.uninit();
 
     gGestureSupport.init(false);
 
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -1147,17 +1147,18 @@
             <hbox class="gclitoolbar-prompt">
               <label class="gclitoolbar-prompt-label">&#187;</label>
             </hbox>
             <hbox class="gclitoolbar-complete-node"/>
             <textbox class="gclitoolbar-input-node" rows="1"/>
           </stack>
           <toolbarbutton id="developer-toolbar-toolbox-button"
                          class="developer-toolbar-button"
-                         observes="devtoolsMenuBroadcaster_DevToolbox"/>
+                         observes="devtoolsMenuBroadcaster_DevToolbox"
+                         tooltiptext="&devToolbarToolsButton.tooltip;"/>
 #ifndef XP_MACOSX
           <toolbarbutton id="developer-toolbar-closebutton"
                          class="devtools-closebutton"
                          oncommand="DeveloperToolbar.hide();"
                          tooltiptext="&devToolbarCloseButton.tooltiptext;"/>
 #endif
    </toolbar>
 
--- a/browser/build.mk
+++ b/browser/build.mk
@@ -9,18 +9,16 @@ endif
 TIERS += app
 
 ifdef MOZ_EXTENSIONS
 tier_app_dirs += extensions
 endif
 
 tier_app_dirs += $(MOZ_BRANDING_DIRECTORY)
 
-tier_app_dirs += services
-
 ifdef MOZ_WEBAPP_RUNTIME
 tier_app_dirs += webapprt
 endif
 
 tier_app_dirs += browser
 # Never add other tier_app_dirs after browser. They won't get packaged
 # properly on mac.
 
--- a/browser/components/downloads/content/allDownloadsViewOverlay.css
+++ b/browser/components/downloads/content/allDownloadsViewOverlay.css
@@ -21,14 +21,13 @@ richlistitem.download {
                               [state="9"]) /* Blocked (policy)   */)
                                            .downloadRemoveFromHistoryMenuItem,
 .download-state:not(:-moz-any([state="-1"],/* Starting (initial) */
                               [state="0"], /* Downloading        */
                               [state="1"], /* Finished           */
                               [state="4"], /* Paused             */
                               [state="5"]) /* Starting (queued)  */)
                                            .downloadShowMenuItem,
-
-.download-state[state="7"]                 .downloadCommandsSeparator
-
+.download-state[state="7"]                 .downloadCommandsSeparator,
+.download-state:not([state])                 .downloadCommandsSeparator
 {
   display: none;
 }
--- a/browser/components/downloads/content/allDownloadsViewOverlay.js
+++ b/browser/components/downloads/content/allDownloadsViewOverlay.js
@@ -7,33 +7,38 @@
  * IT IS HIGHLY RECOMMENDED NOT TO EXTEND IT FOR ANY OTHER USE CASES OR RELY
  * ON IT AS AN API.
  */
 
 let Cu = Components.utils;
 let Ci = Components.interfaces;
 let Cc = Components.classes;
 
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/NetUtil.jsm");
 Cu.import("resource://gre/modules/DownloadUtils.jsm");
 Cu.import("resource:///modules/DownloadsCommon.jsm");
 Cu.import("resource://gre/modules/PlacesUtils.jsm");
+Cu.import("resource://gre/modules/osfile.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
+                                  "resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 const nsIDM = Ci.nsIDownloadManager;
 
 const DESTINATION_FILE_URI_ANNO  = "downloads/destinationFileURI";
 const DESTINATION_FILE_NAME_ANNO = "downloads/destinationFileName";
 const DOWNLOAD_STATE_ANNO        = "downloads/state";
 
 const DOWNLOAD_VIEW_SUPPORTED_COMMANDS =
  ["cmd_delete", "cmd_copy", "cmd_paste", "cmd_selectAll",
   "downloadsCmd_pauseResume", "downloadsCmd_cancel",
   "downloadsCmd_open", "downloadsCmd_show", "downloadsCmd_retry",
-  "downloadsCmd_openReferrer"];
+  "downloadsCmd_openReferrer", "downloadsCmd_clearDownloads"];
 
 const NOT_AVAILABLE = Number.MAX_VALUE;
 
 function GetFileForFileURI(aFileURI)
   Cc["@mozilla.org/network/protocol;1?name=file"]
     .getService(Ci.nsIFileProtocolHandler)
     .getFileFromURLSpec(aFileURI);
 
@@ -88,40 +93,49 @@ DownloadElementShell.prototype = {
   // The data item for the download
   _dataItem: null,
   get dataItem() this._dataItem,
 
   set dataItem(aValue) {
     if ((this._dataItem = aValue)) {
       this._wasDone = this._dataItem.done;
       this._wasInProgress = this._dataItem.inProgress;
+      this._targetFileInfoFetched = false;
+      this._fetchTargetFileInfo();
     }
     else if (this._placesNode) {
       this._wasInProgress = false;
       this._wasDone = this.getDownloadState(true) == nsIDM.DOWNLOAD_FINISHED;
+      this._targetFileInfoFetched = false;
+      this._fetchTargetFileInfo();
     }
 
     this._updateStatusUI();
     return aValue;
   },
 
   _placesNode: null,
   get placesNode() this._placesNode,
   set placesNode(aNode) {
     if (this._placesNode != aNode) {
       // Preserve the annotations map if this is the first loading and we got
       // cached values.
       if (this._placesNode || !this._annotations) {
         this._annotations = new Map();
       }
       this._placesNode = aNode;
+
+      // We don't need to update the UI if we had a data item, because
+      // the places information isn't used in this case.
       if (!this._dataItem && this._placesNode) {
         this._wasInProgress = false;
         this._wasDone = this.getDownloadState(true) == nsIDM.DOWNLOAD_FINISHED;
+        this._targetFileInfoFetched = false;
         this._updateStatusUI();
+        this._fetchTargetFileInfo();
       }
     }
     return aNode;
   },
 
   // The download uri (as a string)
   get downloadURI() {
     if (this._dataItem)
@@ -172,106 +186,118 @@ DownloadElementShell.prototype = {
       }
       value = aDefaultValue;
     }
 
     this._annotations.set(aAnnotation, value);
     return value;
   },
 
-  // The uri (as a string) of the target file, if any.
-  get _targetFileURI() {
-    if (this._dataItem)
-      return this._dataItem.file;
-
-    return this._getAnnotation(DESTINATION_FILE_URI_ANNO, "");
-  },
-
   // The label for the download
   get _displayName() {
     if (this._dataItem)
       return this._dataItem.target;
 
     try {
       return this._getAnnotation(DESTINATION_FILE_NAME_ANNO);
     }
     catch(ex) { }
 
     // Fallback to the places title, or, at last, to the download uri.
     return this._placesNode.title || this.downloadURI;
   },
 
-  // If there's a target file for the download, this is its nsIFile object.
-  get _file() {
-    if (!("__file" in this)) {
-      if (this._dataItem) {
-        this.__file = this._dataItem.localFile;
-      }
-      else {
-        this.__file = this._targetFileURI ?
-          GetFileForFileURI(this._targetFileURI) : null;
-      }
-    }
-    return this.__file;
+  // The uri (as a string) of the target file, if any.
+  get _targetFileURI() {
+    if (this._dataItem)
+      return this._dataItem.file;
+
+    return this._getAnnotation(DESTINATION_FILE_URI_ANNO, "");
+  },
+
+  get _targetFilePath() {
+    let fileURI = this._targetFileURI;
+    if (fileURI)
+      return GetFileForFileURI(fileURI).path;
+    return "";
   },
 
-  // The target's file size in bytes. If there's no target file, or If we
-  // cannot determine its size, 0 is returned.
-  get _fileSize() {
-    if (!("__fileSize" in this)) {
-      if (!this._file || !this._file.exists())
-        this.__fileSize = 0;
-      try {
-        this.__fileSize = this._file.fileSize;
-      }
-      catch(ex) {
-        Cu.reportError(ex);
-        this.__fileSize = 0;
-      }
+  _fetchTargetFileInfo: function DES__fetchTargetFileInfo() {
+    if (this._targetFileInfoFetched)
+      throw new Error("_fetchTargetFileInfo should not be called if the information was already fetched");
+
+    let path = this._targetFilePath;
+
+    // In previous version, the target file annotations were not set,
+    // so we cannot where is the file.
+    if (!path) {
+      this._targetFileInfoFetched = true;
+      this._targetFileExists = false;
+      return;
     }
-    return this.__fileSize;
+
+    OS.File.stat(path).then(
+      function onSuccess(fileInfo) {
+        this._targetFileInfoFetched = true;
+        this._targetFileExists = true;
+        this._targetFileSize = fileInfo.size;
+        delete this._state;
+        this._updateDownloadStatusUI();
+      }.bind(this),
+
+      function onFailure(aReason) {
+        if (reason instanceof OS.File.Error && reason.becauseNoSuchFile) {
+          this._targetFileInfoFetched = true;
+          this._targetFileExists = false;
+        }
+        else {
+          Cu.reportError("Could not fetch info for target file (reason: " +
+                         aReason + ")");
+        }
+
+        this._updateDownloadStatusUI();
+      }.bind(this)
+    );
   },
 
   /**
-   * Get the state of the download
+   * Get the state of the download (see nsIDownloadManager).
+   * For past downloads, for which we don't know the state at first,
+   * |undefined| is returned until we have info for the target file,
+   * indicating the state is unknown. |undefined| is also returned
+   * if the file was not found at last.
+   *
    * @param [optional] aForceUpdate
    *        Whether to force update the cached download state. Default: false.
+   * @return the download state if available, |undefined| otherwise.
    */
-  // The download state (see nsIDownloadManager).
   getDownloadState: function DES_getDownloadState(aForceUpdate = false) {
     if (aForceUpdate || !("_state" in this)) {
       if (this._dataItem) {
         this._state = this._dataItem.state;
       }
       else {
         try {
           this._state = this._getAnnotation(DOWNLOAD_STATE_ANNO);
         }
         catch (ex) {
-          // The state annotation didn't exist in past releases.
-          if (!this._file) {
+          if (!this._targetFileInfoFetched || !this._targetFileExists)
+            this._state = undefined;
+          else if (this._targetFileSize > 0)
+            this._state = nsIDM.DOWNLOAD_FINISHED;
+          else
             this._state = nsIDM.DOWNLOAD_FAILED;
-          }
-          else if (this._file.exists()) {
-            this._state = this._fileSize > 0 ?
-              nsIDM.DOWNLOAD_FINISHED : nsIDM.DOWNLOAD_FAILED;
-          }
-          else {
-            // XXXmano I'm not sure if this right. We should probably show no
-            // status text at all in this case.
-            this._state = nsIDM.DOWNLOAD_CANCELED;
-          }
         }
       }
     }
     return this._state;
   },
 
   // The status text for the download
-  get _statusText() {
+  _getStatusText: function DES__getStatusText() {
     let s = DownloadsCommon.strings;
     if (this._dataItem && this._dataItem.inProgress) {
       if (this._dataItem.paused) {
         let transfer =
           DownloadUtils.getTransferTotal(this._dataItem.currBytes,
                                          this._dataItem.maxBytes);
 
          // We use the same XUL label to display both the state and the amount
@@ -311,25 +337,25 @@ DownloadElementShell.prototype = {
       case nsIDM.DOWNLOAD_BLOCKED_PARENTAL:
         return s.stateBlockedParentalControls;
       case nsIDM.DOWNLOAD_BLOCKED_POLICY:
         return s.stateBlockedPolicy;
       case nsIDM.DOWNLOAD_DIRTY:
         return s.stateDirty;
       case nsIDM.DOWNLOAD_FINISHED:{
         // For completed downloads, show the file size (e.g. "1.5 MB")
-        if (this._fileSize > 0) {
-          let [size, unit] = DownloadUtils.convertByteUnits(this._fileSize);
+        if (this._targetFileInfoFetched && this._targetFileExists) {
+          let [size, unit] = DownloadUtils.convertByteUnits(this._targetFileSize);
           return s.sizeWithUnits(size, unit);
         }
         break;
       }
     }
 
-    return "";
+    return s.sizeUnknown;
   },
 
   // The progressmeter element for the download
   get _progressElement() {
     let progressElement = document.getAnonymousElementByAttribute(
       this._element, "anonid", "progressmeter");
     if (progressElement) {
       delete this._progressElement;
@@ -337,18 +363,21 @@ DownloadElementShell.prototype = {
     }
     return null;
   },
 
   // Updates the download state attribute (and by that hide/unhide the
   // appropriate buttons and context menu items), the status text label,
   // and the progress meter.
   _updateDownloadStatusUI: function  DES__updateDownloadStatusUI() {
-    this._element.setAttribute("state", this.getDownloadState(true));
-    this._element.setAttribute("status", this._statusText);
+    let state = this.getDownloadState(true);
+    if (state !== undefined)
+      this._element.setAttribute("state", state);
+
+    this._element.setAttribute("status", this._getStatusText());
 
     // For past-downloads, we're done. For session-downloads, we may also need
     // to update the progress-meter.
     if (!this._dataItem)
       return;
 
     // Copied from updateProgress in downloads.js.
     if (this._dataItem.starting) {
@@ -369,24 +398,22 @@ DownloadElementShell.prototype = {
     }
 
     // Dispatch the ValueChange event for accessibility, if possible.
     if (this._progressElement) {
       let event = document.createEvent("Events");
       event.initEvent("ValueChange", true, true);
       this._progressElement.dispatchEvent(event);
     }
-
-    goUpdateDownloadCommands();
   },
 
   _updateStatusUI: function DES__updateStatusUI() {
-    this._updateDownloadStatusUI();
+    this._element.setAttribute("displayName", this._displayName);
     this._element.setAttribute("image", this._icon);
-    this._element.setAttribute("displayName", this._displayName);
+    this._updateDownloadStatusUI();
   },
 
   placesNodeIconChanged: function DES_placesNodeIconChanged() {
     if (!this._dataItem)
       this._element.setAttribute("image", this._icon);
   },
 
   placesNodeTitleChanged: function DES_placesNodeTitleChanged() {
@@ -401,102 +428,122 @@ DownloadElementShell.prototype = {
         this._element.setAttribute("image", this._icon);
         this._updateDownloadStatusUI();
       }
       else if (aAnnoName == DESTINATION_FILE_NAME_ANNO) {
         this._element.setAttribute("displayName", this._displayName);
       }
       else if (aAnnoName == DOWNLOAD_STATE_ANNO) {
         this._updateDownloadStatusUI();
+        if (this._element.selected)
+          goUpdateDownloadCommands();
       }
     }
   },
 
   /* DownloadView */
   onStateChange: function DES_onStateChange() {
-    // See comment in DVI_onStateChange in downloads.js (the panel-view)
-    if (!this._wasDone && this._dataItem.done)
+    if (!this._wasDone && this._dataItem.done) {
+      // See comment in DVI_onStateChange in downloads.js (the panel-view)
       this._element.setAttribute("image", this._icon + "&state=normal");
 
+      this._targetFileInfoFetched = false;
+      this._fetchTargetFileInfo();
+    }
+
     this._wasDone = this._dataItem.done;
 
     // Update the end time using the current time if required.
     if (this._wasInProgress && !this._dataItem.inProgress) {
       this._endTime = Date.now();
     }
 
     this._wasDone = this._dataItem.done;
     this._wasInProgress = this._dataItem.inProgress;
 
     this._updateDownloadStatusUI();
+    if (this._element.selected)
+      goUpdateDownloadCommands();
   },
 
   /* DownloadView */
   onProgressChange: function DES_onProgressChange() {
     this._updateDownloadStatusUI();
   },
 
   /* nsIController */
   isCommandEnabled: function DES_isCommandEnabled(aCommand) {
     switch (aCommand) {
       case "downloadsCmd_open": {
-        return this._file.exists() &&
-               ((this._dataItem && this._dataItem.openable) ||
-                (this.getDownloadState() == nsIDM.DOWNLOAD_FINISHED));
+        // We cannot open a session dowload file unless it's done ("openable").
+        // If it's finished, we need to make sure the file was not removed,
+        // as we do for past downloads.
+        if (this._dataItem && !this._dataItem.openable)
+          return false;
+
+        // Disable the command until we can yet tell whether
+        // or not the file is there.
+        if (!this._targetFileInfoFetched)
+          return false;
+
+        return this._targetFileExists;
       }
       case "downloadsCmd_show": {
-        return this._getTargetFileOrPartFileIfExists() != null;
+        // TODO: Bug 827010 - Handle part-file asynchronously. 
+        if (this._dataItem &&
+            this._dataItem.partFile && this._dataItem.partFile.exists())
+          return true;
+
+        // Disable the command until we can yet tell whether
+        // or not the file is there.
+        if (!this._targetFileInfoFetched)
+          return false;
+
+        return this._targetFileExists;
       }
       case "downloadsCmd_pauseResume":
         return this._dataItem && this._dataItem.inProgress && this._dataItem.resumable;
       case "downloadsCmd_retry":
-        return ((this._dataItem && this._dataItem.canRetry) ||
-                (!this._dataItem && this._file))
+        // Disable the retry command for past downloads until it's fully implemented.
+        return this._dataItem && this._dataItem.canRetry;
       case "downloadsCmd_openReferrer":
         return this._dataItem && !!this._dataItem.referrer;
       case "cmd_delete":
         // The behavior in this case is somewhat unexpected, so we disallow that.
         if (this._placesNode && this._dataItem && this._dataItem.inProgress)
           return false;
         return true;
       case "downloadsCmd_cancel":
         return this._dataItem != null;
     }
     return false;
   },
 
-  _getTargetFileOrPartFileIfExists: function DES__getTargetFileOrPartFileIfExists() {
-    if (this._file && this._file.exists())
-      return this._file;
-    if (this._dataItem &&
-        this._dataItem.partFile && this._dataItem.partFile.exists())
-      return this._dataItem.partFile;
-    return null;
-  },
-
   _retryAsHistoryDownload: function DES__retryAsHistoryDownload() {
     // TODO: save in the right location (the current saveURL api does not allow this)
     saveURL(this.downloadURI, this._displayName, null, true, true, undefined, document);
   },
 
   /* nsIController */
   doCommand: function DES_doCommand(aCommand) {
     switch (aCommand) {
       case "downloadsCmd_open": {
         if (this._dateItem)
           this._dataItem.openLocalFile(window);
         else
-          DownloadsCommon.openDownloadedFile(this._file, null, window);
+          DownloadsCommon.openDownloadedFile(
+            GetFileForFileURI(this._targetFileURI), null, window);
         break;
       }
       case "downloadsCmd_show": {
         if (this._dataItem)
           this._dataItem.showLocalFile();
         else
-          DownloadsCommon.showDownloadedFile(this._getTargetFileOrPartFileIfExists());
+          DownloadsCommon.showDownloadedFile(
+            GetFileForFileURI(this._targetFileURI));
         break;
       }
       case "downloadsCmd_openReferrer": {
         openURL(this._dataItem.referrer);
         break;
       }
       case "downloadsCmd_cancel": {
         this._dataItem.cancel();
@@ -821,17 +868,17 @@ DownloadsPlacesView.prototype = {
     else {
       shell.dataItem = null;
       // Move it below the session-download items;
       if (this._lastSessionDownloadElement == shell.dataItem) {
         this._lastSessionDownloadElement = shell.dataItem.previousSibling;
       }
       else {
         let before = this._lastSessionDownloadElement ?
-          this._lastSessionDownloadElement.nextSibling : this._richlistbox.firstchild;
+          this._lastSessionDownloadElement.nextSibling : this._richlistbox.firstChild;
         this._richlistbox.insertBefore(shell.element, before);
       }
     }
   },
 
   _place: "",
   get place() this._place,
   set place(val) {
@@ -960,16 +1007,17 @@ DownloadsPlacesView.prototype = {
   nodeDateAddedChanged: function() {},
   nodeLastModifiedChanged: function() {},
   nodeReplaced: function() {},
   nodeHistoryDetailsChanged: function() {},
   nodeTagsChanged: function() {},
   sortingChanged: function() {},
   nodeMoved: function() {},
   nodeURIChanged: function() {},
+  batching: function() {},
 
   get controller() this._richlistbox.controller,
 
   get searchTerm() this._searchTerm,
   set searchTerm(aValue) {
     if (this._searchTerm != aValue) {
       for (let element of this._richlistbox.childNodes) {
         element.hidden = !element._shell.matchesSearchTerm(aValue);
@@ -1007,16 +1055,18 @@ DownloadsPlacesView.prototype = {
     let selectedElements = this._richlistbox.selectedItems;
     switch (aCommand) {
       case "cmd_copy":
         return selectedElements && selectedElements.length > 0;
       case "cmd_selectAll":
         return true;
       case "cmd_paste":
         return this._canDownloadClipboardURL();
+      case "downloadsCmd_clearDownloads":
+        return !!this._richlistbox.firstChild;
       default:
         return Array.every(selectedElements, function(element) {
           return element._shell.isCommandEnabled(aCommand);
         });
     }
   },
 
   _copySelectedDownloadsToClipboard:
@@ -1068,16 +1118,28 @@ DownloadsPlacesView.prototype = {
         this._copySelectedDownloadsToClipboard();
         break;
       case "cmd_selectAll":
         this._richlistbox.selectAll();
         break;
       case "cmd_paste":
         this._downloadURLFromClipboard();
         break;
+      case "downloadsCmd_clearDownloads":
+        if (PrivateBrowsingUtils.isWindowPrivate(window)) {
+          Services.downloads.cleanUpPrivate();
+        } else {
+          Services.downloads.cleanUp();
+        }
+        if (this.result) {
+          Cc["@mozilla.org/browser/download-history;1"]
+            .getService(Ci.nsIDownloadHistory)
+            .removeAllDownloads();
+        }
+        break;
       default: {
         let selectedElements = this._richlistbox.selectedItems;
         for (let element of selectedElements) {
           element._shell.doCommand(aCommand);
         }
       }
     }
   },
@@ -1087,17 +1149,22 @@ DownloadsPlacesView.prototype = {
   onContextMenu: function DPV_onContextMenu(aEvent)
   {
     let element = this._richlistbox.selectedItem;
     if (!element || !element._shell)
       return false;
 
     // Set the state attribute so that only the appropriate items are displayed.
     let contextMenu = document.getElementById("downloadsContextMenu");
-    contextMenu.setAttribute("state", element._shell.getDownloadState());
+    let state = element._shell.getDownloadState();
+    if (state !== undefined)
+      contextMenu.setAttribute("state", state);
+    else
+      contextMenu.removeAttribute("state");
+
     return true;
   },
 
   onKeyPress: function DPV_onKeyPress(aEvent) {
     let selectedElements = this._richlistbox.selectedItems;
     if (!selectedElements)
       return;
 
@@ -1113,16 +1180,29 @@ DownloadsPlacesView.prototype = {
     }
     else if (aEvent.charCode == " ".charCodeAt(0)) {
       // Pausue/Resume every selected download
       for (let element of selectedElements) {
         if (element._shell.isCommandEnabled("downloadsCmd_pauseResume"))
           element._shell.doCommand("downloadsCmd_pauseResume");
       }
     }
+  },
+
+  onDoubleClick: function DPV_onDoubleClick(aEvent) {
+    if (aEvent.button != 0)
+      return;
+
+    let selectedElements = this._richlistbox.selectedItems;
+    if (!selectedElements || selectedElements.length != 1)
+      return;
+
+    let element = selectedElements[0];
+    if (element._shell)
+      element._shell.doDefaultCommand();
   }
 };
 
 function goUpdateDownloadCommands() {
   for (let command of DOWNLOAD_VIEW_SUPPORTED_COMMANDS) {
     goUpdateCommand(command);
   }
 }
--- a/browser/components/downloads/content/allDownloadsViewOverlay.xul
+++ b/browser/components/downloads/content/allDownloadsViewOverlay.xul
@@ -38,17 +38,21 @@
           src="chrome://browser/content/downloads/allDownloadsViewOverlay.js"/>
   <script type="application/javascript"
           src="chrome://global/content/contentAreaUtils.js"/>
 
   <richlistbox flex="1"
                seltype="multiple"
                id="downloadsRichListBox" context="downloadsContextMenu"
                onkeypress="return this._placesView.onKeyPress(event);"
-               oncontextmenu="return this._placesView.onContextMenu(event);"/>
+               ondblclick="return this._placesView.onDoubleClick(event);"
+               oncontextmenu="return this._placesView.onContextMenu(event);"
+               onfocus="goUpdateDownloadCommands();"
+               onselect="goUpdateDownloadCommands();"
+               onblur="goUpdateDownloadCommands();"/>
 
   <commandset id="downloadCommands"
               commandupdater="true"
               events="focus,select,contextmenu"
               oncommandupdate="goUpdateDownloadCommands();">
     <command id="downloadsCmd_pauseResume"
              oncommand="goDoCommand('downloadsCmd_pauseResume')"/>
     <command id="downloadsCmd_cancel"
@@ -56,16 +60,18 @@
     <command id="downloadsCmd_open"
              oncommand="goDoCommand('downloadsCmd_open')"/>
     <command id="downloadsCmd_show"
              oncommand="goDoCommand('downloadsCmd_show')"/>
     <command id="downloadsCmd_retry"
              oncommand="goDoCommand('downloadsCmd_retry')"/>
     <command id="downloadsCmd_openReferrer"
              oncommand="goDoCommand('downloadsCmd_openReferrer')"/>
+    <command id="downloadsCmd_clearDownloads"
+             oncommand="goDoCommand('downloadsCmd_clearDownloads')"/>
   </commandset>
 
   <menupopup id="downloadsContextMenu" class="download-state">
     <menuitem command="downloadsCmd_pauseResume"
               class="downloadPauseMenuItem"
               label="&cmd.pause.label;"
               accesskey="&cmd.pause.accesskey;"/>
     <menuitem command="downloadsCmd_pauseResume"
@@ -94,10 +100,16 @@
     <menuseparator class="downloadCommandsSeparator"/>
 
     <menuitem command="downloadsCmd_openReferrer"
               label="&cmd.goToDownloadPage.label;"
               accesskey="&cmd.goToDownloadPage.accesskey;"/>
     <menuitem command="cmd_copy"
               label="&cmd.copyDownloadLink.label;"
               accesskey="&cmd.copyDownloadLink.accesskey;"/>
+
+    <menuseparator/>
+
+    <menuitem command="downloadsCmd_clearDownloads"
+              label="&cmd.clearDownloads.label;"
+              accesskey="&cmd.clearDownloads.accesskey;"/>
   </menupopup>
 </overlay>
--- a/browser/components/downloads/content/download.css
+++ b/browser/components/downloads/content/download.css
@@ -34,12 +34,14 @@ richlistitem.download button {
                               [state="4"]) /* Paused             */)
                                            .downloadCancel,
 
 .download-state:not(:-moz-any([state="2"], /* Failed             */
                               [state="3"]) /* Canceled           */)
                                            .downloadRetry,
 
 .download-state:not(          [state="1"]  /* Finished           */)
-                                           .downloadShow
+                                           .downloadShow,
+
+.download-state:not([state]) > button
 {
   display: none;
 }
--- a/browser/components/places/content/bookmarkProperties.js
+++ b/browser/components/places/content/bookmarkProperties.js
@@ -400,25 +400,25 @@ var BookmarkPropertiesPanel = {
         break;
     }
   },
 
   _beginBatch: function BPP__beginBatch() {
     if (this._batching)
       return;
 
-    PlacesUtils.transactionManager.beginBatch();
+    PlacesUtils.transactionManager.beginBatch(null);
     this._batching = true;
   },
 
   _endBatch: function BPP__endBatch() {
     if (!this._batching)
       return;
 
-    PlacesUtils.transactionManager.endBatch();
+    PlacesUtils.transactionManager.endBatch(false);
     this._batching = false;
   },
 
   _fillEditProperties: function BPP__fillEditProperties() {
     gEditItemOverlay.initPanel(this._itemId,
                                { hiddenRows: this._hiddenRows,
                                  forceReadOnly: this._readOnly });
   },
--- a/browser/components/places/content/downloadsViewOverlay.xul
+++ b/browser/components/places/content/downloadsViewOverlay.xul
@@ -1,29 +1,44 @@
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 <?xul-overlay href="chrome://browser/content/downloads/allDownloadsViewOverlay.xul"?>
 
+<!DOCTYPE overlay [
+<!ENTITY % downloadsDTD SYSTEM "chrome://browser/locale/downloads/downloads.dtd">
+%downloadsDTD;
+]>
+
 <overlay id="downloadsViewOverlay"
          xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <script type="application/javascript"><![CDATA[
     const DOWNLOADS_QUERY = "place:transition=" +
       Components.interfaces.nsINavHistoryService.TRANSITION_DOWNLOAD +
       "&sort=" +
       Components.interfaces.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING;
 
     ContentArea.setContentViewForQueryString(DOWNLOADS_QUERY,
       function() new DownloadsPlacesView(document.getElementById("downloadsRichListBox")),
-      { showDetailsPane: false });
+      { showDetailsPane: false,
+        toolbarSet: "back-button, forward-button, organizeButton, clearDownloadsButton, libraryToolbarSpacer, searchFilter" });
   ]]></script>
 
   <window id="places">
     <commandset id="downloadCommands"/>
     <menupopup id="downloadsContextMenu"/>
   </window>
 
   <deck id="placesViewsDeck">
     <richlistbox id="downloadsRichListBox"/>
   </deck>
+
+  <toolbar id="placesToolbar">
+    <toolbarbutton id="clearDownloadsButton"
+                   insertbefore="libraryToolbarSpacer"
+                   label="&clearDownloadsButton.label;"
+                   command="downloadsCmd_clearDownloads"
+                   tooltiptext="&clearDownloadsButton.tooltip;"/>
+  </toolbar>
+
 </overlay>
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -1247,16 +1247,17 @@ let gPrivateBrowsingListener = {
 };
 #endif
 
 let ContentArea = {
   _specialViews: new Map(),
 
   init: function CA_init() {
     this._deck = document.getElementById("placesViewsDeck");
+    this._toolbar = document.getElementById("placesToolbar");
     ContentTree.init();
   },
 
   /**
    * Gets the content view to be used for loading the given query.
    * If a custom view was set by setContentViewForQueryString, that
    * view would be returned, else the default tree view is returned
    *
@@ -1310,19 +1311,35 @@ let ContentArea = {
       this._deck.selectedPanel = aView.associatedElement;
     return aView;
   },
 
   get currentPlace() this.currentView.place,
   set currentPlace(aQueryString) {
     this.currentView = this.getContentViewForQueryString(aQueryString);
     this.currentView.place = aQueryString;
+    this._updateToolbarSet();
     return aQueryString;
   },
 
+  _updateToolbarSet: function CA__updateToolbarSet() {
+    let toolbarSet = this.currentViewOptions.toolbarSet;
+    for (let elt of this._toolbar.childNodes) {
+      // On Windows and Linux the menu buttons are menus wrapped in a menubar.
+      if (elt.id == "placesMenu") {
+        for (let menuElt of elt.childNodes) {
+          menuElt.hidden = toolbarSet.indexOf(menuElt.id) == -1;
+        }
+      }
+      else {
+        elt.hidden = toolbarSet.indexOf(elt.id) == -1;
+      }
+    }
+  },
+
   /**
    * Options for the current view.
    *
    * @see ContentTree.viewOptions for supported options and default values.
    */
   get currentViewOptions() {
     // Use ContentTree options as default.
     let viewOptions = ContentTree.viewOptions;
@@ -1342,17 +1359,20 @@ let ContentArea = {
 
 let ContentTree = {
   init: function CT_init() {
     this._view = document.getElementById("placeContent");
   },
 
   get view() this._view,
 
-  get viewOptions() Object.seal({ showDetailsPane: true }),
+  get viewOptions() Object.seal({
+    showDetailsPane: true,
+    toolbarSet: "back-button, forward-button, organizeButton, viewMenu, maintenanceButton, libraryToolbarSpacer, searchFilter"
+  }),
 
   openSelectedNode: function CT_openSelectedNode(aEvent) {
     let view = this.view;
     PlacesUIUtils.openNodeWithEvent(view.selectedNode, aEvent, view);
   },
 
   onClick: function CT_onClick(aEvent) {
     // Only handle clicks on tree children.
--- a/browser/components/places/content/places.xul
+++ b/browser/components/places/content/places.xul
@@ -321,17 +321,17 @@
           </menupopup>
 #ifdef XP_MACOSX
         </toolbarbutton>
 #else
         </menu>
       </menubar>
 #endif
 
-      <spacer flex="1"/>
+      <spacer id="libraryToolbarSpacer" flex="1"/>
 
       <textbox id="searchFilter"
                clickSelectsAll="true"
                type="search"
                aria-controls="placeContent"
                oncommand="PlacesSearchBox.search(this.value);"
                collection="bookmarks">
       </textbox>
--- a/browser/components/places/src/PlacesUIUtils.jsm
+++ b/browser/components/places/src/PlacesUIUtils.jsm
@@ -1148,20 +1148,20 @@ XPCOMUtils.defineLazyGetter(PlacesUIUtil
                       expires: Ci.nsIAnnotationService.EXPIRE_NEVER };
       return new PlacesSetItemAnnotationTransaction(aItemId, annoObj);
     },
 
     ////////////////////////////////////////////////////////////////////////////
     //// nsITransactionManager forwarders.
 
     beginBatch: function()
-      PlacesUtils.transactionManager.beginBatch(),
+      PlacesUtils.transactionManager.beginBatch(null),
 
     endBatch: function()
-      PlacesUtils.transactionManager.endBatch(),
+      PlacesUtils.transactionManager.endBatch(false),
 
     doTransaction: function(txn)
       PlacesUtils.transactionManager.doTransaction(txn),
 
     undoTransaction: function()
       PlacesUtils.transactionManager.undoTransaction(),
 
     redoTransaction: function()
new file mode 100644
--- /dev/null
+++ b/browser/devtools/commandline/BuiltinCommands.jsm
@@ -0,0 +1,1994 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+
+this.EXPORTED_SYMBOLS = [ "CmdAddonFlags" ];
+
+Cu.import("resource:///modules/devtools/gcli.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
+                                  "resource:///modules/devtools/gDevTools.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
+                                  "resource:///modules/devtools/Target.jsm");
+
+/* CmdAddon ---------------------------------------------------------------- */
+
+(function(module) {
+  XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
+                                    "resource://gre/modules/AddonManager.jsm");
+
+  // We need to use an object in which to store any flags because a primitive
+  // would remain undefined.
+  module.CmdAddonFlags = {
+    addonsLoaded: false
+  };
+
+  /**
+  * 'addon' command.
+  */
+  gcli.addCommand({
+    name: "addon",
+    description: gcli.lookup("addonDesc")
+  });
+
+  /**
+  * 'addon list' command.
+  */
+  gcli.addCommand({
+    name: "addon list",
+    description: gcli.lookup("addonListDesc"),
+    params: [{
+      name: 'type',
+      type: {
+        name: 'selection',
+        data: ["dictionary", "extension", "locale", "plugin", "theme", "all"]
+      },
+      defaultValue: 'all',
+      description: gcli.lookup("addonListTypeDesc"),
+    }],
+    exec: function(aArgs, context) {
+      function representEnabledAddon(aAddon) {
+        return "<li><![CDATA[" + aAddon.name + "\u2002" + aAddon.version +
+        getAddonStatus(aAddon) + "]]></li>";
+      }
+
+      function representDisabledAddon(aAddon) {
+        return "<li class=\"gcli-addon-disabled\">" +
+          "<![CDATA[" + aAddon.name + "\u2002" + aAddon.version + aAddon.version +
+          "]]></li>";
+      }
+
+      function getAddonStatus(aAddon) {
+        let operations = [];
+
+        if (aAddon.pendingOperations & AddonManager.PENDING_ENABLE) {
+          operations.push("PENDING_ENABLE");
+        }
+
+        if (aAddon.pendingOperations & AddonManager.PENDING_DISABLE) {
+          operations.push("PENDING_DISABLE");
+        }
+
+        if (aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL) {
+          operations.push("PENDING_UNINSTALL");
+        }
+
+        if (aAddon.pendingOperations & AddonManager.PENDING_INSTALL) {
+          operations.push("PENDING_INSTALL");
+        }
+
+        if (aAddon.pendingOperations & AddonManager.PENDING_UPGRADE) {
+          operations.push("PENDING_UPGRADE");
+        }
+
+        if (operations.length) {
+          return " (" + operations.join(", ") + ")";
+        }
+        return "";
+      }
+
+      /**
+      * Compares two addons by their name. Used in sorting.
+      */
+      function compareAddonNames(aNameA, aNameB) {
+        return String.localeCompare(aNameA.name, aNameB.name);
+      }
+
+      /**
+      * Resolves the promise which is the scope (this) of this function, filling
+      * it with an HTML representation of the passed add-ons.
+      */
+      function list(aType, aAddons) {
+        if (!aAddons.length) {
+          this.resolve(gcli.lookup("addonNoneOfType"));
+        }
+
+        // Separate the enabled add-ons from the disabled ones.
+        let enabledAddons = [];
+        let disabledAddons = [];
+
+        aAddons.forEach(function(aAddon) {
+          if (aAddon.isActive) {
+            enabledAddons.push(aAddon);
+          } else {
+            disabledAddons.push(aAddon);
+          }
+        });
+
+        let header;
+        switch(aType) {
+          case "dictionary":
+            header = gcli.lookup("addonListDictionaryHeading");
+            break;
+          case "extension":
+            header = gcli.lookup("addonListExtensionHeading");
+            break;
+          case "locale":
+            header = gcli.lookup("addonListLocaleHeading");
+            break;
+          case "plugin":
+            header = gcli.lookup("addonListPluginHeading");
+            break;
+          case "theme":
+            header = gcli.lookup("addonListThemeHeading");
+          case "all":
+            header = gcli.lookup("addonListAllHeading");
+            break;
+          default:
+            header = gcli.lookup("addonListUnknownHeading");
+        }
+
+        // Map and sort the add-ons, and create an HTML list.
+        let message = header +
+                      "<ol>" +
+                      enabledAddons.sort(compareAddonNames).map(representEnabledAddon).join("") +
+                      disabledAddons.sort(compareAddonNames).map(representDisabledAddon).join("") +
+                      "</ol>";
+
+        this.resolve(context.createView({ html: message }));
+      }
+
+      // Create the promise that will be resolved when the add-on listing has
+      // been finished.
+      let promise = context.createPromise();
+      let types = aArgs.type == "all" ? null : [aArgs.type];
+      AddonManager.getAddonsByTypes(types, list.bind(promise, aArgs.type));
+      return promise;
+    }
+  });
+
+  // We need a list of addon names for the enable and disable commands. Because
+  // getting the name list is async we do not add the commands until we have the
+  // list.
+  AddonManager.getAllAddons(function addonAsync(aAddons) {
+    // We listen for installs to keep our addon list up to date. There is no need
+    // to listen for uninstalls because uninstalled addons are simply disabled
+    // until restart (to enable undo functionality).
+    AddonManager.addAddonListener({
+      onInstalled: function(aAddon) {
+        addonNameCache.push({
+          name: representAddon(aAddon).replace(/\s/g, "_"),
+          value: aAddon.name
+        });
+      },
+      onUninstalled: function(aAddon) {
+        let name = representAddon(aAddon).replace(/\s/g, "_");
+
+        for (let i = 0; i < addonNameCache.length; i++) {
+          if(addonNameCache[i].name == name) {
+            addonNameCache.splice(i, 1);
+            break;
+          }
+        }
+      },
+    });
+
+    /**
+    * Returns a string that represents the passed add-on.
+    */
+    function representAddon(aAddon) {
+      let name = aAddon.name + " " + aAddon.version;
+      return name.trim();
+    }
+
+    let addonNameCache = [];
+
+    // The name parameter, used in "addon enable" and "addon disable."
+    let nameParameter = {
+      name: "name",
+      type: {
+        name: "selection",
+        lookup: addonNameCache
+      },
+      description: gcli.lookup("addonNameDesc")
+    };
+
+    for (let addon of aAddons) {
+      addonNameCache.push({
+        name: representAddon(addon).replace(/\s/g, "_"),
+        value: addon.name
+      });
+    }
+
+    /**
+    * 'addon enable' command.
+    */
+    gcli.addCommand({
+      name: "addon enable",
+      description: gcli.lookup("addonEnableDesc"),
+      params: [nameParameter],
+      exec: function(aArgs, context) {
+        /**
+        * Enables the addon in the passed list which has a name that matches
+        * according to the passed name comparer, and resolves the promise which
+        * is the scope (this) of this function to display the result of this
+        * enable attempt.
+        */
+        function enable(aName, addons) {
+          // Find the add-on.
+          let addon = null;
+          addons.some(function(candidate) {
+            if (candidate.name == aName) {
+              addon = candidate;
+              return true;
+            } else {
+              return false;
+            }
+          });
+
+          let name = representAddon(addon);
+          let message = "";
+
+          if (!addon.userDisabled) {
+            message = gcli.lookupFormat("addonAlreadyEnabled", [name]);
+          } else {
+            addon.userDisabled = false;
+            message = gcli.lookupFormat("addonEnabled", [name]);
+          }
+          this.resolve(message);
+        }
+
+        let promise = context.createPromise();
+        // List the installed add-ons, enable one when done listing.
+        AddonManager.getAllAddons(enable.bind(promise, aArgs.name));
+        return promise;
+      }
+    });
+
+    /**
+    * 'addon disable' command.
+    */
+    gcli.addCommand({
+      name: "addon disable",
+      description: gcli.lookup("addonDisableDesc"),
+      params: [nameParameter],
+      exec: function(aArgs, context) {
+        /**
+        * Like enable, but ... you know ... the exact opposite.
+        */
+        function disable(aName, addons) {
+          // Find the add-on.
+          let addon = null;
+          addons.some(function(candidate) {
+            if (candidate.name == aName) {
+              addon = candidate;
+              return true;
+            } else {
+              return false;
+            }
+          });
+
+          let name = representAddon(addon);
+          let message = "";
+
+          if (addon.userDisabled) {
+            message = gcli.lookupFormat("addonAlreadyDisabled", [name]);
+          } else {
+            addon.userDisabled = true;
+            message = gcli.lookupFormat("addonDisabled", [name]);
+          }
+          this.resolve(message);
+        }
+
+        let promise = context.createPromise();
+        // List the installed add-ons, disable one when done listing.
+        AddonManager.getAllAddons(disable.bind(promise, aArgs.name));
+        return promise;
+      }
+    });
+    module.CmdAddonFlags.addonsLoaded = true;
+    Services.obs.notifyObservers(null, "gcli_addon_commands_ready", null);
+  });
+}(this));
+
+/* CmdBreak ---------------------------------------------------------------- */
+(function(module) {
+  XPCOMUtils.defineLazyModuleGetter(this, "HUDService",
+                                    "resource:///modules/HUDService.jsm");
+
+  XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
+                                    "resource:///modules/devtools/Target.jsm");
+
+  /**
+  * 'break' command
+  */
+  gcli.addCommand({
+    name: "break",
+    description: gcli.lookup("breakDesc"),
+    manual: gcli.lookup("breakManual")
+  });
+
+  /**
+  * 'break list' command
+  */
+  gcli.addCommand({
+    name: "break list",
+    description: gcli.lookup("breaklistDesc"),
+    returnType: "html",
+    exec: function(args, context) {
+      let dbg = getPanel(context, "jsdebugger");
+      if (!dbg) {
+        return gcli.lookup("debuggerStopped");
+      }
+
+      let breakpoints = dbg.getAllBreakpoints();
+
+      if (Object.keys(breakpoints).length === 0) {
+        return gcli.lookup("breaklistNone");
+      }
+
+      let reply = gcli.lookup("breaklistIntro");
+      reply += "<ol>";
+      for each (let breakpoint in breakpoints) {
+        let text = gcli.lookupFormat("breaklistLineEntry",
+                                    [breakpoint.location.url,
+                                      breakpoint.location.line]);
+        reply += "<li>" + text + "</li>";
+      };
+      reply += "</ol>";
+      return reply;
+    }
+  });
+
+  /**
+  * 'break add' command
+  */
+  gcli.addCommand({
+    name: "break add",
+    description: gcli.lookup("breakaddDesc"),
+    manual: gcli.lookup("breakaddManual")
+  });
+
+  /**
+  * 'break add line' command
+  */
+  gcli.addCommand({
+    name: "break add line",
+    description: gcli.lookup("breakaddlineDesc"),
+    params: [
+      {
+        name: "file",
+        type: {
+          name: "selection",
+          data: function(args, context) {
+            let files = [];
+            let dbg = getPanel(context, "jsdebugger");
+            if (dbg) {
+              let sourcesView = dbg.panelWin.DebuggerView.Sources;
+              for (let item in sourcesView) {
+                files.push(item.value);
+              }
+            }
+            return files;
+          }
+        },
+        description: gcli.lookup("breakaddlineFileDesc")
+      },
+      {
+        name: "line",
+        type: { name: "number", min: 1, step: 10 },
+        description: gcli.lookup("breakaddlineLineDesc")
+      }
+    ],
+    returnType: "html",
+    exec: function(args, context) {
+      args.type = "line";
+
+      let dbg = getPanel(context, "jsdebugger");
+      if (!dbg) {
+        return gcli.lookup("debuggerStopped");
+      }
+      var deferred = context.defer();
+      let position = { url: args.file, line: args.line };
+      dbg.addBreakpoint(position, function(aBreakpoint, aError) {
+        if (aError) {
+          deferred.resolve(gcli.lookupFormat("breakaddFailed", [aError]));
+          return;
+        }
+        deferred.resolve(gcli.lookup("breakaddAdded"));
+      });
+      return deferred.promise;
+    }
+  });
+
+
+  /**
+  * 'break del' command
+  */
+  gcli.addCommand({
+    name: "break del",
+    description: gcli.lookup("breakdelDesc"),
+    params: [
+      {
+        name: "breakid",
+        type: {
+          name: "number",
+          min: 0,
+          max: function(args, context) {
+            let dbg = getPanel(context, "jsdebugger");
+            return dbg == null ?
+                null :
+                Object.keys(dbg.getAllBreakpoints()).length - 1;
+          },
+        },
+        description: gcli.lookup("breakdelBreakidDesc")
+      }
+    ],
+    returnType: "html",
+    exec: function(args, context) {
+      let dbg = getPanel(context, "jsdebugger");
+      if (!dbg) {
+        return gcli.lookup("debuggerStopped");
+      }
+
+      let breakpoints = dbg.getAllBreakpoints();
+      let id = Object.keys(breakpoints)[args.breakid];
+      if (!id || !(id in breakpoints)) {
+        return gcli.lookup("breakNotFound");
+      }
+
+      let deferred = context.defer();
+      try {
+        dbg.removeBreakpoint(breakpoints[id], function() {
+          deferred.resolve(gcli.lookup("breakdelRemoved"));
+        });
+      } catch (ex) {
+        // If the debugger has been closed already, don't scare the user.
+        deferred.resolve(gcli.lookup("breakdelRemoved"));
+      }
+      return deferred.promise;
+    }
+  });
+
+  /**
+  * A helper to go from a command context to a debugger panel
+  */
+  function getPanel(context, id) {
+    if (context == null) {
+      return undefined;
+    }
+
+    let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    let toolbox = gDevTools.getToolbox(target);
+    return toolbox == null ? undefined : toolbox.getPanel(id);
+  }
+}(this));
+
+/* CmdCalllog -------------------------------------------------------------- */
+
+(function(module) {
+  XPCOMUtils.defineLazyGetter(this, "Debugger", function() {
+    let JsDebugger = {};
+    Components.utils.import("resource://gre/modules/jsdebugger.jsm", JsDebugger);
+
+    let global = Components.utils.getGlobalForObject({});
+    JsDebugger.addDebuggerToGlobal(global);
+
+    return global.Debugger;
+  });
+
+  XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
+                                    "resource:///modules/devtools/Target.jsm");
+
+  let debuggers = [];
+
+  /**
+  * 'calllog' command
+  */
+  gcli.addCommand({
+    name: "calllog",
+    description: gcli.lookup("calllogDesc")
+  })
+
+  /**
+  * 'calllog start' command
+  */
+  gcli.addCommand({
+    name: "calllog start",
+    description: gcli.lookup("calllogStartDesc"),
+
+    exec: function(args, context) {
+      let contentWindow = context.environment.contentDocument.defaultView;
+
+      let dbg = new Debugger(contentWindow);
+      dbg.onEnterFrame = function(frame) {
+        // BUG 773652 -  Make the output from the GCLI calllog command nicer
+        contentWindow.console.log("Method call: " + this.callDescription(frame));
+      }.bind(this);
+
+      debuggers.push(dbg);
+
+      let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
+      let target = TargetFactory.forTab(gBrowser.selectedTab);
+      gDevTools.showToolbox(target, "webconsole");
+
+      return gcli.lookup("calllogStartReply");
+    },
+
+    callDescription: function(frame) {
+      let name = "<anonymous>";
+      if (frame.callee.name) {
+        name = frame.callee.name;
+      }
+      else {
+        let desc = frame.callee.getOwnPropertyDescriptor("displayName");
+        if (desc && desc.value && typeof desc.value == "string") {
+          name = desc.value;
+        }
+      }
+
+      let args = frame.arguments.map(this.valueToString).join(", ");
+      return name + "(" + args + ")";
+    },
+
+    valueToString: function(value) {
+      if (typeof value !== "object" || value === null) {
+        return uneval(value);
+      }
+      return "[object " + value.class + "]";
+    }
+  });
+
+  /**
+  * 'calllog stop' command
+  */
+  gcli.addCommand({
+    name: "calllog stop",
+    description: gcli.lookup("calllogStopDesc"),
+
+    exec: function(args, context) {
+      let numDebuggers = debuggers.length;
+      if (numDebuggers == 0) {
+        return gcli.lookup("calllogStopNoLogging");
+      }
+
+      for (let dbg of debuggers) {
+        dbg.onEnterFrame = undefined;
+      }
+      debuggers = [];
+
+      return gcli.lookupFormat("calllogStopReply", [ numDebuggers ]);
+    }
+  });
+}(this));
+
+/* CmdCalllogChrome -------------------------------------------------------- */
+
+(function(module) {
+  XPCOMUtils.defineLazyGetter(this, "Debugger", function() {
+    let JsDebugger = {};
+    Cu.import("resource://gre/modules/jsdebugger.jsm", JsDebugger);
+
+    let global = Components.utils.getGlobalForObject({});
+    JsDebugger.addDebuggerToGlobal(global);
+
+    return global.Debugger;
+  });
+
+  let debuggers = [];
+  let sandboxes = [];
+
+  /**
+  * 'calllog chromestart' command
+  */
+  gcli.addCommand({
+    name: "calllog chromestart",
+    description: gcli.lookup("calllogChromeStartDesc"),
+    get hidden() gcli.hiddenByChromePref(),
+    params: [
+      {
+        name: "sourceType",
+        type: {
+          name: "selection",
+          data: ["content-variable", "chrome-variable", "jsm", "javascript"]
+        }
+      },
+      {
+        name: "source",
+        type: "string",
+        description: gcli.lookup("calllogChromeSourceTypeDesc"),
+        manual: gcli.lookup("calllogChromeSourceTypeManual"),
+      }
+    ],
+    exec: function(args, context) {
+      let globalObj;
+      let contentWindow = context.environment.contentDocument.defaultView;
+
+      if (args.sourceType == "jsm") {
+        try {
+          globalObj = Cu.import(args.source);
+        }
+        catch (e) {
+          return gcli.lookup("callLogChromeInvalidJSM");
+        }
+      } else if (args.sourceType == "content-variable") {
+        if (args.source in contentWindow) {
+          globalObj = Cu.getGlobalForObject(contentWindow[args.source]);
+        } else {
+          throw new Error(gcli.lookup("callLogChromeVarNotFoundContent"));
+        }
+      } else if (args.sourceType == "chrome-variable") {
+        let chromeWin = context.environment.chromeDocument.defaultView;
+        if (args.source in chromeWin) {
+          globalObj = Cu.getGlobalForObject(chromeWin[args.source]);
+        } else {
+          return gcli.lookup("callLogChromeVarNotFoundChrome");
+        }
+      } else {
+        let chromeWin = context.environment.chromeDocument.defaultView;
+        let sandbox = new Cu.Sandbox(chromeWin,
+                                    {
+                                      sandboxPrototype: chromeWin,
+                                      wantXrays: false,
+                                      sandboxName: "gcli-cmd-calllog-chrome"
+                                    });
+        let returnVal;
+        try {
+          returnVal = Cu.evalInSandbox(args.source, sandbox, "ECMAv5");
+          sandboxes.push(sandbox);
+        } catch(e) {
+          // We need to save the message before cleaning up else e contains a dead
+          // object.
+          let msg = gcli.lookup("callLogChromeEvalException") + ": " + e;
+          Cu.nukeSandbox(sandbox);
+          return msg;
+        }
+
+        if (typeof returnVal == "undefined") {
+          return gcli.lookup("callLogChromeEvalNeedsObject");
+        }
+
+        globalObj = Cu.getGlobalForObject(returnVal);
+      }
+
+      let dbg = new Debugger(globalObj);
+      debuggers.push(dbg);
+
+      dbg.onEnterFrame = function(frame) {
+        // BUG 773652 -  Make the output from the GCLI calllog command nicer
+        contentWindow.console.log(gcli.lookup("callLogChromeMethodCall") +
+                                  ": " + this.callDescription(frame));
+      }.bind(this);
+
+      let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
+      let target = TargetFactory.forTab(gBrowser.selectedTab);
+      gDevTools.showToolbox(target, "webconsole");
+
+      return gcli.lookup("calllogChromeStartReply");
+    },
+
+    valueToString: function(value) {
+      if (typeof value !== "object" || value === null)
+        return uneval(value);
+      return "[object " + value.class + "]";
+    },
+
+    callDescription: function(frame) {
+      let name = frame.callee.name || gcli.lookup("callLogChromeAnonFunction");
+      let args = frame.arguments.map(this.valueToString).join(", ");
+      return name + "(" + args + ")";
+    }
+  });
+
+  /**
+  * 'calllog chromestop' command
+  */
+  gcli.addCommand({
+    name: "calllog chromestop",
+    description: gcli.lookup("calllogChromeStopDesc"),
+    get hidden() gcli.hiddenByChromePref(),
+    exec: function(args, context) {
+      let numDebuggers = debuggers.length;
+      if (numDebuggers == 0) {
+        return gcli.lookup("calllogChromeStopNoLogging");
+      }
+
+      for (let dbg of debuggers) {
+        dbg.onEnterFrame = undefined;
+        dbg.enabled = false;
+      }
+      for (let sandbox of sandboxes) {
+        Cu.nukeSandbox(sandbox);
+      }
+      debuggers = [];
+      sandboxes = [];
+
+      return gcli.lookupFormat("calllogChromeStopReply", [ numDebuggers ]);
+    }
+  });
+}(this));
+
+/* CmdCmd ------------------------------------------------------------------ */
+
+(function(module) {
+  let prefSvc = "@mozilla.org/preferences-service;1";
+  XPCOMUtils.defineLazyGetter(this, "prefBranch", function() {
+    let prefService = Cc[prefSvc].getService(Ci.nsIPrefService);
+    return prefService.getBranch(null).QueryInterface(Ci.nsIPrefBranch2);
+  });
+
+  XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
+                                    "resource://gre/modules/NetUtil.jsm");
+  XPCOMUtils.defineLazyModuleGetter(this, "console",
+                                    "resource://gre/modules/devtools/Console.jsm");
+
+  const PREF_DIR = "devtools.commands.dir";
+
+  /**
+  * A place to store the names of the commands that we have added as a result of
+  * calling refreshAutoCommands(). Used by refreshAutoCommands to remove the
+  * added commands.
+  */
+  let commands = [];
+
+  /**
+  * Exported API
+  */
+  this.CmdCommands = {
+    /**
+    * Called to look in a directory pointed at by the devtools.commands.dir pref
+    * for *.mozcmd files which are then loaded.
+    * @param nsIPrincipal aSandboxPrincipal Scope object for the Sandbox in which
+    * we eval the script from the .mozcmd file. This should be a chrome window.
+    */
+    refreshAutoCommands: function GC_refreshAutoCommands(aSandboxPrincipal) {
+      // First get rid of the last set of commands
+      commands.forEach(function(name) {
+        gcli.removeCommand(name);
+      });
+
+      let dirName = prefBranch.getComplexValue(PREF_DIR,
+                                              Ci.nsISupportsString).data.trim();
+      if (dirName == "") {
+        return;
+      }
+
+      let dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
+      dir.initWithPath(dirName);
+      if (!dir.exists() || !dir.isDirectory()) {
+        throw new Error('\'' + dirName + '\' is not a directory.');
+      }
+
+      let en = dir.directoryEntries.QueryInterface(Ci.nsIDirectoryEnumerator);
+
+      while (true) {
+        let file = en.nextFile;
+        if (!file) {
+          break;
+        }
+        if (file.leafName.match(/.*\.mozcmd$/) && file.isFile() && file.isReadable()) {
+          loadCommandFile(file, aSandboxPrincipal);
+        }
+      }
+    },
+  };
+
+  /**
+  * Load the commands from a single file
+  * @param nsIFile aFile The file containing the commands that we should read
+  * @param nsIPrincipal aSandboxPrincipal Scope object for the Sandbox in which
+  * we eval the script from the .mozcmd file. This should be a chrome window.
+  */
+  function loadCommandFile(aFile, aSandboxPrincipal) {
+    NetUtil.asyncFetch(aFile, function refresh_fetch(aStream, aStatus) {
+      if (!Components.isSuccessCode(aStatus)) {
+        console.error("NetUtil.asyncFetch(" + aFile.path + ",..) failed. Status=" + aStatus);
+        return;
+      }
+
+      let source = NetUtil.readInputStreamToString(aStream, aStream.available());
+      aStream.close();
+
+      let sandbox = new Cu.Sandbox(aSandboxPrincipal, {
+        sandboxPrototype: aSandboxPrincipal,
+        wantXrays: false,
+        sandboxName: aFile.path
+      });
+      let data = Cu.evalInSandbox(source, sandbox, "1.8", aFile.leafName, 1);
+
+      if (!Array.isArray(data)) {
+        console.error("Command file '" + aFile.leafName + "' does not have top level array.");
+        return;
+      }
+
+      data.forEach(function(commandSpec) {
+        gcli.addCommand(commandSpec);
+        commands.push(commandSpec.name);
+      });
+    }.bind(this));
+  }
+
+  /**
+  * 'cmd' command
+  */
+  gcli.addCommand({
+    name: "cmd",
+    get hidden() { return !prefBranch.prefHasUserValue(PREF_DIR); },
+    description: gcli.lookup("cmdDesc")
+  });
+
+  /**
+  * 'cmd refresh' command
+  */
+  gcli.addCommand({
+    name: "cmd refresh",
+    description: gcli.lookup("cmdRefreshDesc"),
+    get hidden() { return !prefBranch.prefHasUserValue(PREF_DIR); },
+    exec: function Command_cmdRefresh(args, context) {
+      let chromeWindow = context.environment.chromeDocument.defaultView;
+      CmdCommands.refreshAutoCommands(chromeWindow);
+    }
+  });
+}(this));
+
+/* CmdConsole -------------------------------------------------------------- */
+
+(function(module) {
+  XPCOMUtils.defineLazyModuleGetter(this, "HUDService",
+                                    "resource:///modules/HUDService.jsm");
+
+  /**
+  * 'console' command
+  */
+  gcli.addCommand({
+    name: "console",
+    description: gcli.lookup("consoleDesc"),
+    manual: gcli.lookup("consoleManual")
+  });
+
+  /**
+  * 'console clear' command
+  */
+  gcli.addCommand({
+    name: "console clear",
+    description: gcli.lookup("consoleclearDesc"),
+    exec: function Command_consoleClear(args, context) {
+      let window = context.environment.contentDocument.defaultView;
+      let hud = HUDService.getHudByWindow(window);
+      // hud will be null if the web console has not been opened for this window
+      if (hud) {
+        hud.jsterm.clearOutput();
+      }
+    }
+  });
+
+  /**
+  * 'console close' command
+  */
+  gcli.addCommand({
+    name: "console close",
+    description: gcli.lookup("consolecloseDesc"),
+    exec: function Command_consoleClose(args, context) {
+      let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
+      let target = TargetFactory.forTab(gBrowser.selectedTab);
+      return gDevTools.closeToolbox(target);
+    }
+  });
+
+  /**
+  * 'console open' command
+  */
+  gcli.addCommand({
+    name: "console open",
+    description: gcli.lookup("consoleopenDesc"),
+    exec: function Command_consoleOpen(args, context) {
+      let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
+      let target = TargetFactory.forTab(gBrowser.selectedTab);
+      return gDevTools.showToolbox(target, "webconsole");
+    }
+  });
+}(this));
+
+/* CmdCookie --------------------------------------------------------------- */
+
+(function(module) {
+  XPCOMUtils.defineLazyModuleGetter(this, "console",
+                                    "resource://gre/modules/devtools/Console.jsm");
+
+  // We should really be using nsICookieManager so we can read more than just the
+  // key/value of cookies. The difficulty is filtering the cookies that are
+  // relevant to the current page. See
+  // https://github.com/firebug/firebug/blob/master/extension/content/firebug/cookies/cookieObserver.js#L123
+  // For details on how this is done with Firebug
+
+  /**
+  * 'cookie' command
+  */
+  gcli.addCommand({
+    name: "cookie",
+    description: gcli.lookup("cookieDesc"),
+    manual: gcli.lookup("cookieManual")
+  });
+
+  /**
+  * The template for the 'cookie list' command.
+  */
+  var cookieListHtml = "" +
+    "<table>" +
+    "  <tr>" +
+    "    <th>" + gcli.lookup("cookieListOutKey") + "</th>" +
+    "    <th>" + gcli.lookup("cookieListOutValue") + "</th>" +
+    "    <th>" + gcli.lookup("cookieListOutActions") + "</th>" +
+    "  </tr>" +
+    "  <tr foreach='cookie in ${cookies}'>" +
+    "    <td>${cookie.key}</td>" +
+    "    <td>${cookie.value}</td>" +
+    "    <td>" +
+    "      <span class='gcli-out-shortcut' onclick='${onclick}'" +
+    "          data-command='cookie set ${cookie.key} '" +
+    "          >" + gcli.lookup("cookieListOutEdit") + "</span>" +
+    "      <span class='gcli-out-shortcut'" +
+    "          onclick='${onclick}' ondblclick='${ondblclick}'" +
+    "          data-command='cookie remove ${cookie.key}'" +
+    "          >" + gcli.lookup("cookieListOutRemove") + "</span>" +
+    "    </td>" +
+    "  </tr>" +
+    "</table>" +
+    "";
+
+  /**
+  * 'cookie list' command
+  */
+  gcli.addCommand({
+    name: "cookie list",
+    description: gcli.lookup("cookieListDesc"),
+    manual: gcli.lookup("cookieListManual"),
+    returnType: "string",
+    exec: function Command_cookieList(args, context) {
+      // Parse out an array of { key:..., value:... } objects for each cookie
+      var doc = context.environment.contentDocument;
+      var cookies = doc.cookie.split("; ").map(function(cookieStr) {
+        var equalsPos = cookieStr.indexOf("=");
+        return {
+          key: cookieStr.substring(0, equalsPos),
+          value: cookieStr.substring(equalsPos + 1)
+        };
+      });
+
+      return context.createView({
+        html: cookieListHtml,
+        data: {
+          cookies: cookies,
+          onclick: createUpdateHandler(context),
+          ondblclick: createExecuteHandler(context),
+        }
+      });
+    }
+  });
+
+  /**
+  * 'cookie remove' command
+  */
+  gcli.addCommand({
+    name: "cookie remove",
+    description: gcli.lookup("cookieRemoveDesc"),
+    manual: gcli.lookup("cookieRemoveManual"),
+    params: [
+      {
+        name: "key",
+        type: "string",
+        description: gcli.lookup("cookieRemoveKeyDesc"),
+      }
+    ],
+    exec: function Command_cookieRemove(args, context) {
+      let document = context.environment.contentDocument;
+      let expDate = new Date();
+      expDate.setDate(expDate.getDate() - 1);
+      document.cookie = escape(args.key) + "=; expires=" + expDate.toGMTString();
+    }
+  });
+
+  /**
+  * 'cookie set' command
+  */
+  gcli.addCommand({
+    name: "cookie set",
+    description: gcli.lookup("cookieSetDesc"),
+    manual: gcli.lookup("cookieSetManual"),
+    params: [
+      {
+        name: "key",
+        type: "string",
+        description: gcli.lookup("cookieSetKeyDesc")
+      },
+      {
+        name: "value",
+        type: "string",
+        description: gcli.lookup("cookieSetValueDesc")
+      },
+      {
+        group: gcli.lookup("cookieSetOptionsDesc"),
+        params: [
+          {
+            name: "path",
+            type: "string",
+            defaultValue: "/",
+            description: gcli.lookup("cookieSetPathDesc")
+          },
+          {
+            name: "domain",
+            type: "string",
+            defaultValue: null,
+            description: gcli.lookup("cookieSetDomainDesc")
+          },
+          {
+            name: "secure",
+            type: "boolean",
+            description: gcli.lookup("cookieSetSecureDesc")
+          }
+        ]
+      }
+    ],
+    exec: function Command_cookieSet(args, context) {
+      let document = context.environment.contentDocument;
+
+      document.cookie = escape(args.key) + "=" + escape(args.value) +
+              (args.domain ? "; domain=" + args.domain : "") +
+              (args.path ? "; path=" + args.path : "") +
+              (args.secure ? "; secure" : ""); 
+    }
+  });
+
+  /**
+  * Helper to find the 'data-command' attribute and call some action on it.
+  * @see |updateCommand()| and |executeCommand()|
+  */
+  function withCommand(element, action) {
+    var command = element.getAttribute("data-command");
+    if (!command) {
+      command = element.querySelector("*[data-command]")
+              .getAttribute("data-command");
+    }
+
+    if (command) {
+      action(command);
+    }
+    else {
+      console.warn("Missing data-command for " + util.findCssSelector(element));
+    }
+  }
+
+  /**
+  * Create a handler to update the requisition to contain the text held in the
+  * first matching data-command attribute under the currentTarget of the event.
+  * @param context Either a Requisition or an ExecutionContext or another object
+  * that contains an |update()| function that follows a similar contract.
+  */
+  function createUpdateHandler(context) {
+    return function(ev) {
+      withCommand(ev.currentTarget, function(command) {
+        context.update(command);
+      });
+    }
+  }
+
+  /**
+  * Create a handler to execute the text held in the data-command attribute
+  * under the currentTarget of the event.
+  * @param context Either a Requisition or an ExecutionContext or another object
+  * that contains an |update()| function that follows a similar contract.
+  */
+  function createExecuteHandler(context) {
+    return function(ev) {
+      withCommand(ev.currentTarget, function(command) {
+        context.exec({
+          visible: true,
+          typed: command
+        });
+      });
+    }
+  }
+}(this));
+
+/* CmdDbg ------------------------------------------------------------------ */
+
+(function(module) {
+  /**
+  * 'dbg' command
+  */
+  gcli.addCommand({
+    name: "dbg",
+    description: gcli.lookup("dbgDesc"),
+    manual: gcli.lookup("dbgManual")
+  });
+
+  /**
+  * 'dbg open' command
+  */
+  gcli.addCommand({
+    name: "dbg open",
+    description: gcli.lookup("dbgOpen"),
+    params: [],
+    exec: function (args, context) {
+      let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
+      let target = TargetFactory.forTab(gBrowser.selectedTab);
+      return gDevTools.showToolbox(target, "jsdebugger");
+    }
+  });
+
+  /**
+  * 'dbg close' command
+  */
+  gcli.addCommand({
+    name: "dbg close",
+    description: gcli.lookup("dbgClose"),
+    params: [],
+    exec: function (args, context) {
+      let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
+      let target = TargetFactory.forTab(gBrowser.selectedTab);
+      return gDevTools.closeToolbox(target);
+    }
+  });
+
+  /**
+  * 'dbg interrupt' command
+  */
+  gcli.addCommand({
+    name: "dbg interrupt",
+    description: gcli.lookup("dbgInterrupt"),
+    params: [],
+    exec: function(args, context) {
+      let dbg = getPanel(context, "jsdebugger");
+      if (!dbg) {
+        return gcli.lookup("debuggerStopped");
+      }
+
+      let controller = dbg._controller;
+      let thread = controller.activeThread;
+      if (!thread.paused) {
+        thread.interrupt();
+      }
+    }
+  });
+
+  /**
+  * 'dbg continue' command
+  */
+  gcli.addCommand({
+    name: "dbg continue",
+    description: gcli.lookup("dbgContinue"),
+    params: [],
+    exec: function(args, context) {
+      let dbg = getPanel(context, "jsdebugger");
+      if (!dbg) {
+        return gcli.lookup("debuggerStopped");
+      }
+
+      let controller = dbg._controller;
+      let thread = controller.activeThread;
+      if (thread.paused) {
+        thread.resume();
+      }
+    }
+  });
+
+  /**
+  * 'dbg step' command
+  */
+  gcli.addCommand({
+    name: "dbg step",
+    description: gcli.lookup("dbgStepDesc"),
+    manual: gcli.lookup("dbgStepManual")
+  });
+
+  /**
+  * 'dbg step over' command
+  */
+  gcli.addCommand({
+    name: "dbg step over",
+    description: gcli.lookup("dbgStepOverDesc"),
+    params: [],
+    exec: function(args, context) {
+      let dbg = getPanel(context, "jsdebugger");
+      if (!dbg) {
+        return gcli.lookup("debuggerStopped");
+      }
+
+      let controller = dbg._controller;
+      let thread = controller.activeThread;
+      if (thread.paused) {
+        thread.stepOver();
+      }
+    }
+  });
+
+  /**
+  * 'dbg step in' command
+  */
+  gcli.addCommand({
+    name: 'dbg step in',
+    description: gcli.lookup("dbgStepInDesc"),
+    params: [],
+    exec: function(args, context) {
+      let dbg = getPanel(context, "jsdebugger");
+      if (!dbg) {
+        return gcli.lookup("debuggerStopped");
+      }
+
+      let controller = dbg._controller;
+      let thread = controller.activeThread;
+      if (thread.paused) {
+        thread.stepIn();
+      }
+    }
+  });
+
+  /**
+  * 'dbg step over' command
+  */
+  gcli.addCommand({
+    name: 'dbg step out',
+    description: gcli.lookup("dbgStepOutDesc"),
+    params: [],
+    exec: function(args, context) {
+      let dbg = getPanel(context, "jsdebugger");
+      if (!dbg) {
+        return gcli.lookup("debuggerStopped");
+      }
+
+      let controller = dbg._controller;
+      let thread = controller.activeThread;
+      if (thread.paused) {
+        thread.stepOut();
+      }
+    }
+  });
+
+  /**
+  * A helper to go from a command context to a debugger panel
+  */
+  function getPanel(context, id) {
+    let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    let toolbox = gDevTools.getToolbox(target);
+    return toolbox == null ? undefined : toolbox.getPanel(id);
+  }
+}(this));
+
+/* CmdEcho ----------------------------------------------------------------- */
+
+(function(module) {
+  /**
+  * 'echo' command
+  */
+  gcli.addCommand({
+    name: "echo",
+    description: gcli.lookup("echoDesc"),
+    params: [
+      {
+        name: "message",
+        type: "string",
+        description: gcli.lookup("echoMessageDesc")
+      }
+    ],
+    returnType: "string",
+    hidden: true,
+    exec: function Command_echo(args, context) {
+      return args.message;
+    }
+  });
+}(this));
+
+/* CmdExport --------------------------------------------------------------- */
+
+(function(module) {
+  /**
+  * 'export' command
+  */
+  gcli.addCommand({
+    name: "export",
+    description: gcli.lookup("exportDesc"),
+  });
+
+  /**
+  * The 'export html' command. This command allows the user to export the page to
+  * HTML after they do DOM changes.
+  */
+  gcli.addCommand({
+    name: "export html",
+    description: gcli.lookup("exportHtmlDesc"),
+    exec: function(args, context) {
+      let document = context.environment.contentDocument;
+      let window = document.defaultView;
+      let page = document.documentElement.outerHTML;
+      window.open('data:text/plain;charset=utf8,' + encodeURIComponent(page));
+    }
+  });
+}(this));
+
+/* CmdJsb ------------------------------------------------------------------ */
+
+(function(module) {
+  const XMLHttpRequest =
+    Components.Constructor("@mozilla.org/xmlextras/xmlhttprequest;1");
+
+  XPCOMUtils.defineLazyModuleGetter(this, "js_beautify",
+                                    "resource:///modules/devtools/Jsbeautify.jsm");
+
+  /**
+  * jsb command.
+  */
+  gcli.addCommand({
+    name: 'jsb',
+    description: gcli.lookup('jsbDesc'),
+    returnValue:'string',
+    params: [
+      {
+        name: 'url',
+        type: 'string',
+        description: gcli.lookup('jsbUrlDesc')
+      },
+      {
+        group: gcli.lookup("jsbOptionsDesc"),
+        params: [
+          {
+            name: 'indentSize',
+            type: 'number',
+            description: gcli.lookup('jsbIndentSizeDesc'),
+            manual: gcli.lookup('jsbIndentSizeManual'),
+            defaultValue: 2
+          },
+          {
+            name: 'indentChar',
+            type: {
+              name: 'selection',
+              lookup: [
+                { name: "space", value: " " },
+                { name: "tab", value: "\t" }
+              ]
+            },
+            description: gcli.lookup('jsbIndentCharDesc'),
+            manual: gcli.lookup('jsbIndentCharManual'),
+            defaultValue: ' ',
+          },
+          {
+            name: 'doNotPreserveNewlines',
+            type: 'boolean',
+            description: gcli.lookup('jsbDoNotPreserveNewlinesDesc')
+          },
+          {
+            name: 'preserveMaxNewlines',
+            type: 'number',
+            description: gcli.lookup('jsbPreserveMaxNewlinesDesc'),
+            manual: gcli.lookup('jsbPreserveMaxNewlinesManual'),
+            defaultValue: -1
+          },
+          {
+            name: 'jslintHappy',
+            type: 'boolean',
+            description: gcli.lookup('jsbJslintHappyDesc'),
+            manual: gcli.lookup('jsbJslintHappyManual')
+          },
+          {
+            name: 'braceStyle',
+            type: {
+              name: 'selection',
+              data: ['collapse', 'expand', 'end-expand', 'expand-strict']
+            },
+            description: gcli.lookup('jsbBraceStyleDesc'),
+            manual: gcli.lookup('jsbBraceStyleManual'),
+            defaultValue: "collapse"
+          },
+          {
+            name: 'noSpaceBeforeConditional',
+            type: 'boolean',
+            description: gcli.lookup('jsbNoSpaceBeforeConditionalDesc')
+          },
+          {
+            name: 'unescapeStrings',
+            type: 'boolean',
+            description: gcli.lookup('jsbUnescapeStringsDesc'),
+            manual: gcli.lookup('jsbUnescapeStringsManual')
+          }
+        ]
+      }
+    ],
+    exec: function(args, context) {
+      let opts = {
+        indent_size: args.indentSize,
+        indent_char: args.indentChar,
+        preserve_newlines: !args.doNotPreserveNewlines,
+        max_preserve_newlines: args.preserveMaxNewlines == -1 ?
+                              undefined : args.preserveMaxNewlines,
+        jslint_happy: args.jslintHappy,
+        brace_style: args.braceStyle,
+        space_before_conditional: !args.noSpaceBeforeConditional,
+        unescape_strings: args.unescapeStrings
+      };
+
+      let xhr = new XMLHttpRequest();
+
+      try {
+        xhr.open("GET", args.url, true);
+      } catch(e) {
+        return gcli.lookup('jsbInvalidURL');
+      }
+
+      let promise = context.createPromise();
+
+      xhr.onreadystatechange = function(aEvt) {
+        if (xhr.readyState == 4) {
+          if (xhr.status == 200 || xhr.status == 0) {
+            let browserDoc = context.environment.chromeDocument;
+            let browserWindow = browserDoc.defaultView;
+            let gBrowser = browserWindow.gBrowser;
+            let result = js_beautify(xhr.responseText, opts);
+
+            browserWindow.Scratchpad.ScratchpadManager.openScratchpad({text: result});
+
+            promise.resolve();
+          } else {
+            promise.resolve("Unable to load page to beautify: " + args.url + " " +
+                            xhr.status + " " + xhr.statusText);
+          }
+        };
+      }
+      xhr.send(null);
+      return promise;
+    }
+  });
+}(this));
+
+/* CmdPagemod -------------------------------------------------------------- */
+
+(function(module) {
+  /**
+  * 'pagemod' command
+  */
+  gcli.addCommand({
+    name: "pagemod",
+    description: gcli.lookup("pagemodDesc"),
+  });
+
+  /**
+  * The 'pagemod replace' command. This command allows the user to search and
+  * replace within text nodes and attributes.
+  */
+  gcli.addCommand({
+    name: "pagemod replace",
+    description: gcli.lookup("pagemodReplaceDesc"),
+    params: [
+      {
+        name: "search",
+        type: "string",
+        description: gcli.lookup("pagemodReplaceSearchDesc"),
+      },
+      {
+        name: "replace",
+        type: "string",
+        description: gcli.lookup("pagemodReplaceReplaceDesc"),
+      },
+      {
+        name: "ignoreCase",
+        type: "boolean",
+        description: gcli.lookup("pagemodReplaceIgnoreCaseDesc"),
+      },
+      {
+        name: "selector",
+        type: "string",
+        description: gcli.lookup("pagemodReplaceSelectorDesc"),
+        defaultValue: "*:not(script):not(style):not(embed):not(object):not(frame):not(iframe):not(frameset)",
+      },
+      {
+        name: "root",
+        type: "node",
+        description: gcli.lookup("pagemodReplaceRootDesc"),
+        defaultValue: null,
+      },
+      {
+        name: "attrOnly",
+        type: "boolean",
+        description: gcli.lookup("pagemodReplaceAttrOnlyDesc"),
+      },
+      {
+        name: "contentOnly",
+        type: "boolean",
+        description: gcli.lookup("pagemodReplaceContentOnlyDesc"),
+      },
+      {
+        name: "attributes",
+        type: "string",
+        description: gcli.lookup("pagemodReplaceAttributesDesc"),
+        defaultValue: null,
+      },
+    ],
+    exec: function(args, context) {
+      let document = context.environment.contentDocument;
+      let searchTextNodes = !args.attrOnly;
+      let searchAttributes = !args.contentOnly;
+      let regexOptions = args.ignoreCase ? 'ig' : 'g';
+      let search = new RegExp(escapeRegex(args.search), regexOptions);
+      let attributeRegex = null;
+      if (args.attributes) {
+        attributeRegex = new RegExp(args.attributes, regexOptions);
+      }
+
+      let root = args.root || document;
+      let elements = root.querySelectorAll(args.selector);
+      elements = Array.prototype.slice.call(elements);
+
+      let replacedTextNodes = 0;
+      let replacedAttributes = 0;
+
+      function replaceAttribute() {
+        replacedAttributes++;
+        return args.replace;
+      }
+      function replaceTextNode() {
+        replacedTextNodes++;
+        return args.replace;
+      }
+
+      for (let i = 0; i < elements.length; i++) {
+        let element = elements[i];
+        if (searchTextNodes) {
+          for (let y = 0; y < element.childNodes.length; y++) {
+            let node = element.childNodes[y];
+            if (node.nodeType == node.TEXT_NODE) {
+              node.textContent = node.textContent.replace(search, replaceTextNode);
+            }
+          }
+        }
+
+        if (searchAttributes) {
+          if (!element.attributes) {
+            continue;
+          }
+          for (let y = 0; y < element.attributes.length; y++) {
+            let attr = element.attributes[y];
+            if (!attributeRegex || attributeRegex.test(attr.name)) {
+              attr.value = attr.value.replace(search, replaceAttribute);
+            }
+          }
+        }
+      }
+
+      return gcli.lookupFormat("pagemodReplaceResult",
+                              [elements.length, replacedTextNodes,
+                                replacedAttributes]);
+    }
+  });
+
+  /**
+  * 'pagemod remove' command
+  */
+  gcli.addCommand({
+    name: "pagemod remove",
+    description: gcli.lookup("pagemodRemoveDesc"),
+  });
+
+
+  /**
+  * The 'pagemod remove element' command.
+  */
+  gcli.addCommand({
+    name: "pagemod remove element",
+    description: gcli.lookup("pagemodRemoveElementDesc"),
+    params: [
+      {
+        name: "search",
+        type: "string",
+        description: gcli.lookup("pagemodRemoveElementSearchDesc"),
+      },
+      {
+        name: "root",
+        type: "node",
+        description: gcli.lookup("pagemodRemoveElementRootDesc"),
+        defaultValue: null,
+      },
+      {
+        name: 'stripOnly',
+        type: 'boolean',
+        description: gcli.lookup("pagemodRemoveElementStripOnlyDesc"),
+      },
+      {
+        name: 'ifEmptyOnly',
+        type: 'boolean',
+        description: gcli.lookup("pagemodRemoveElementIfEmptyOnlyDesc"),
+      },
+    ],
+    exec: function(args, context) {
+      let document = context.environment.contentDocument;
+      let root = args.root || document;
+      let elements = Array.prototype.slice.call(root.querySelectorAll(args.search));
+
+      let removed = 0;
+      for (let i = 0; i < elements.length; i++) {
+        let element = elements[i];
+        let parentNode = element.parentNode;
+        if (!parentNode || !element.removeChild) {
+          continue;
+        }
+        if (args.stripOnly) {
+          while (element.hasChildNodes()) {
+            parentNode.insertBefore(element.childNodes[0], element);
+          }
+        }
+        if (!args.ifEmptyOnly || !element.hasChildNodes()) {
+          element.parentNode.removeChild(element);
+          removed++;
+        }
+      }
+
+      return gcli.lookupFormat("pagemodRemoveElementResultMatchedAndRemovedElements",
+                              [elements.length, removed]);
+    }
+  });
+
+  /**
+  * The 'pagemod remove attribute' command.
+  */
+  gcli.addCommand({
+    name: "pagemod remove attribute",
+    description: gcli.lookup("pagemodRemoveAttributeDesc"),
+    params: [
+      {
+        name: "searchAttributes",
+        type: "string",
+        description: gcli.lookup("pagemodRemoveAttributeSearchAttributesDesc"),
+      },
+      {
+        name: "searchElements",
+        type: "string",
+        description: gcli.lookup("pagemodRemoveAttributeSearchElementsDesc"),
+      },
+      {
+        name: "root",
+        type: "node",
+        description: gcli.lookup("pagemodRemoveAttributeRootDesc"),
+        defaultValue: null,
+      },
+      {
+        name: "ignoreCase",
+        type: "boolean",
+        description: gcli.lookup("pagemodRemoveAttributeIgnoreCaseDesc"),
+      },
+    ],
+    exec: function(args, context) {
+      let document = context.environment.contentDocument;
+
+      let root = args.root || document;
+      let regexOptions = args.ignoreCase ? 'ig' : 'g';
+      let attributeRegex = new RegExp(args.searchAttributes, regexOptions);
+      let elements = root.querySelectorAll(args.searchElements);
+      elements = Array.prototype.slice.call(elements);
+
+      let removed = 0;
+      for (let i = 0; i < elements.length; i++) {
+        let element = elements[i];
+        if (!element.attributes) {
+          continue;
+        }
+
+        var attrs = Array.prototype.slice.call(element.attributes);
+        for (let y = 0; y < attrs.length; y++) {
+          let attr = attrs[y];
+          if (attributeRegex.test(attr.name)) {
+            element.removeAttribute(attr.name);
+            removed++;
+          }
+        }
+      }
+
+      return gcli.lookupFormat("pagemodRemoveAttributeResult",
+                              [elements.length, removed]);
+    }
+  });
+
+  /**
+  * Make a given string safe to use  in a regular expression.
+  *
+  * @param string aString
+  *        The string you want to use in a regex.
+  * @return string
+  *         The equivalent of |aString| but safe to use in a regex.
+  */
+  function escapeRegex(aString) {
+    return aString.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
+  }
+}(this));
+
+/* CmdRestart -------------------------------------------------------------- */
+
+(function(module) {
+  /**
+  * Restart command
+  *
+  * @param boolean nocache
+  *        Disables loading content from cache upon restart.
+  *
+  * Examples :
+  * >> restart
+  * - restarts browser immediately
+  * >> restart --nocache
+  * - restarts immediately and starts Firefox without using cache
+  */
+  gcli.addCommand({
+    name: "restart",
+    description: gcli.lookup("restartFirefoxDesc"),
+    params: [
+      {
+        name: "nocache",
+        type: "boolean",
+        description: gcli.lookup("restartFirefoxNocacheDesc")
+      }
+    ],
+    returnType: "string",
+    exec: function Restart(args, context) {
+      let canceled = Cc["@mozilla.org/supports-PRBool;1"]
+                      .createInstance(Ci.nsISupportsPRBool);
+      Services.obs.notifyObservers(canceled, "quit-application-requested", "restart");
+      if (canceled.data) {
+        return gcli.lookup("restartFirefoxRequestCancelled");
+      }
+
+      // disable loading content from cache.
+      if (args.nocache) {
+        Services.appinfo.invalidateCachesOnRestart();
+      }
+
+      // restart
+      Cc['@mozilla.org/toolkit/app-startup;1']
+        .getService(Ci.nsIAppStartup)
+        .quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
+      return gcli.lookup("restartFirefoxRestarting");
+    }
+  });
+}(this));
+
+/* CmdScreenshot ----------------------------------------------------------- */
+
+(function(module) {
+  XPCOMUtils.defineLazyModuleGetter(this, "LayoutHelpers",
+                                    "resource:///modules/devtools/LayoutHelpers.jsm");
+
+  // String used as an indication to generate default file name in the following
+  // format: "Screen Shot yyyy-mm-dd at HH.MM.SS.png"
+  const FILENAME_DEFAULT_VALUE = " ";
+
+  /**
+  * 'screenshot' command
+  */
+  gcli.addCommand({
+    name: "screenshot",
+    description: gcli.lookup("screenshotDesc"),
+    manual: gcli.lookup("screenshotManual"),
+    returnType: "html",
+    params: [
+      {
+        name: "filename",
+        type: "string",
+        defaultValue: FILENAME_DEFAULT_VALUE,
+        description: gcli.lookup("screenshotFilenameDesc"),
+        manual: gcli.lookup("screenshotFilenameManual")
+      },
+      {
+        group: gcli.lookup("screenshotGroupOptions"),
+        params: [
+          {
+            name: "clipboard",
+            type: "boolean",
+            description: gcli.lookup("screenshotClipboardDesc"),
+            manual: gcli.lookup("screenshotClipboardManual")
+          },
+          {
+            name: "chrome",
+            type: "boolean",
+            description: gcli.lookup("screenshotChromeDesc"),
+            manual: gcli.lookup("screenshotChromeManual")
+          },
+          {
+            name: "delay",
+            type: { name: "number", min: 0 },
+            defaultValue: 0,
+            description: gcli.lookup("screenshotDelayDesc"),
+            manual: gcli.lookup("screenshotDelayManual")
+          },
+          {
+            name: "fullpage",
+            type: "boolean",
+            description: gcli.lookup("screenshotFullPageDesc"),
+            manual: gcli.lookup("screenshotFullPageManual")
+          },
+          {
+            name: "selector",
+            type: "node",
+            defaultValue: null,
+            description: gcli.lookup("inspectNodeDesc"),
+            manual: gcli.lookup("inspectNodeManual")
+          }
+        ]
+      }
+    ],
+    exec: function Command_screenshot(args, context) {
+      if (args.chrome && args.selector) {
+        // Node screenshot with chrome option does not work as inteded
+        // Refer https://bugzilla.mozilla.org/show_bug.cgi?id=659268#c7
+        // throwing for now.
+        throw new Error(gcli.lookup("screenshotSelectorChromeConflict"));
+      }
+      var document = args.chrome? context.environment.chromeDocument
+                                : context.environment.contentDocument;
+      if (args.delay > 0) {
+        var promise = context.createPromise();
+        document.defaultView.setTimeout(function Command_screenshotDelay() {
+          let reply = this.grabScreen(document, args.filename, args.clipboard,
+                                      args.fullpage);
+          promise.resolve(reply);
+        }.bind(this), args.delay * 1000);
+        return promise;
+      }
+      else {
+        return this.grabScreen(document, args.filename, args.clipboard,
+                              args.fullpage, args.selector);
+      }
+    },
+    grabScreen:
+    function Command_screenshotGrabScreen(document, filename, clipboard,
+                                          fullpage, node) {
+      let window = document.defaultView;
+      let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
+      let left = 0;
+      let top = 0;
+      let width;
+      let height;
+      let div = document.createElementNS("http://www.w3.org/1999/xhtml", "div");
+
+      if (!fullpage) {
+        if (!node) {
+          left = window.scrollX;
+          top = window.scrollY;
+          width = window.innerWidth;
+          height = window.innerHeight;
+        } else {
+          let rect = LayoutHelpers.getRect(node, window);
+          top = rect.top;
+          left = rect.left;
+          width = rect.width;
+          height = rect.height;
+        }
+      } else {
+        width = window.innerWidth + window.scrollMaxX;
+        height = window.innerHeight + window.scrollMaxY;
+      }
+      canvas.width = width;
+      canvas.height = height;
+
+      let ctx = canvas.getContext("2d");
+      ctx.drawWindow(window, left, top, width, height, "#fff");
+      let data = canvas.toDataURL("image/png", "");
+
+      let loadContext = document.defaultView
+                                .QueryInterface(Ci.nsIInterfaceRequestor)
+                                .getInterface(Ci.nsIWebNavigation)
+                                .QueryInterface(Ci.nsILoadContext);
+
+      try {
+        if (clipboard) {
+          let io = Cc["@mozilla.org/network/io-service;1"]
+                    .getService(Ci.nsIIOService);
+          let channel = io.newChannel(data, null, null);
+          let input = channel.open();
+          let imgTools = Cc["@mozilla.org/image/tools;1"]
+                          .getService(Ci.imgITools);
+
+          let container = {};
+          imgTools.decodeImageData(input, channel.contentType, container);
+
+          let wrapped = Cc["@mozilla.org/supports-interface-pointer;1"]
+                          .createInstance(Ci.nsISupportsInterfacePointer);
+          wrapped.data = container.value;
+
+          let trans = Cc["@mozilla.org/widget/transferable;1"]
+                        .createInstance(Ci.nsITransferable);
+          trans.init(loadContext);
+          trans.addDataFlavor(channel.contentType);
+          trans.setTransferData(channel.contentType, wrapped, -1);
+
+          let clipid = Ci.nsIClipboard;
+          let clip = Cc["@mozilla.org/widget/clipboard;1"].getService(clipid);
+          clip.setData(trans, null, clipid.kGlobalClipboard);
+          div.textContent = gcli.lookup("screenshotCopied");
+          return div;
+        }
+      }
+      catch (ex) {
+        div.textContent = gcli.lookup("screenshotErrorCopying");
+        return div;
+      }
+
+      let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
+
+      // Create a name for the file if not present
+      if (filename == FILENAME_DEFAULT_VALUE) {
+        let date = new Date();
+        let dateString = date.getFullYear() + "-" + (date.getMonth() + 1) +
+                        "-" + date.getDate();
+        dateString = dateString.split("-").map(function(part) {
+          if (part.length == 1) {
+            part = "0" + part;
+          }
+          return part;
+        }).join("-");
+        let timeString = date.toTimeString().replace(/:/g, ".").split(" ")[0];
+        filename = gcli.lookupFormat("screenshotGeneratedFilename",
+                                    [dateString, timeString]) + ".png";
+      }
+      // Check there is a .png extension to filename
+      else if (!filename.match(/.png$/i)) {
+        filename += ".png";
+      }
+
+      // If the filename is relative, tack it onto the download directory
+      if (!filename.match(/[\\\/]/)) {
+        let downloadMgr = Cc["@mozilla.org/download-manager;1"]
+                            .getService(Ci.nsIDownloadManager);
+        let tempfile = downloadMgr.userDownloadsDirectory;
+        tempfile.append(filename);
+        filename = tempfile.path;
+      }
+
+      try {
+        file.initWithPath(filename);
+      } catch (ex) {
+        div.textContent = gcli.lookup("screenshotErrorSavingToFile") + " " + filename;
+        return div;
+      }
+
+      let ioService = Cc["@mozilla.org/network/io-service;1"]
+                        .getService(Ci.nsIIOService);
+
+      let Persist = Ci.nsIWebBrowserPersist;
+      let persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
+                      .createInstance(Persist);
+      persist.persistFlags = Persist.PERSIST_FLAGS_REPLACE_EXISTING_FILES |
+                            Persist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
+
+      let source = ioService.newURI(data, "UTF8", null);
+      persist.saveURI(source, null, null, null, null, file, loadContext);
+
+      div.textContent = gcli.lookup("screenshotSavedToFile") + " \"" + filename +
+                        "\"";
+      div.addEventListener("click", function openFile() {
+        div.removeEventListener("click", openFile);
+        file.reveal();
+      });
+      div.style.cursor = "pointer";
+      let image = document.createElement("div");
+      let previewHeight = parseInt(256*height/width);
+      image.setAttribute("style",
+                        "width:256px; height:" + previewHeight + "px;" +
+                        "max-height: 256px;" +
+                        "background-image: url('" + data + "');" +
+                        "background-size: 256px " + previewHeight + "px;" +
+                        "margin: 4px; display: block");
+      div.appendChild(image);
+      return div;
+    }
+  });
+}(this));
deleted file mode 100644
--- a/browser/devtools/commandline/CmdAddon.jsm
+++ /dev/null
@@ -1,297 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-this.EXPORTED_SYMBOLS = [ "Flags" ];
-
-Cu.import("resource:///modules/devtools/gcli.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
-                                  "resource://gre/modules/AddonManager.jsm");
-
-// We need to use an object in which to store any flags because a primitive
-// would remain undefined.
-this.Flags = {
-  addonsLoaded: false
-};
-
-/**
- * 'addon' command.
- */
-gcli.addCommand({
-  name: "addon",
-  description: gcli.lookup("addonDesc")
-});
-
-/**
- * 'addon list' command.
- */
-gcli.addCommand({
-  name: "addon list",
-  description: gcli.lookup("addonListDesc"),
-  params: [{
-    name: 'type',
-    type: {
-      name: 'selection',
-      data: ["dictionary", "extension", "locale", "plugin", "theme", "all"]
-    },
-    defaultValue: 'all',
-    description: gcli.lookup("addonListTypeDesc"),
-  }],
-  exec: function(aArgs, context) {
-    function representEnabledAddon(aAddon) {
-      return "<li><![CDATA[" + aAddon.name + "\u2002" + aAddon.version +
-      getAddonStatus(aAddon) + "]]></li>";
-    }
-
-    function representDisabledAddon(aAddon) {
-      return "<li class=\"gcli-addon-disabled\">" +
-        "<![CDATA[" + aAddon.name + "\u2002" + aAddon.version + aAddon.version +
-        "]]></li>";
-    }
-
-    function getAddonStatus(aAddon) {
-      let operations = [];
-
-      if (aAddon.pendingOperations & AddonManager.PENDING_ENABLE) {
-        operations.push("PENDING_ENABLE");
-      }
-
-      if (aAddon.pendingOperations & AddonManager.PENDING_DISABLE) {
-        operations.push("PENDING_DISABLE");
-      }
-
-      if (aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL) {
-        operations.push("PENDING_UNINSTALL");
-      }
-
-      if (aAddon.pendingOperations & AddonManager.PENDING_INSTALL) {
-        operations.push("PENDING_INSTALL");
-      }
-
-      if (aAddon.pendingOperations & AddonManager.PENDING_UPGRADE) {
-        operations.push("PENDING_UPGRADE");
-      }
-
-      if (operations.length) {
-        return " (" + operations.join(", ") + ")";
-      }
-      return "";
-    }
-
-    /**
-     * Compares two addons by their name. Used in sorting.
-     */
-    function compareAddonNames(aNameA, aNameB) {
-      return String.localeCompare(aNameA.name, aNameB.name);
-    }
-
-    /**
-     * Resolves the promise which is the scope (this) of this function, filling
-     * it with an HTML representation of the passed add-ons.
-     */
-    function list(aType, aAddons) {
-      if (!aAddons.length) {
-        this.resolve(gcli.lookup("addonNoneOfType"));
-      }
-
-      // Separate the enabled add-ons from the disabled ones.
-      let enabledAddons = [];
-      let disabledAddons = [];
-
-      aAddons.forEach(function(aAddon) {
-        if (aAddon.isActive) {
-          enabledAddons.push(aAddon);
-        } else {
-          disabledAddons.push(aAddon);
-        }
-      });
-
-      let header;
-      switch(aType) {
-        case "dictionary":
-          header = gcli.lookup("addonListDictionaryHeading");
-          break;
-        case "extension":
-          header = gcli.lookup("addonListExtensionHeading");
-          break;
-        case "locale":
-          header = gcli.lookup("addonListLocaleHeading");
-          break;
-        case "plugin":
-          header = gcli.lookup("addonListPluginHeading");
-          break;
-        case "theme":
-          header = gcli.lookup("addonListThemeHeading");
-        case "all":
-          header = gcli.lookup("addonListAllHeading");
-          break;
-        default:
-          header = gcli.lookup("addonListUnknownHeading");
-      }
-
-      // Map and sort the add-ons, and create an HTML list.
-      let message = header +
-                    "<ol>" +
-                    enabledAddons.sort(compareAddonNames).map(representEnabledAddon).join("") +
-                    disabledAddons.sort(compareAddonNames).map(representDisabledAddon).join("") +
-                    "</ol>";
-
-      this.resolve(context.createView({ html: message }));
-    }
-
-    // Create the promise that will be resolved when the add-on listing has
-    // been finished.
-    let promise = context.createPromise();
-    let types = aArgs.type == "all" ? null : [aArgs.type];
-    AddonManager.getAddonsByTypes(types, list.bind(promise, aArgs.type));
-    return promise;
-  }
-});
-
-// We need a list of addon names for the enable and disable commands. Because
-// getting the name list is async we do not add the commands until we have the
-// list.
-AddonManager.getAllAddons(function addonAsync(aAddons) {
-  // We listen for installs to keep our addon list up to date. There is no need
-  // to listen for uninstalls because uninstalled addons are simply disabled
-  // until restart (to enable undo functionality).
-  AddonManager.addAddonListener({
-    onInstalled: function(aAddon) {
-      addonNameCache.push({
-        name: representAddon(aAddon).replace(/\s/g, "_"),
-        value: aAddon.name
-      });
-    },
-    onUninstalled: function(aAddon) {
-      let name = representAddon(aAddon).replace(/\s/g, "_");
-
-      for (let i = 0; i < addonNameCache.length; i++) {
-        if(addonNameCache[i].name == name) {
-          addonNameCache.splice(i, 1);
-          break;
-        }
-      }
-    },
-  });
-
-  /**
-   * Returns a string that represents the passed add-on.
-   */
-  function representAddon(aAddon) {
-    let name = aAddon.name + " " + aAddon.version;
-    return name.trim();
-  }
-
-  let addonNameCache = [];
-
-  // The name parameter, used in "addon enable" and "addon disable."
-  let nameParameter = {
-    name: "name",
-    type: {
-      name: "selection",
-      lookup: addonNameCache
-    },
-    description: gcli.lookup("addonNameDesc")
-  };
-
-  for (let addon of aAddons) {
-    addonNameCache.push({
-      name: representAddon(addon).replace(/\s/g, "_"),
-      value: addon.name
-    });
-  }
-
-  /**
-   * 'addon enable' command.
-   */
-  gcli.addCommand({
-    name: "addon enable",
-    description: gcli.lookup("addonEnableDesc"),
-    params: [nameParameter],
-    exec: function(aArgs, context) {
-      /**
-       * Enables the addon in the passed list which has a name that matches
-       * according to the passed name comparer, and resolves the promise which
-       * is the scope (this) of this function to display the result of this
-       * enable attempt.
-       */
-      function enable(aName, addons) {
-        // Find the add-on.
-        let addon = null;
-        addons.some(function(candidate) {
-          if (candidate.name == aName) {
-            addon = candidate;
-            return true;
-          } else {
-            return false;
-          }
-        });
-
-        let name = representAddon(addon);
-        let message = "";
-
-        if (!addon.userDisabled) {
-          message = gcli.lookupFormat("addonAlreadyEnabled", [name]);
-        } else {
-          addon.userDisabled = false;
-          message = gcli.lookupFormat("addonEnabled", [name]);
-        }
-        this.resolve(message);
-      }
-
-      let promise = context.createPromise();
-      // List the installed add-ons, enable one when done listing.
-      AddonManager.getAllAddons(enable.bind(promise, aArgs.name));
-      return promise;
-    }
-  });
-
-  /**
-   * 'addon disable' command.
-   */
-  gcli.addCommand({
-    name: "addon disable",
-    description: gcli.lookup("addonDisableDesc"),
-    params: [nameParameter],
-    exec: function(aArgs, context) {
-      /**
-       * Like enable, but ... you know ... the exact opposite.
-       */
-      function disable(aName, addons) {
-        // Find the add-on.
-        let addon = null;
-        addons.some(function(candidate) {
-          if (candidate.name == aName) {
-            addon = candidate;
-            return true;
-          } else {
-            return false;
-          }
-        });
-
-        let name = representAddon(addon);
-        let message = "";
-
-        if (addon.userDisabled) {
-          message = gcli.lookupFormat("addonAlreadyDisabled", [name]);
-        } else {
-          addon.userDisabled = true;
-          message = gcli.lookupFormat("addonDisabled", [name]);
-        }
-        this.resolve(message);
-      }
-
-      let promise = context.createPromise();
-      // List the installed add-ons, disable one when done listing.
-      AddonManager.getAllAddons(disable.bind(promise, aArgs.name));
-      return promise;
-    }
-  });
-  Flags.addonsLoaded = true;
-  Services.obs.notifyObservers(null, "gcli_addon_commands_ready", null);
-});
deleted file mode 100644
--- a/browser/devtools/commandline/CmdBreak.jsm
+++ /dev/null
@@ -1,184 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-this.EXPORTED_SYMBOLS = [ ];
-
-Cu.import("resource:///modules/devtools/gcli.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "HUDService",
-                                  "resource:///modules/HUDService.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
-                                  "resource:///modules/devtools/Target.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
-                                  "resource:///modules/devtools/gDevTools.jsm");
-
-/**
- * 'break' command
- */
-gcli.addCommand({
-  name: "break",
-  description: gcli.lookup("breakDesc"),
-  manual: gcli.lookup("breakManual")
-});
-
-/**
- * 'break list' command
- */
-gcli.addCommand({
-  name: "break list",
-  description: gcli.lookup("breaklistDesc"),
-  returnType: "html",
-  exec: function(args, context) {
-    let dbg = getPanel(context, "jsdebugger");
-    if (!dbg) {
-      return gcli.lookup("debuggerStopped");
-    }
-
-    let breakpoints = dbg.getAllBreakpoints();
-
-    if (Object.keys(breakpoints).length === 0) {
-      return gcli.lookup("breaklistNone");
-    }
-
-    let reply = gcli.lookup("breaklistIntro");
-    reply += "<ol>";
-    for each (let breakpoint in breakpoints) {
-      let text = gcli.lookupFormat("breaklistLineEntry",
-                                   [breakpoint.location.url,
-                                    breakpoint.location.line]);
-      reply += "<li>" + text + "</li>";
-    };
-    reply += "</ol>";
-    return reply;
-  }
-});
-
-/**
- * 'break add' command
- */
-gcli.addCommand({
-  name: "break add",
-  description: gcli.lookup("breakaddDesc"),
-  manual: gcli.lookup("breakaddManual")
-});
-
-/**
- * 'break add line' command
- */
-gcli.addCommand({
-  name: "break add line",
-  description: gcli.lookup("breakaddlineDesc"),
-  params: [
-    {
-      name: "file",
-      type: {
-        name: "selection",
-        data: function(args, context) {
-          let files = [];
-          let dbg = getPanel(context, "jsdebugger");
-          if (dbg) {
-            let sourcesView = dbg.panelWin.DebuggerView.Sources;
-            for (let item in sourcesView) {
-              files.push(item.value);
-            }
-          }
-          return files;
-        }
-      },
-      description: gcli.lookup("breakaddlineFileDesc")
-    },
-    {
-      name: "line",
-      type: { name: "number", min: 1, step: 10 },
-      description: gcli.lookup("breakaddlineLineDesc")
-    }
-  ],
-  returnType: "html",
-  exec: function(args, context) {
-    args.type = "line";
-
-    let dbg = getPanel(context, "jsdebugger");
-    if (!dbg) {
-      return gcli.lookup("debuggerStopped");
-    }
-    var deferred = context.defer();
-    let position = { url: args.file, line: args.line };
-    dbg.addBreakpoint(position, function(aBreakpoint, aError) {
-      if (aError) {
-        deferred.resolve(gcli.lookupFormat("breakaddFailed", [aError]));
-        return;
-      }
-      deferred.resolve(gcli.lookup("breakaddAdded"));
-    });
-    return deferred.promise;
-  }
-});
-
-
-/**
- * 'break del' command
- */
-gcli.addCommand({
-  name: "break del",
-  description: gcli.lookup("breakdelDesc"),
-  params: [
-    {
-      name: "breakid",
-      type: {
-        name: "number",
-        min: 0,
-        max: function(args, context) {
-          let dbg = getPanel(context, "jsdebugger");
-          return dbg == null ?
-              null :
-              Object.keys(dbg.getAllBreakpoints()).length - 1;
-        },
-      },
-      description: gcli.lookup("breakdelBreakidDesc")
-    }
-  ],
-  returnType: "html",
-  exec: function(args, context) {
-    let dbg = getPanel(context, "jsdebugger");
-    if (!dbg) {
-      return gcli.lookup("debuggerStopped");
-    }
-
-    let breakpoints = dbg.getAllBreakpoints();
-    let id = Object.keys(breakpoints)[args.breakid];
-    if (!id || !(id in breakpoints)) {
-      return gcli.lookup("breakNotFound");
-    }
-
-    let deferred = context.defer();
-    try {
-      dbg.removeBreakpoint(breakpoints[id], function() {
-        deferred.resolve(gcli.lookup("breakdelRemoved"));
-      });
-    } catch (ex) {
-      // If the debugger has been closed already, don't scare the user.
-      deferred.resolve(gcli.lookup("breakdelRemoved"));
-    }
-    return deferred.promise;
-  }
-});
-
-/**
- * A helper to go from a command context to a debugger panel
- */
-function getPanel(context, id) {
-  if (context == null) {
-    return undefined;
-  }
-
-  let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
-  let target = TargetFactory.forTab(gBrowser.selectedTab);
-  let toolbox = gDevTools.getToolbox(target);
-  return toolbox == null ? undefined : toolbox.getPanel(id);
-}
deleted file mode 100644
--- a/browser/devtools/commandline/CmdCalllog.jsm
+++ /dev/null
@@ -1,107 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-this.EXPORTED_SYMBOLS = [ ];
-
-Cu.import("resource:///modules/devtools/gcli.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
-                                  "resource:///modules/devtools/gDevTools.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "Debugger", function() {
-  let JsDebugger = {};
-  Components.utils.import("resource://gre/modules/jsdebugger.jsm", JsDebugger);
-
-  let global = Components.utils.getGlobalForObject({});
-  JsDebugger.addDebuggerToGlobal(global);
-
-  return global.Debugger;
-});
-
-XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
-                                  "resource:///modules/devtools/Target.jsm");
-
-let debuggers = [];
-
-/**
- * 'calllog' command
- */
-gcli.addCommand({
-  name: "calllog",
-  description: gcli.lookup("calllogDesc")
-})
-
-/**
- * 'calllog start' command
- */
-gcli.addCommand({
-  name: "calllog start",
-  description: gcli.lookup("calllogStartDesc"),
-
-  exec: function(args, context) {
-    let contentWindow = context.environment.contentDocument.defaultView;
-
-    let dbg = new Debugger(contentWindow);
-    dbg.onEnterFrame = function(frame) {
-      // BUG 773652 -  Make the output from the GCLI calllog command nicer
-      contentWindow.console.log("Method call: " + this.callDescription(frame));
-    }.bind(this);
-
-    debuggers.push(dbg);
-
-    let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
-    let target = TargetFactory.forTab(gBrowser.selectedTab);
-    gDevTools.showToolbox(target, "webconsole");
-
-    return gcli.lookup("calllogStartReply");
-  },
-
-  callDescription: function(frame) {
-    let name = "<anonymous>";
-    if (frame.callee.name) {
-      name = frame.callee.name;
-    }
-    else {
-      let desc = frame.callee.getOwnPropertyDescriptor("displayName");
-      if (desc && desc.value && typeof desc.value == "string") {
-        name = desc.value;
-      }
-    }
-
-    let args = frame.arguments.map(this.valueToString).join(", ");
-    return name + "(" + args + ")";
-  },
-
-  valueToString: function(value) {
-    if (typeof value !== "object" || value === null) {
-      return uneval(value);
-    }
-    return "[object " + value.class + "]";
-  }
-});
-
-/**
- * 'calllog stop' command
- */
-gcli.addCommand({
-  name: "calllog stop",
-  description: gcli.lookup("calllogStopDesc"),
-
-  exec: function(args, context) {
-    let numDebuggers = debuggers.length;
-    if (numDebuggers == 0) {
-      return gcli.lookup("calllogStopNoLogging");
-    }
-
-    for (let dbg of debuggers) {
-      dbg.onEnterFrame = undefined;
-    }
-    debuggers = [];
-
-    return gcli.lookupFormat("calllogStopReply", [ numDebuggers ]);
-  }
-});
deleted file mode 100644
--- a/browser/devtools/commandline/CmdCalllogChrome.jsm
+++ /dev/null
@@ -1,158 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-this.EXPORTED_SYMBOLS = [ ];
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-Cu.import("resource:///modules/devtools/gcli.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
-                                  "resource:///modules/devtools/gDevTools.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
-                                  "resource:///modules/devtools/Target.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "Debugger", function() {
-  let JsDebugger = {};
-  Cu.import("resource://gre/modules/jsdebugger.jsm", JsDebugger);
-
-  let global = Components.utils.getGlobalForObject({});
-  JsDebugger.addDebuggerToGlobal(global);
-
-  return global.Debugger;
-});
-
-let debuggers = [];
-let sandboxes = [];
-
-/**
- * 'calllog chromestart' command
- */
-gcli.addCommand({
-  name: "calllog chromestart",
-  description: gcli.lookup("calllogChromeStartDesc"),
-  get hidden() gcli.hiddenByChromePref(),
-  params: [
-    {
-      name: "sourceType",
-      type: {
-        name: "selection",
-        data: ["content-variable", "chrome-variable", "jsm", "javascript"]
-      }
-    },
-    {
-      name: "source",
-      type: "string",
-      description: gcli.lookup("calllogChromeSourceTypeDesc"),
-      manual: gcli.lookup("calllogChromeSourceTypeManual"),
-    }
-  ],
-  exec: function(args, context) {
-    let globalObj;
-    let contentWindow = context.environment.contentDocument.defaultView;
-
-    if (args.sourceType == "jsm") {
-      try {
-        globalObj = Cu.import(args.source);
-      }
-      catch (e) {
-        return gcli.lookup("callLogChromeInvalidJSM");
-      }
-    } else if (args.sourceType == "content-variable") {
-      if (args.source in contentWindow) {
-        globalObj = Cu.getGlobalForObject(contentWindow[args.source]);
-      } else {
-        throw new Error(gcli.lookup("callLogChromeVarNotFoundContent"));
-      }
-    } else if (args.sourceType == "chrome-variable") {
-      let chromeWin = context.environment.chromeDocument.defaultView;
-      if (args.source in chromeWin) {
-        globalObj = Cu.getGlobalForObject(chromeWin[args.source]);
-      } else {
-        return gcli.lookup("callLogChromeVarNotFoundChrome");
-      }
-    } else {
-      let chromeWin = context.environment.chromeDocument.defaultView;
-      let sandbox = new Cu.Sandbox(chromeWin,
-                                   {
-                                     sandboxPrototype: chromeWin,
-                                     wantXrays: false,
-                                     sandboxName: "gcli-cmd-calllog-chrome"
-                                   });
-      let returnVal;
-      try {
-        returnVal = Cu.evalInSandbox(args.source, sandbox, "ECMAv5");
-        sandboxes.push(sandbox);
-      } catch(e) {
-        // We need to save the message before cleaning up else e contains a dead
-        // object.
-        let msg = gcli.lookup("callLogChromeEvalException") + ": " + e;
-        Cu.nukeSandbox(sandbox);
-        return msg;
-      }
-
-      if (typeof returnVal == "undefined") {
-        return gcli.lookup("callLogChromeEvalNeedsObject");
-      }
-
-      globalObj = Cu.getGlobalForObject(returnVal);
-    }
-
-    let dbg = new Debugger(globalObj);
-    debuggers.push(dbg);
-
-    dbg.onEnterFrame = function(frame) {
-      // BUG 773652 -  Make the output from the GCLI calllog command nicer
-      contentWindow.console.log(gcli.lookup("callLogChromeMethodCall") +
-                                ": " + this.callDescription(frame));
-    }.bind(this);
-
-    let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
-    let target = TargetFactory.forTab(gBrowser.selectedTab);
-    gDevTools.showToolbox(target, "webconsole");
-
-    return gcli.lookup("calllogChromeStartReply");
-  },
-
-  valueToString: function(value) {
-    if (typeof value !== "object" || value === null)
-      return uneval(value);
-    return "[object " + value.class + "]";
-  },
-
-  callDescription: function(frame) {
-    let name = frame.callee.name || gcli.lookup("callLogChromeAnonFunction");
-    let args = frame.arguments.map(this.valueToString).join(", ");
-    return name + "(" + args + ")";
-  }
-});
-
-/**
- * 'calllog chromestop' command
- */
-gcli.addCommand({
-  name: "calllog chromestop",
-  description: gcli.lookup("calllogChromeStopDesc"),
-  get hidden() gcli.hiddenByChromePref(),
-  exec: function(args, context) {
-    let numDebuggers = debuggers.length;
-    if (numDebuggers == 0) {
-      return gcli.lookup("calllogChromeStopNoLogging");
-    }
-
-    for (let dbg of debuggers) {
-      dbg.onEnterFrame = undefined;
-      dbg.enabled = false;
-    }
-    for (let sandbox of sandboxes) {
-      Cu.nukeSandbox(sandbox);
-    }
-    debuggers = [];
-    sandboxes = [];
-
-    return gcli.lookupFormat("calllogChromeStopReply", [ numDebuggers ]);
-  }
-});
deleted file mode 100644
--- a/browser/devtools/commandline/CmdCmd.jsm
+++ /dev/null
@@ -1,129 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-this.EXPORTED_SYMBOLS = [ "CmdCommands" ];
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-Cu.import("resource:///modules/devtools/gcli.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-let prefSvc = "@mozilla.org/preferences-service;1";
-XPCOMUtils.defineLazyGetter(this, "prefBranch", function() {
-  let prefService = Cc[prefSvc].getService(Ci.nsIPrefService);
-  return prefService.getBranch(null).QueryInterface(Ci.nsIPrefBranch2);
-});
-
-XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
-                                  "resource://gre/modules/NetUtil.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "console",
-                                  "resource://gre/modules/devtools/Console.jsm");
-
-const PREF_DIR = "devtools.commands.dir";
-
-/**
- * A place to store the names of the commands that we have added as a result of
- * calling refreshAutoCommands(). Used by refreshAutoCommands to remove the
- * added commands.
- */
-let commands = [];
-
-/**
- * Exported API
- */
-this.CmdCommands = {
-  /**
-   * Called to look in a directory pointed at by the devtools.commands.dir pref
-   * for *.mozcmd files which are then loaded.
-   * @param nsIPrincipal aSandboxPrincipal Scope object for the Sandbox in which
-   * we eval the script from the .mozcmd file. This should be a chrome window.
-   */
-  refreshAutoCommands: function GC_refreshAutoCommands(aSandboxPrincipal) {
-    // First get rid of the last set of commands
-    commands.forEach(function(name) {
-      gcli.removeCommand(name);
-    });
-
-    let dirName = prefBranch.getComplexValue(PREF_DIR,
-                                             Ci.nsISupportsString).data.trim();
-    if (dirName == "") {
-      return;
-    }
-
-    let dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
-    dir.initWithPath(dirName);
-    if (!dir.exists() || !dir.isDirectory()) {
-      throw new Error('\'' + dirName + '\' is not a directory.');
-    }
-
-    let en = dir.directoryEntries.QueryInterface(Ci.nsIDirectoryEnumerator);
-
-    while (true) {
-      let file = en.nextFile;
-      if (!file) {
-        break;
-      }
-      if (file.leafName.match(/.*\.mozcmd$/) && file.isFile() && file.isReadable()) {
-        loadCommandFile(file, aSandboxPrincipal);
-      }
-    }
-  },
-};
-
-/**
- * Load the commands from a single file
- * @param nsIFile aFile The file containing the commands that we should read
- * @param nsIPrincipal aSandboxPrincipal Scope object for the Sandbox in which
- * we eval the script from the .mozcmd file. This should be a chrome window.
- */
-function loadCommandFile(aFile, aSandboxPrincipal) {
-  NetUtil.asyncFetch(aFile, function refresh_fetch(aStream, aStatus) {
-    if (!Components.isSuccessCode(aStatus)) {
-      console.error("NetUtil.asyncFetch(" + aFile.path + ",..) failed. Status=" + aStatus);
-      return;
-    }
-
-    let source = NetUtil.readInputStreamToString(aStream, aStream.available());
-    aStream.close();
-
-    let sandbox = new Cu.Sandbox(aSandboxPrincipal, {
-      sandboxPrototype: aSandboxPrincipal,
-      wantXrays: false,
-      sandboxName: aFile.path
-    });
-    let data = Cu.evalInSandbox(source, sandbox, "1.8", aFile.leafName, 1);
-
-    if (!Array.isArray(data)) {
-      console.error("Command file '" + aFile.leafName + "' does not have top level array.");
-      return;
-    }
-
-    data.forEach(function(commandSpec) {
-      gcli.addCommand(commandSpec);
-      commands.push(commandSpec.name);
-    });
-  }.bind(this));
-}
-
-/**
- * 'cmd' command
- */
-gcli.addCommand({
-  name: "cmd",
-  get hidden() { return !prefBranch.prefHasUserValue(PREF_DIR); },
-  description: gcli.lookup("cmdDesc")
-});
-
-/**
- * 'cmd refresh' command
- */
-gcli.addCommand({
-  name: "cmd refresh",
-  description: gcli.lookup("cmdRefreshDesc"),
-  get hidden() { return !prefBranch.prefHasUserValue(PREF_DIR); },
-  exec: function Command_cmdRefresh(args, context) {
-    let chromeWindow = context.environment.chromeDocument.defaultView;
-    CmdCommands.refreshAutoCommands(chromeWindow);
-  }
-});
deleted file mode 100644
--- a/browser/devtools/commandline/CmdConsole.jsm
+++ /dev/null
@@ -1,68 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-this.EXPORTED_SYMBOLS = [ ];
-
-Cu.import("resource:///modules/devtools/gcli.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "HUDService",
-                                  "resource:///modules/HUDService.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
-                                  "resource:///modules/devtools/gDevTools.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
-                                  "resource:///modules/devtools/Target.jsm");
-
-/**
- * 'console' command
- */
-gcli.addCommand({
-  name: "console",
-  description: gcli.lookup("consoleDesc"),
-  manual: gcli.lookup("consoleManual")
-});
-
-/**
- * 'console clear' command
- */
-gcli.addCommand({
-  name: "console clear",
-  description: gcli.lookup("consoleclearDesc"),
-  exec: function Command_consoleClear(args, context) {
-    let window = context.environment.contentDocument.defaultView;
-    let hud = HUDService.getHudByWindow(window);
-    // hud will be null if the web console has not been opened for this window
-    if (hud) {
-      hud.jsterm.clearOutput();
-    }
-  }
-});
-
-/**
- * 'console close' command
- */
-gcli.addCommand({
-  name: "console close",
-  description: gcli.lookup("consolecloseDesc"),
-  exec: function Command_consoleClose(args, context) {
-    let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
-    let target = TargetFactory.forTab(gBrowser.selectedTab);
-    return gDevTools.closeToolbox(target);
-  }
-});
-
-/**
- * 'console open' command
- */
-gcli.addCommand({
-  name: "console open",
-  description: gcli.lookup("consoleopenDesc"),
-  exec: function Command_consoleOpen(args, context) {
-    let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
-    let target = TargetFactory.forTab(gBrowser.selectedTab);
-    return gDevTools.showToolbox(target, "webconsole");
-  }
-});
deleted file mode 100644
--- a/browser/devtools/commandline/CmdCookie.jsm
+++ /dev/null
@@ -1,207 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-this.EXPORTED_SYMBOLS = [ ];
-
-Cu.import("resource:///modules/devtools/gcli.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "console",
-                                  "resource://gre/modules/devtools/Console.jsm");
-
-// We should really be using nsICookieManager so we can read more than just the
-// key/value of cookies. The difficulty is filtering the cookies that are
-// relevant to the current page. See
-// https://github.com/firebug/firebug/blob/master/extension/content/firebug/cookies/cookieObserver.js#L123
-// For details on how this is done with Firebug
-
-/**
- * 'cookie' command
- */
-gcli.addCommand({
-  name: "cookie",
-  description: gcli.lookup("cookieDesc"),
-  manual: gcli.lookup("cookieManual")
-});
-
-/**
- * The template for the 'cookie list' command.
- */
-var cookieListHtml = "" +
-  "<table>" +
-  "  <tr>" +
-  "    <th>" + gcli.lookup("cookieListOutKey") + "</th>" +
-  "    <th>" + gcli.lookup("cookieListOutValue") + "</th>" +
-  "    <th>" + gcli.lookup("cookieListOutActions") + "</th>" +
-  "  </tr>" +
-  "  <tr foreach='cookie in ${cookies}'>" +
-  "    <td>${cookie.key}</td>" +
-  "    <td>${cookie.value}</td>" +
-  "    <td>" +
-  "      <span class='gcli-out-shortcut' onclick='${onclick}'" +
-  "          data-command='cookie set ${cookie.key} '" +
-  "          >" + gcli.lookup("cookieListOutEdit") + "</span>" +
-  "      <span class='gcli-out-shortcut'" +
-  "          onclick='${onclick}' ondblclick='${ondblclick}'" +
-  "          data-command='cookie remove ${cookie.key}'" +
-  "          >" + gcli.lookup("cookieListOutRemove") + "</span>" +
-  "    </td>" +
-  "  </tr>" +
-  "</table>" +
-  "";
-
-/**
- * 'cookie list' command
- */
-gcli.addCommand({
-  name: "cookie list",
-  description: gcli.lookup("cookieListDesc"),
-  manual: gcli.lookup("cookieListManual"),
-  returnType: "string",
-  exec: function Command_cookieList(args, context) {
-    // Parse out an array of { key:..., value:... } objects for each cookie
-    var doc = context.environment.contentDocument;
-    var cookies = doc.cookie.split("; ").map(function(cookieStr) {
-      var equalsPos = cookieStr.indexOf("=");
-      return {
-        key: cookieStr.substring(0, equalsPos),
-        value: cookieStr.substring(equalsPos + 1)
-      };
-    });
-
-    return context.createView({
-      html: cookieListHtml,
-      data: {
-        cookies: cookies,
-        onclick: createUpdateHandler(context),
-        ondblclick: createExecuteHandler(context),
-      }
-    });
-  }
-});
-
-/**
- * 'cookie remove' command
- */
-gcli.addCommand({
-  name: "cookie remove",
-  description: gcli.lookup("cookieRemoveDesc"),
-  manual: gcli.lookup("cookieRemoveManual"),
-  params: [
-    {
-      name: "key",
-      type: "string",
-      description: gcli.lookup("cookieRemoveKeyDesc"),
-    }
-  ],
-  exec: function Command_cookieRemove(args, context) {
-    let document = context.environment.contentDocument;
-    let expDate = new Date();
-    expDate.setDate(expDate.getDate() - 1);
-    document.cookie = escape(args.key) + "=; expires=" + expDate.toGMTString();
-  }
-});
-
-/**
- * 'cookie set' command
- */
-gcli.addCommand({
-  name: "cookie set",
-  description: gcli.lookup("cookieSetDesc"),
-  manual: gcli.lookup("cookieSetManual"),
-  params: [
-    {
-      name: "key",
-      type: "string",
-      description: gcli.lookup("cookieSetKeyDesc")
-    },
-    {
-      name: "value",
-      type: "string",
-      description: gcli.lookup("cookieSetValueDesc")
-    },
-    {
-      group: gcli.lookup("cookieSetOptionsDesc"),
-      params: [
-        {
-          name: "path",
-          type: "string",
-          defaultValue: "/",
-          description: gcli.lookup("cookieSetPathDesc")
-        },
-        {
-          name: "domain",
-          type: "string",
-          defaultValue: null,
-          description: gcli.lookup("cookieSetDomainDesc")
-        },
-        {
-          name: "secure",
-          type: "boolean",
-          description: gcli.lookup("cookieSetSecureDesc")
-        }
-      ]
-    }
-  ],
-  exec: function Command_cookieSet(args, context) {
-    let document = context.environment.contentDocument;
-
-    document.cookie = escape(args.key) + "=" + escape(args.value) +
-            (args.domain ? "; domain=" + args.domain : "") +
-            (args.path ? "; path=" + args.path : "") +
-            (args.secure ? "; secure" : ""); 
-  }
-});
-
-/**
- * Helper to find the 'data-command' attribute and call some action on it.
- * @see |updateCommand()| and |executeCommand()|
- */
-function withCommand(element, action) {
-  var command = element.getAttribute("data-command");
-  if (!command) {
-    command = element.querySelector("*[data-command]")
-            .getAttribute("data-command");
-  }
-
-  if (command) {
-    action(command);
-  }
-  else {
-    console.warn("Missing data-command for " + util.findCssSelector(element));
-  }
-}
-
-/**
- * Create a handler to update the requisition to contain the text held in the
- * first matching data-command attribute under the currentTarget of the event.
- * @param context Either a Requisition or an ExecutionContext or another object
- * that contains an |update()| function that follows a similar contract.
- */
-function createUpdateHandler(context) {
-  return function(ev) {
-    withCommand(ev.currentTarget, function(command) {
-      context.update(command);
-    });
-  }
-}
-
-/**
- * Create a handler to execute the text held in the data-command attribute
- * under the currentTarget of the event.
- * @param context Either a Requisition or an ExecutionContext or another object
- * that contains an |update()| function that follows a similar contract.
- */
-function createExecuteHandler(context) {
-  return function(ev) {
-    withCommand(ev.currentTarget, function(command) {
-      context.exec({
-        visible: true,
-        typed: command
-      });
-    });
-  }
-}
deleted file mode 100644
--- a/browser/devtools/commandline/CmdDbg.jsm
+++ /dev/null
@@ -1,176 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-this.EXPORTED_SYMBOLS = [ ];
-
-Cu.import("resource:///modules/devtools/gcli.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
-                                  "resource:///modules/devtools/gDevTools.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
-                                  "resource:///modules/devtools/Target.jsm");
-
-/**
- * 'dbg' command
- */
-gcli.addCommand({
-  name: "dbg",
-  description: gcli.lookup("dbgDesc"),
-  manual: gcli.lookup("dbgManual")
-});
-
-/**
- * 'dbg open' command
- */
-gcli.addCommand({
-  name: "dbg open",
-  description: gcli.lookup("dbgOpen"),
-  params: [],
-  exec: function (args, context) {
-    let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
-    let target = TargetFactory.forTab(gBrowser.selectedTab);
-    return gDevTools.showToolbox(target, "jsdebugger");
-  }
-});
-
-/**
- * 'dbg close' command
- */
-gcli.addCommand({
-  name: "dbg close",
-  description: gcli.lookup("dbgClose"),
-  params: [],
-  exec: function (args, context) {
-    let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
-    let target = TargetFactory.forTab(gBrowser.selectedTab);
-    return gDevTools.closeToolbox(target);
-  }
-});
-
-/**
- * 'dbg interrupt' command
- */
-gcli.addCommand({
-  name: "dbg interrupt",
-  description: gcli.lookup("dbgInterrupt"),
-  params: [],
-  exec: function(args, context) {
-    let dbg = getPanel(context, "jsdebugger");
-    if (!dbg) {
-      return gcli.lookup("debuggerStopped");
-    }
-
-    let controller = dbg._controller;
-    let thread = controller.activeThread;
-    if (!thread.paused) {
-      thread.interrupt();
-    }
-  }
-});
-
-/**
- * 'dbg continue' command
- */
-gcli.addCommand({
-  name: "dbg continue",
-  description: gcli.lookup("dbgContinue"),
-  params: [],
-  exec: function(args, context) {
-    let dbg = getPanel(context, "jsdebugger");
-    if (!dbg) {
-      return gcli.lookup("debuggerStopped");
-    }
-
-    let controller = dbg._controller;
-    let thread = controller.activeThread;
-    if (thread.paused) {
-      thread.resume();
-    }
-  }
-});
-
-/**
- * 'dbg step' command
- */
-gcli.addCommand({
-  name: "dbg step",
-  description: gcli.lookup("dbgStepDesc"),
-  manual: gcli.lookup("dbgStepManual")
-});
-
-/**
- * 'dbg step over' command
- */
-gcli.addCommand({
-  name: "dbg step over",
-  description: gcli.lookup("dbgStepOverDesc"),
-  params: [],
-  exec: function(args, context) {
-    let dbg = getPanel(context, "jsdebugger");
-    if (!dbg) {
-      return gcli.lookup("debuggerStopped");
-    }
-
-    let controller = dbg._controller;
-    let thread = controller.activeThread;
-    if (thread.paused) {
-      thread.stepOver();
-    }
-  }
-});
-
-/**
- * 'dbg step in' command
- */
-gcli.addCommand({
-  name: 'dbg step in',
-  description: gcli.lookup("dbgStepInDesc"),
-  params: [],
-  exec: function(args, context) {
-    let dbg = getPanel(context, "jsdebugger");
-    if (!dbg) {
-      return gcli.lookup("debuggerStopped");
-    }
-
-    let controller = dbg._controller;
-    let thread = controller.activeThread;
-    if (thread.paused) {
-      thread.stepIn();
-    }
-  }
-});
-
-/**
- * 'dbg step over' command
- */
-gcli.addCommand({
-  name: 'dbg step out',
-  description: gcli.lookup("dbgStepOutDesc"),
-  params: [],
-  exec: function(args, context) {
-    let dbg = getPanel(context, "jsdebugger");
-    if (!dbg) {
-      return gcli.lookup("debuggerStopped");
-    }
-
-    let controller = dbg._controller;
-    let thread = controller.activeThread;
-    if (thread.paused) {
-      thread.stepOut();
-    }
-  }
-});
-
-/**
- * A helper to go from a command context to a debugger panel
- */
-function getPanel(context, id) {
-  let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
-  let target = TargetFactory.forTab(gBrowser.selectedTab);
-  let toolbox = gDevTools.getToolbox(target);
-  return toolbox == null ? undefined : toolbox.getPanel(id);
-}
deleted file mode 100644
--- a/browser/devtools/commandline/CmdEcho.jsm
+++ /dev/null
@@ -1,29 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-this.EXPORTED_SYMBOLS = [ ];
-
-Cu.import("resource:///modules/devtools/gcli.jsm");
-
-/**
- * 'echo' command
- */
-gcli.addCommand({
-  name: "echo",
-  description: gcli.lookup("echoDesc"),
-  params: [
-    {
-      name: "message",
-      type: "string",
-      description: gcli.lookup("echoMessageDesc")
-    }
-  ],
-  returnType: "string",
-  hidden: true,
-  exec: function Command_echo(args, context) {
-    return args.message;
-  }
-});
deleted file mode 100644
--- a/browser/devtools/commandline/CmdExport.jsm
+++ /dev/null
@@ -1,32 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-this.EXPORTED_SYMBOLS = [ ];
-
-Cu.import("resource:///modules/devtools/gcli.jsm");
-
-/**
- * 'export' command
- */
-gcli.addCommand({
-  name: "export",
-  description: gcli.lookup("exportDesc"),
-});
-
-/**
- * The 'export html' command. This command allows the user to export the page to
- * HTML after they do DOM changes.
- */
-gcli.addCommand({
-  name: "export html",
-  description: gcli.lookup("exportHtmlDesc"),
-  exec: function(args, context) {
-    let document = context.environment.contentDocument;
-    let window = document.defaultView;
-    let page = document.documentElement.outerHTML;
-    window.open('data:text/plain;charset=utf8,' + encodeURIComponent(page));
-  }
-});
deleted file mode 100644
--- a/browser/devtools/commandline/CmdJsb.jsm
+++ /dev/null
@@ -1,138 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-const XMLHttpRequest =
-  Components.Constructor("@mozilla.org/xmlextras/xmlhttprequest;1");
-
-this.EXPORTED_SYMBOLS = [ ];
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource:///modules/devtools/gcli.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "js_beautify",
-                                  "resource:///modules/devtools/Jsbeautify.jsm");
-
-/**
- * jsb command.
- */
-gcli.addCommand({
-  name: 'jsb',
-  description: gcli.lookup('jsbDesc'),
-  returnValue:'string',
-  params: [
-    {
-      name: 'url',
-      type: 'string',
-      description: gcli.lookup('jsbUrlDesc')
-    },
-    {
-      group: gcli.lookup("jsbOptionsDesc"),
-      params: [
-        {
-          name: 'indentSize',
-          type: 'number',
-          description: gcli.lookup('jsbIndentSizeDesc'),
-          manual: gcli.lookup('jsbIndentSizeManual'),
-          defaultValue: 2
-        },
-        {
-          name: 'indentChar',
-          type: {
-            name: 'selection',
-            lookup: [
-              { name: "space", value: " " },
-              { name: "tab", value: "\t" }
-            ]
-          },
-          description: gcli.lookup('jsbIndentCharDesc'),
-          manual: gcli.lookup('jsbIndentCharManual'),
-          defaultValue: ' ',
-        },
-        {
-          name: 'doNotPreserveNewlines',
-          type: 'boolean',
-          description: gcli.lookup('jsbDoNotPreserveNewlinesDesc')
-        },
-        {
-          name: 'preserveMaxNewlines',
-          type: 'number',
-          description: gcli.lookup('jsbPreserveMaxNewlinesDesc'),
-          manual: gcli.lookup('jsbPreserveMaxNewlinesManual'),
-          defaultValue: -1
-        },
-        {
-          name: 'jslintHappy',
-          type: 'boolean',
-          description: gcli.lookup('jsbJslintHappyDesc'),
-          manual: gcli.lookup('jsbJslintHappyManual')
-        },
-        {
-          name: 'braceStyle',
-          type: {
-            name: 'selection',
-            data: ['collapse', 'expand', 'end-expand', 'expand-strict']
-          },
-          description: gcli.lookup('jsbBraceStyleDesc'),
-          manual: gcli.lookup('jsbBraceStyleManual'),
-          defaultValue: "collapse"
-        },
-        {
-          name: 'noSpaceBeforeConditional',
-          type: 'boolean',
-          description: gcli.lookup('jsbNoSpaceBeforeConditionalDesc')
-        },
-        {
-          name: 'unescapeStrings',
-          type: 'boolean',
-          description: gcli.lookup('jsbUnescapeStringsDesc'),
-          manual: gcli.lookup('jsbUnescapeStringsManual')
-        }
-      ]
-    }
-  ],
-  exec: function(args, context) {
-    let opts = {
-      indent_size: args.indentSize,
-      indent_char: args.indentChar,
-      preserve_newlines: !args.doNotPreserveNewlines,
-      max_preserve_newlines: args.preserveMaxNewlines == -1 ?
-                             undefined : args.preserveMaxNewlines,
-      jslint_happy: args.jslintHappy,
-      brace_style: args.braceStyle,
-      space_before_conditional: !args.noSpaceBeforeConditional,
-      unescape_strings: args.unescapeStrings
-    };
-
-    let xhr = new XMLHttpRequest();
-
-    try {
-      xhr.open("GET", args.url, true);
-    } catch(e) {
-      return gcli.lookup('jsbInvalidURL');
-    }
-
-    let promise = context.createPromise();
-
-    xhr.onreadystatechange = function(aEvt) {
-      if (xhr.readyState == 4) {
-        if (xhr.status == 200 || xhr.status == 0) {
-          let browserDoc = context.environment.chromeDocument;
-          let browserWindow = browserDoc.defaultView;
-          let gBrowser = browserWindow.gBrowser;
-          let result = js_beautify(xhr.responseText, opts);
-
-          browserWindow.Scratchpad.ScratchpadManager.openScratchpad({text: result});
-
-          promise.resolve();
-        } else {
-          promise.resolve("Unable to load page to beautify: " + args.url + " " +
-                          xhr.status + " " + xhr.statusText);
-        }
-      };
-    }
-    xhr.send(null);
-    return promise;
-  }
-});
deleted file mode 100644
--- a/browser/devtools/commandline/CmdPagemod.jsm
+++ /dev/null
@@ -1,264 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-this.EXPORTED_SYMBOLS = [ ];
-
-Cu.import("resource:///modules/devtools/gcli.jsm");
-
-/**
- * 'pagemod' command
- */
-gcli.addCommand({
-  name: "pagemod",
-  description: gcli.lookup("pagemodDesc"),
-});
-
-/**
- * The 'pagemod replace' command. This command allows the user to search and
- * replace within text nodes and attributes.
- */
-gcli.addCommand({
-  name: "pagemod replace",
-  description: gcli.lookup("pagemodReplaceDesc"),
-  params: [
-    {
-      name: "search",
-      type: "string",
-      description: gcli.lookup("pagemodReplaceSearchDesc"),
-    },
-    {
-      name: "replace",
-      type: "string",
-      description: gcli.lookup("pagemodReplaceReplaceDesc"),
-    },
-    {
-      name: "ignoreCase",
-      type: "boolean",
-      description: gcli.lookup("pagemodReplaceIgnoreCaseDesc"),
-    },
-    {
-      name: "selector",
-      type: "string",
-      description: gcli.lookup("pagemodReplaceSelectorDesc"),
-      defaultValue: "*:not(script):not(style):not(embed):not(object):not(frame):not(iframe):not(frameset)",
-    },
-    {
-      name: "root",
-      type: "node",
-      description: gcli.lookup("pagemodReplaceRootDesc"),
-      defaultValue: null,
-    },
-    {
-      name: "attrOnly",
-      type: "boolean",
-      description: gcli.lookup("pagemodReplaceAttrOnlyDesc"),
-    },
-    {
-      name: "contentOnly",
-      type: "boolean",
-      description: gcli.lookup("pagemodReplaceContentOnlyDesc"),
-    },
-    {
-      name: "attributes",
-      type: "string",
-      description: gcli.lookup("pagemodReplaceAttributesDesc"),
-      defaultValue: null,
-    },
-  ],
-  exec: function(args, context) {
-    let document = context.environment.contentDocument;
-    let searchTextNodes = !args.attrOnly;
-    let searchAttributes = !args.contentOnly;
-    let regexOptions = args.ignoreCase ? 'ig' : 'g';
-    let search = new RegExp(escapeRegex(args.search), regexOptions);
-    let attributeRegex = null;
-    if (args.attributes) {
-      attributeRegex = new RegExp(args.attributes, regexOptions);
-    }
-
-    let root = args.root || document;
-    let elements = root.querySelectorAll(args.selector);
-    elements = Array.prototype.slice.call(elements);
-
-    let replacedTextNodes = 0;
-    let replacedAttributes = 0;
-
-    function replaceAttribute() {
-      replacedAttributes++;
-      return args.replace;
-    }
-    function replaceTextNode() {
-      replacedTextNodes++;
-      return args.replace;
-    }
-
-    for (let i = 0; i < elements.length; i++) {
-      let element = elements[i];
-      if (searchTextNodes) {
-        for (let y = 0; y < element.childNodes.length; y++) {
-          let node = element.childNodes[y];
-          if (node.nodeType == node.TEXT_NODE) {
-            node.textContent = node.textContent.replace(search, replaceTextNode);
-          }
-        }
-      }
-
-      if (searchAttributes) {
-        if (!element.attributes) {
-          continue;
-        }
-        for (let y = 0; y < element.attributes.length; y++) {
-          let attr = element.attributes[y];
-          if (!attributeRegex || attributeRegex.test(attr.name)) {
-            attr.value = attr.value.replace(search, replaceAttribute);
-          }
-        }
-      }
-    }
-
-    return gcli.lookupFormat("pagemodReplaceResult",
-                             [elements.length, replacedTextNodes,
-                              replacedAttributes]);
-  }
-});
-
-/**
- * 'pagemod remove' command
- */
-gcli.addCommand({
-  name: "pagemod remove",
-  description: gcli.lookup("pagemodRemoveDesc"),
-});
-
-
-/**
- * The 'pagemod remove element' command.
- */
-gcli.addCommand({
-  name: "pagemod remove element",
-  description: gcli.lookup("pagemodRemoveElementDesc"),
-  params: [
-    {
-      name: "search",
-      type: "string",
-      description: gcli.lookup("pagemodRemoveElementSearchDesc"),
-    },
-    {
-      name: "root",
-      type: "node",
-      description: gcli.lookup("pagemodRemoveElementRootDesc"),
-      defaultValue: null,
-    },
-    {
-      name: 'stripOnly',
-      type: 'boolean',
-      description: gcli.lookup("pagemodRemoveElementStripOnlyDesc"),
-    },
-    {
-      name: 'ifEmptyOnly',
-      type: 'boolean',
-      description: gcli.lookup("pagemodRemoveElementIfEmptyOnlyDesc"),
-    },
-  ],
-  exec: function(args, context) {
-    let document = context.environment.contentDocument;
-    let root = args.root || document;
-    let elements = Array.prototype.slice.call(root.querySelectorAll(args.search));
-
-    let removed = 0;
-    for (let i = 0; i < elements.length; i++) {
-      let element = elements[i];
-      let parentNode = element.parentNode;
-      if (!parentNode || !element.removeChild) {
-        continue;
-      }
-      if (args.stripOnly) {
-        while (element.hasChildNodes()) {
-          parentNode.insertBefore(element.childNodes[0], element);
-        }
-      }
-      if (!args.ifEmptyOnly || !element.hasChildNodes()) {
-        element.parentNode.removeChild(element);
-        removed++;
-      }
-    }
-
-    return gcli.lookupFormat("pagemodRemoveElementResultMatchedAndRemovedElements",
-                             [elements.length, removed]);
-  }
-});
-
-/**
- * The 'pagemod remove attribute' command.
- */
-gcli.addCommand({
-  name: "pagemod remove attribute",
-  description: gcli.lookup("pagemodRemoveAttributeDesc"),
-  params: [
-    {
-      name: "searchAttributes",
-      type: "string",
-      description: gcli.lookup("pagemodRemoveAttributeSearchAttributesDesc"),
-    },
-    {
-      name: "searchElements",
-      type: "string",
-      description: gcli.lookup("pagemodRemoveAttributeSearchElementsDesc"),
-    },
-    {
-      name: "root",
-      type: "node",
-      description: gcli.lookup("pagemodRemoveAttributeRootDesc"),
-      defaultValue: null,
-    },
-    {
-      name: "ignoreCase",
-      type: "boolean",
-      description: gcli.lookup("pagemodRemoveAttributeIgnoreCaseDesc"),
-    },
-  ],
-  exec: function(args, context) {
-    let document = context.environment.contentDocument;
-
-    let root = args.root || document;
-    let regexOptions = args.ignoreCase ? 'ig' : 'g';
-    let attributeRegex = new RegExp(args.searchAttributes, regexOptions);
-    let elements = root.querySelectorAll(args.searchElements);
-    elements = Array.prototype.slice.call(elements);
-
-    let removed = 0;
-    for (let i = 0; i < elements.length; i++) {
-      let element = elements[i];
-      if (!element.attributes) {
-        continue;
-      }
-
-      var attrs = Array.prototype.slice.call(element.attributes);
-      for (let y = 0; y < attrs.length; y++) {
-        let attr = attrs[y];
-        if (attributeRegex.test(attr.name)) {
-          element.removeAttribute(attr.name);
-          removed++;
-        }
-      }
-    }
-
-    return gcli.lookupFormat("pagemodRemoveAttributeResult",
-                             [elements.length, removed]);
-  }
-});
-
-/**
- * Make a given string safe to use  in a regular expression.
- *
- * @param string aString
- *        The string you want to use in a regex.
- * @return string
- *         The equivalent of |aString| but safe to use in a regex.
- */
-function escapeRegex(aString) {
-  return aString.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
-}
deleted file mode 100644
--- a/browser/devtools/commandline/CmdRestart.jsm
+++ /dev/null
@@ -1,54 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-this.EXPORTED_SYMBOLS = [ ];
-
-Cu.import("resource:///modules/devtools/gcli.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-/**
- * Restart command
- *
- * @param boolean nocache
- *        Disables loading content from cache upon restart.
- *
- * Examples :
- * >> restart
- * - restarts browser immediately
- * >> restart --nocache
- * - restarts immediately and starts Firefox without using cache
- */
-gcli.addCommand({
-  name: "restart",
-  description: gcli.lookup("restartFirefoxDesc"),
-  params: [
-    {
-      name: "nocache",
-      type: "boolean",
-      description: gcli.lookup("restartFirefoxNocacheDesc")
-    }
-  ],
-  returnType: "string",
-  exec: function Restart(args, context) {
-    let canceled = Cc["@mozilla.org/supports-PRBool;1"]
-                     .createInstance(Ci.nsISupportsPRBool);
-    Services.obs.notifyObservers(canceled, "quit-application-requested", "restart");
-    if (canceled.data) {
-      return gcli.lookup("restartFirefoxRequestCancelled");
-    }
-
-    // disable loading content from cache.
-    if (args.nocache) {
-      Services.appinfo.invalidateCachesOnRestart();
-    }
-
-    // restart
-    Cc['@mozilla.org/toolkit/app-startup;1']
-      .getService(Ci.nsIAppStartup)
-      .quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
-    return gcli.lookup("restartFirefoxRestarting");
-  }
-});
deleted file mode 100644
--- a/browser/devtools/commandline/CmdScreenshot.jsm
+++ /dev/null
@@ -1,238 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-this.EXPORTED_SYMBOLS = [ ];
-
-Cu.import("resource:///modules/devtools/gcli.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "LayoutHelpers",
-                                  "resource:///modules/devtools/LayoutHelpers.jsm");
-
-// String used as an indication to generate default file name in the following
-// format: "Screen Shot yyyy-mm-dd at HH.MM.SS.png"
-const FILENAME_DEFAULT_VALUE = " ";
-
-/**
- * 'screenshot' command
- */
-gcli.addCommand({
-  name: "screenshot",
-  description: gcli.lookup("screenshotDesc"),
-  manual: gcli.lookup("screenshotManual"),
-  returnType: "html",
-  params: [
-    {
-      name: "filename",
-      type: "string",
-      defaultValue: FILENAME_DEFAULT_VALUE,
-      description: gcli.lookup("screenshotFilenameDesc"),
-      manual: gcli.lookup("screenshotFilenameManual")
-    },
-    {
-      group: gcli.lookup("screenshotGroupOptions"),
-      params: [
-        {
-          name: "clipboard",
-          type: "boolean",
-          description: gcli.lookup("screenshotClipboardDesc"),
-          manual: gcli.lookup("screenshotClipboardManual")
-        },
-        {
-          name: "chrome",
-          type: "boolean",
-          description: gcli.lookup("screenshotChromeDesc"),
-          manual: gcli.lookup("screenshotChromeManual")
-        },
-        {
-          name: "delay",
-          type: { name: "number", min: 0 },
-          defaultValue: 0,
-          description: gcli.lookup("screenshotDelayDesc"),
-          manual: gcli.lookup("screenshotDelayManual")
-        },
-        {
-          name: "fullpage",
-          type: "boolean",
-          description: gcli.lookup("screenshotFullPageDesc"),
-          manual: gcli.lookup("screenshotFullPageManual")
-        },
-        {
-          name: "selector",
-          type: "node",
-          defaultValue: null,
-          description: gcli.lookup("inspectNodeDesc"),
-          manual: gcli.lookup("inspectNodeManual")
-        }
-      ]
-    }
-  ],
-  exec: function Command_screenshot(args, context) {
-    if (args.chrome && args.selector) {
-      // Node screenshot with chrome option does not work as inteded
-      // Refer https://bugzilla.mozilla.org/show_bug.cgi?id=659268#c7
-      // throwing for now.
-      throw new Error(gcli.lookup("screenshotSelectorChromeConflict"));
-    }
-    var document = args.chrome? context.environment.chromeDocument
-                              : context.environment.contentDocument;
-    if (args.delay > 0) {
-      var promise = context.createPromise();
-      document.defaultView.setTimeout(function Command_screenshotDelay() {
-        let reply = this.grabScreen(document, args.filename, args.clipboard,
-                                    args.fullpage);
-        promise.resolve(reply);
-      }.bind(this), args.delay * 1000);
-      return promise;
-    }
-    else {
-      return this.grabScreen(document, args.filename, args.clipboard,
-                             args.fullpage, args.selector);
-    }
-  },
-  grabScreen:
-  function Command_screenshotGrabScreen(document, filename, clipboard,
-                                        fullpage, node) {
-    let window = document.defaultView;
-    let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
-    let left = 0;
-    let top = 0;
-    let width;
-    let height;
-    let div = document.createElementNS("http://www.w3.org/1999/xhtml", "div");
-
-    if (!fullpage) {
-      if (!node) {
-        left = window.scrollX;
-        top = window.scrollY;
-        width = window.innerWidth;
-        height = window.innerHeight;
-      } else {
-        let rect = LayoutHelpers.getRect(node, window);
-        top = rect.top;
-        left = rect.left;
-        width = rect.width;
-        height = rect.height;
-      }
-    } else {
-      width = window.innerWidth + window.scrollMaxX;
-      height = window.innerHeight + window.scrollMaxY;
-    }
-    canvas.width = width;
-    canvas.height = height;
-
-    let ctx = canvas.getContext("2d");
-    ctx.drawWindow(window, left, top, width, height, "#fff");
-    let data = canvas.toDataURL("image/png", "");
-
-    let loadContext = document.defaultView
-                              .QueryInterface(Ci.nsIInterfaceRequestor)
-                              .getInterface(Ci.nsIWebNavigation)
-                              .QueryInterface(Ci.nsILoadContext);
-
-    try {
-      if (clipboard) {
-        let io = Cc["@mozilla.org/network/io-service;1"]
-                   .getService(Ci.nsIIOService);
-        let channel = io.newChannel(data, null, null);
-        let input = channel.open();
-        let imgTools = Cc["@mozilla.org/image/tools;1"]
-                         .getService(Ci.imgITools);
-
-        let container = {};
-        imgTools.decodeImageData(input, channel.contentType, container);
-
-        let wrapped = Cc["@mozilla.org/supports-interface-pointer;1"]
-                        .createInstance(Ci.nsISupportsInterfacePointer);
-        wrapped.data = container.value;
-
-        let trans = Cc["@mozilla.org/widget/transferable;1"]
-                      .createInstance(Ci.nsITransferable);
-        trans.init(loadContext);
-        trans.addDataFlavor(channel.contentType);
-        trans.setTransferData(channel.contentType, wrapped, -1);
-
-        let clipid = Ci.nsIClipboard;
-        let clip = Cc["@mozilla.org/widget/clipboard;1"].getService(clipid);
-        clip.setData(trans, null, clipid.kGlobalClipboard);
-        div.textContent = gcli.lookup("screenshotCopied");
-        return div;
-      }
-    }
-    catch (ex) {
-      div.textContent = gcli.lookup("screenshotErrorCopying");
-      return div;
-    }
-
-    let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
-
-    // Create a name for the file if not present
-    if (filename == FILENAME_DEFAULT_VALUE) {
-      let date = new Date();
-      let dateString = date.getFullYear() + "-" + (date.getMonth() + 1) +
-                       "-" + date.getDate();
-      dateString = dateString.split("-").map(function(part) {
-        if (part.length == 1) {
-          part = "0" + part;
-        }
-        return part;
-      }).join("-");
-      let timeString = date.toTimeString().replace(/:/g, ".").split(" ")[0];
-      filename = gcli.lookupFormat("screenshotGeneratedFilename",
-                                   [dateString, timeString]) + ".png";
-    }
-    // Check there is a .png extension to filename
-    else if (!filename.match(/.png$/i)) {
-      filename += ".png";
-    }
-
-    // If the filename is relative, tack it onto the download directory
-    if (!filename.match(/[\\\/]/)) {
-      let downloadMgr = Cc["@mozilla.org/download-manager;1"]
-                          .getService(Ci.nsIDownloadManager);
-      let tempfile = downloadMgr.userDownloadsDirectory;
-      tempfile.append(filename);
-      filename = tempfile.path;
-    }
-
-    try {
-      file.initWithPath(filename);
-    } catch (ex) {
-      div.textContent = gcli.lookup("screenshotErrorSavingToFile") + " " + filename;
-      return div;
-    }
-
-    let ioService = Cc["@mozilla.org/network/io-service;1"]
-                      .getService(Ci.nsIIOService);
-
-    let Persist = Ci.nsIWebBrowserPersist;
-    let persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
-                    .createInstance(Persist);
-    persist.persistFlags = Persist.PERSIST_FLAGS_REPLACE_EXISTING_FILES |
-                           Persist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
-
-    let source = ioService.newURI(data, "UTF8", null);
-    persist.saveURI(source, null, null, null, null, file, loadContext);
-
-    div.textContent = gcli.lookup("screenshotSavedToFile") + " \"" + filename +
-                      "\"";
-    div.addEventListener("click", function openFile() {
-      div.removeEventListener("click", openFile);
-      file.reveal();
-    });
-    div.style.cursor = "pointer";
-    let image = document.createElement("div");
-    let previewHeight = parseInt(256*height/width);
-    image.setAttribute("style",
-                       "width:256px; height:" + previewHeight + "px;" +
-                       "max-height: 256px;" +
-                       "background-image: url('" + data + "');" +
-                       "background-size: 256px " + previewHeight + "px;" +
-                       "margin: 4px; display: block");
-    div.appendChild(image);
-    return div;
-  }
-});
\ No newline at end of file
--- a/browser/devtools/commandline/Commands.jsm
+++ b/browser/devtools/commandline/Commands.jsm
@@ -2,26 +2,14 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 this.EXPORTED_SYMBOLS = [ ];
 
 const Cu = Components.utils;
 
-Cu.import("resource:///modules/devtools/CmdAddon.jsm");
-Cu.import("resource:///modules/devtools/CmdBreak.jsm");
-Cu.import("resource:///modules/devtools/CmdCalllog.jsm");
-Cu.import("resource:///modules/devtools/CmdCalllogChrome.jsm");
-Cu.import("resource:///modules/devtools/CmdConsole.jsm");
-Cu.import("resource:///modules/devtools/CmdCookie.jsm");
-Cu.import("resource:///modules/devtools/CmdDbg.jsm");
-Cu.import("resource:///modules/devtools/CmdEcho.jsm");
+Cu.import("resource:///modules/devtools/BuiltinCommands.jsm");
 Cu.import("resource:///modules/devtools/CmdEdit.jsm");
-Cu.import("resource:///modules/devtools/CmdExport.jsm");
 Cu.import("resource:///modules/devtools/CmdInspect.jsm");
-Cu.import("resource:///modules/devtools/CmdJsb.jsm");
-Cu.import("resource:///modules/devtools/CmdPagemod.jsm");
 Cu.import("resource:///modules/devtools/CmdResize.jsm");
-Cu.import("resource:///modules/devtools/CmdRestart.jsm");
-Cu.import("resource:///modules/devtools/CmdScreenshot.jsm");
 Cu.import("resource:///modules/devtools/CmdTilt.jsm");
 Cu.import("resource:///modules/devtools/CmdScratchpad.jsm");
--- a/browser/devtools/commandline/gcli.jsm
+++ b/browser/devtools/commandline/gcli.jsm
@@ -2431,77 +2431,85 @@ canon.Command = Command;
  * option switches
  */
 function Parameter(paramSpec, command, groupName) {
   this.command = command || { name: 'unnamed' };
   this.paramSpec = paramSpec;
   this.name = this.paramSpec.name;
   this.type = this.paramSpec.type;
   this.groupName = groupName;
-  this.defaultValue = this.paramSpec.defaultValue;
 
   if (!this.name) {
     throw new Error('In ' + this.command.name +
                     ': all params must have a name');
   }
 
   var typeSpec = this.type;
   this.type = types.getType(typeSpec);
   if (this.type == null) {
     console.error('Known types: ' + types.getTypeNames().join(', '));
     throw new Error('In ' + this.command.name + '/' + this.name +
                     ': can\'t find type for: ' + JSON.stringify(typeSpec));
   }
 
   // boolean parameters have an implicit defaultValue:false, which should
   // not be changed. See the docs.
-  if (this.type instanceof BooleanType) {
-    if (this.defaultValue !== undefined) {
-      throw new Error('In ' + this.command.name + '/' + this.name +
-                      ': boolean parameters can not have a defaultValue.' +
-                      ' Ignoring');
-    }
-    this.defaultValue = false;
+  if (this.type instanceof BooleanType &&
+      this.paramSpec.defaultValue !== undefined) {
+    throw new Error('In ' + this.command.name + '/' + this.name +
+                    ': boolean parameters can not have a defaultValue.' +
+                    ' Ignoring');
   }
 
   // Check the defaultValue for validity.
   // Both undefined and null get a pass on this test. undefined is used when
   // there is no defaultValue, and null is used when the parameter is
   // optional, neither are required to parse and stringify.
-  if (this.defaultValue != null) {
+  if (this._defaultValue != null) {
     try {
-      var defaultText = this.type.stringify(this.defaultValue);
+      var defaultText = this.type.stringify(this.paramSpec.defaultValue);
       var defaultConversion = this.type.parseString(defaultText);
       if (defaultConversion.getStatus() !== Status.VALID) {
         throw new Error('In ' + this.command.name + '/' + this.name +
                         ': Error round tripping defaultValue. status = ' +
                         defaultConversion.getStatus());
       }
     }
     catch (ex) {
       throw new Error('In ' + this.command.name + '/' + this.name +
                       ': ' + ex);
     }
   }
 
-  // Some types (boolean, array) have a non 'undefined' blank value. Give the
-  // type a chance to override the default defaultValue of undefined
-  if (this.defaultValue === undefined) {
-    this.defaultValue = this.type.getBlank().value;
-  }
-
   // All parameters that can only be set via a named parameter must have a
   // non-undefined default value
-  if (!this.isPositionalAllowed && this.defaultValue === undefined) {
+  if (!this.isPositionalAllowed && this.paramSpec.defaultValue === undefined &&
+      this.type.getBlank == null && !(this.type instanceof BooleanType)) {
     throw new Error('In ' + this.command.name + '/' + this.name +
                     ': Missing defaultValue for optional parameter.');
   }
 }
 
 /**
+ * type.getBlank can be expensive, so we delay execution where we can
+ */
+Object.defineProperty(Parameter.prototype, 'defaultValue', {
+  get: function() {
+    if (!('_defaultValue' in this)) {
+      this._defaultValue = (this.paramSpec.defaultValue !== undefined) ?
+          this.paramSpec.defaultValue :
+          this.type.getBlank().value;
+    }
+
+    return this._defaultValue;
+  },
+  enumerable : true
+});
+
+/**
  * Does the given name uniquely identify this param (among the other params
  * in this command)
  * @param name The name to check
  */
 Parameter.prototype.isKnownAs = function(name) {
   if (name === '--' + this.name) {
     return true;
   }
@@ -2684,34 +2692,27 @@ canon.getCommandSpecs = function getComm
  * Enable people to be notified of changes to the list of commands
  */
 canon.onCanonChange = util.createEvent('canon.onCanonChange');
 
 /**
  * CommandOutputManager stores the output objects generated by executed
  * commands.
  *
- * CommandOutputManager is exposed (via canon.commandOutputManager) to the the
- * outside world and could (but shouldn't) be used before gcli.startup() has
- * been called. This could should be defensive to that where possible, and we
- * should certainly document if the use of it or similar will fail if used too
- * soon.
+ * CommandOutputManager is exposed to the the outside world and could (but
+ * shouldn't) be used before gcli.startup() has been called.
+ * This could should be defensive to that where possible, and we should
+ * certainly document if the use of it or similar will fail if used too soon.
  */
 function CommandOutputManager() {
   this.onOutput = util.createEvent('CommandOutputManager.onOutput');
 }
 
 canon.CommandOutputManager = CommandOutputManager;
 
-/**
- * We maintain a global command output manager for the majority case where
- * there is only one important set of outputs.
- */
-canon.commandOutputManager = new CommandOutputManager();
-
 
 });
 /*
  * Copyright 2012, Mozilla Foundation and contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -2732,16 +2733,28 @@ define('gcli/util', ['require', 'exports
  */
 
 
 //------------------------------------------------------------------------------
 
 var eventDebug = false;
 
 /**
+ * Patch up broken console API from node
+ */
+if (eventDebug) {
+  if (console.group == null) {
+    console.group = function() { console.log(arguments); };
+  }
+  if (console.groupEnd == null) {
+    console.groupEnd = function() { console.log(arguments); };
+  }
+}
+
+/**
  * Useful way to create a name for a handler, used in createEvent()
  */
 function nameFunction(handler) {
   var scope = handler.scope ? handler.scope.constructor.name + '.' : '';
   var name = handler.func.name;
   if (name) {
     return scope + name;
   }
@@ -2812,36 +2825,44 @@ exports.createEvent = function(name) {
   };
 
   /**
    * Add a new handler function
    * @param func The function to call when this event is triggered
    * @param scope Optional 'this' object for the function call
    */
   event.add = function(func, scope) {
+    if (eventDebug) {
+      console.log('Adding listener to ' + name);
+    }
+
     handlers.push({ func: func, scope: scope });
   };
 
   /**
    * Remove a handler function added through add(). Both func and scope must
    * be strict equals (===) the values used in the call to add()
    * @param func The function to call when this event is triggered
    * @param scope Optional 'this' object for the function call
    */
   event.remove = function(func, scope) {
+    if (eventDebug) {
+      console.log('Removing listener from ' + name);
+    }
+
     var found = false;
     handlers = handlers.filter(function(test) {
-      var noMatch = (test.func !== func && test.scope !== scope);
-      if (!noMatch) {
+      var match = (test.func === func && test.scope === scope);
+      if (match) {
         found = true;
       }
-      return noMatch;
+      return !match;
     });
     if (!found) {
-      console.warn('Failed to remove handler from ' + name);
+      console.warn('Handler not found. Attached to ' + name);
     }
   };
 
   /**
    * Remove all handlers.
    * Reset the state of this event back to it's post create state
    */
   event.removeAll = function() {
@@ -4052,16 +4073,17 @@ exports.setDocument = function(document)
   }
 };
 
 /**
  * Undo the effects of setDocument()
  */
 exports.unsetDocument = function() {
   doc = undefined;
+  exports._empty = undefined;
 };
 
 /**
  * Getter for the document that contains the nodes we're matching
  * Most for changing things back to how they were for unit testing
  */
 exports.getDocument = function() {
   return doc;
@@ -4681,36 +4703,18 @@ imports.XPCOMUtils.defineLazyGetter(impo
   return Components.classes["@mozilla.org/supports-string;1"]
           .createInstance(Components.interfaces.nsISupportsString);
 });
 
 
 var util = require('gcli/util');
 var types = require('gcli/types');
 
-var allSettings = [];
-
-/**
- * Cache existing settings on startup
- */
-exports.startup = function() {
-  imports.prefBranch.getChildList('').forEach(function(name) {
-    allSettings.push(new Setting(name));
-  }.bind(this));
-  allSettings.sort(function(s1, s2) {
-    return s1.name.localeCompare(s2.name);
-  }.bind(this));
-};
-
-exports.shutdown = function() {
-  allSettings = [];
-};
-
-/**
- *
+/**
+ * All local settings have this prefix when used in Firefox
  */
 var DEVTOOLS_PREFIX = 'devtools.gcli.';
 
 /**
  * A class to wrap up the properties of a preference.
  * @see toolkit/components/viewconfig/content/config.js
  */
 function Setting(prefSpec) {
@@ -4819,73 +4823,146 @@ Object.defineProperty(Setting.prototype,
 /**
  * Reset this setting to it's initial default value
  */
 Setting.prototype.setDefault = function() {
   imports.prefBranch.clearUserPref(this.name);
   Services.prefs.savePrefFile(null);
 };
 
-/**
- * 'static' function to get an array containing all known Settings
+
+/**
+ * Collection of preferences for sorted access
+ */
+var settingsAll = [];
+
+/**
+ * Collection of preferences for fast indexed access
+ */
+var settingsMap = new Map();
+
+/**
+ * Flag so we know if we've read the system preferences
+ */
+var hasReadSystem = false;
+
+/**
+ * Clear out all preferences and return to initial state
+ */
+function reset() {
+  settingsMap = new Map();
+  settingsAll = [];
+  hasReadSystem = false;
+}
+
+/**
+ * Reset everything on startup and shutdown because we're doing lazy loading
+ */
+exports.startup = function() {
+  reset();
+};
+
+exports.shutdown = function() {
+  reset();
+};
+
+/**
+ * Load system prefs if they've not been loaded already
+ * @return true
+ */
+function readSystem() {
+  if (hasReadSystem) {
+    return;
+  }
+
+  imports.prefBranch.getChildList('').forEach(function(name) {
+    var setting = new Setting(name);
+    settingsAll.push(setting);
+    settingsMap.set(name, setting);
+  });
+
+  settingsAll.sort(function(s1, s2) {
+    return s1.name.localeCompare(s2.name);
+  });
+
+  hasReadSystem = true;
+}
+
+/**
+ * Get an array containing all known Settings filtered to match the given
+ * filter (string) at any point in the name of the setting
  */
 exports.getAll = function(filter) {
+  readSystem();
+
   if (filter == null) {
-    return allSettings;
-  }
-  return allSettings.filter(function(setting) {
+    return settingsAll;
+  }
+
+  return settingsAll.filter(function(setting) {
     return setting.name.indexOf(filter) !== -1;
   });
 };
 
 /**
  * Add a new setting.
  */
 exports.addSetting = function(prefSpec) {
   var setting = new Setting(prefSpec);
-  for (var i = 0; i < allSettings.length; i++) {
-    if (allSettings[i].name === setting.name) {
-      allSettings[i] = setting;
-    }
-  }
+
+  if (settingsMap.has(setting.name)) {
+    // Once exists already, we're going to need to replace it in the array
+    for (var i = 0; i < settingsAll.length; i++) {
+      if (settingsAll[i].name === setting.name) {
+        settingsAll[i] = setting;
+      }
+    }
+  }
+
+  settingsMap.set(setting.name, setting);
   exports.onChange({ added: setting.name });
+
   return setting;
 };
 
 /**
  * Getter for an existing setting. Generally use of this function should be
  * avoided. Systems that define a setting should export it if they wish it to
  * be available to the outside, or not otherwise. Use of this function breaks
  * that boundary and also hides dependencies. Acceptable uses include testing
  * and embedded uses of GCLI that pre-define all settings (e.g. Firefox)
  * @param name The name of the setting to fetch
  * @return The found Setting object, or undefined if the setting was not found
  */
 exports.getSetting = function(name) {
-  var found = undefined;
-  allSettings.some(function(setting) {
-    if (setting.name === name) {
-      found = setting;
-      return true;
-    }
-    return false;
-  });
-  return found;
+  // We might be able to give the answer without needing to read all system
+  // settings if this is an internal setting
+  var found = settingsMap.get(name);
+  if (found) {
+    return found;
+  }
+
+  if (hasReadSystem) {
+    return undefined;
+  }
+  else {
+    readSystem();
+    return settingsMap.get(name);
+  }
 };
 
 /**
  * Event for use to detect when the list of settings changes
  */
 exports.onChange = util.createEvent('Settings.onChange');
 
 /**
  * Remove a setting. A no-op in this case
  */
-exports.removeSetting = function(nameOrSpec) {
-};
+exports.removeSetting = function() { };
 
 
 });
 /*
  * Copyright 2012, Mozilla Foundation and contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -5104,16 +5181,17 @@ define('gcli/cli', ['require', 'exports'
 
 
 var util = require('gcli/util');
 var view = require('gcli/ui/view');
 var l10n = require('gcli/l10n');
 
 var canon = require('gcli/canon');
 var Q = require('gcli/promise');
+var CommandOutputManager = require('gcli/canon').CommandOutputManager;
 
 var Status = require('gcli/types').Status;
 var Conversion = require('gcli/types').Conversion;
 var ArrayType = require('gcli/types/basic').ArrayType;
 var StringType = require('gcli/types/basic').StringType;
 var BooleanType = require('gcli/types/basic').BooleanType;
 var NumberType = require('gcli/types/basic').NumberType;
 
@@ -5462,29 +5540,32 @@ UnassignedAssignment.prototype.getStatus
  * <li>onTextChange: The text to be mirrored in a command line has changed.
  * </ul>
  *
  * @param environment An optional opaque object passed to commands in the
  * Execution Context.
  * @param doc A DOM Document passed to commands using the Execution Context in
  * order to allow creation of DOM nodes. If missing Requisition will use the
  * global 'document'.
+ * @param commandOutputManager A custom commandOutputManager to which output
+ * should be sent (optional)
  * @constructor
  */
-function Requisition(environment, doc) {
+function Requisition(environment, doc, commandOutputManager) {
   this.environment = environment;
   this.document = doc;
   if (this.document == null) {
     try {
       this.document = document;
     }
     catch (ex) {
       // Ignore
     }
   }
+  this.commandOutputManager = commandOutputManager || new CommandOutputManager();
 
   // The command that we are about to execute.
   // @see setCommandConversion()
   this.commandAssignment = new CommandAssignment();
   this.setAssignment(this.commandAssignment, null);
 
   // The object that stores of Assignment objects that we are filling out.
   // The Assignment objects are stored under their param.name for named
@@ -5505,18 +5586,16 @@ function Requisition(environment, doc) {
 
   // Temporarily set this to true to prevent _assignmentChanged resetting
   // argument positions
   this._structuralChangeInProgress = false;
 
   this.commandAssignment.onAssignmentChange.add(this._commandAssignmentChanged, this);
   this.commandAssignment.onAssignmentChange.add(this._assignmentChanged, this);
 
-  this.commandOutputManager = canon.commandOutputManager;
-
   this.onAssignmentChange = util.createEvent('Requisition.onAssignmentChange');
   this.onTextChange = util.createEvent('Requisition.onTextChange');
 }
 
 /**
  * Avoid memory leaks
  */
 Requisition.prototype.destroy = function() {
@@ -6987,31 +7066,31 @@ exports.shutdown = function() {
  * if either the command line or any of the inputs in the hint element has the
  * focus, and invisible at other times, without hiding and showing the hint
  * element even briefly as the focus changes between them.
  * It does this simply by postponing the hide events by 250ms to see if
  * something else takes focus.
  * @param options Object containing user customization properties, including:
  * - blurDelay (default=150ms)
  * - debug (default=false)
- * - commandOutputManager (default=canon.commandOutputManager)
  * @param components Object that links to other UI components. GCLI provided:
  * - document
+ * - requisition
  */
 function FocusManager(options, components) {
   options = options || {};
 
   this._document = components.document || document;
+  this._requisition = components.requisition;
+
   this._debug = options.debug || false;
   this._blurDelay = options.blurDelay || 150;
   this._window = this._document.defaultView;
 
-  this._commandOutputManager = options.commandOutputManager ||
-      canon.commandOutputManager;
-  this._commandOutputManager.onOutput.add(this._outputted, this);
+  this._requisition.commandOutputManager.onOutput.add(this._outputted, this);
 
   this._blurDelayTimeout = null; // Result of setTimeout in delaying a blur
   this._monitoredElements = [];  // See addMonitoredElement()
 
   this._isError = false;
   this._hasFocus = false;
   this._helpRequested = false;
   this._recentOutput = false;
@@ -7030,17 +7109,17 @@ function FocusManager(options, component
 
 /**
  * Avoid memory leaks
  */
 FocusManager.prototype.destroy = function() {
   eagerHelper.onChange.remove(this._eagerHelperChanged, this);
 
   this._document.removeEventListener('focus', this._focused, true);
-  this._commandOutputManager.onOutput.remove(this._outputted, this);
+  this._requisition.commandOutputManager.onOutput.remove(this._outputted, this);
 
   for (var i = 0; i < this._monitoredElements.length; i++) {
     var monitor = this._monitoredElements[i];
     console.error('Hanging monitored element: ', monitor.element);
 
     monitor.element.removeEventListener('focus', monitor.onFocus, true);
     monitor.element.removeEventListener('blur', monitor.onBlur, true);
   }
@@ -7048,17 +7127,17 @@ FocusManager.prototype.destroy = functio
   if (this._blurDelayTimeout) {
     this._window.clearTimeout(this._blurDelayTimeout);
     this._blurDelayTimeout = null;
   }
 
   delete this._focused;
   delete this._document;
   delete this._window;
-  delete this._commandOutputManager;
+  delete this._requisition;
 };
 
 /**
  * The easy way to include an element in the set of things that are part of the
  * aggregate focus. Using [add|remove]MonitoredElement() is a simpler way of
  * option than calling report[Focus|Blur]()
  * @param element The element on which to track focus|blur events
  * @param where Optional source string for debugging only
@@ -9007,17 +9086,17 @@ var Requisition = require('gcli/cli').Re
 
 var cli = require('gcli/cli');
 var jstype = require('gcli/types/javascript');
 var nodetype = require('gcli/types/node');
 var resource = require('gcli/types/resource');
 var host = require('gcli/host');
 var intro = require('gcli/ui/intro');
 
-var commandOutputManager = require('gcli/canon').commandOutputManager;
+var CommandOutputManager = require('gcli/canon').CommandOutputManager;
 
 /**
  * Handy utility to inject the content document (i.e. for the viewed page,
  * not for chrome) into the various components.
  */
 function setContentDocument(document) {
   if (document) {
     // TODO: this unwrapping smells
@@ -9043,31 +9122,38 @@ function setContentDocument(document) {
  * - completeElement
  * - backgroundElement
  * - outputDocument
  * - consoleWrap (optional)
  * - eval (optional)
  * - environment
  * - scratchpad (optional)
  * - chromeWindow
+ * - commandOutputManager (optional)
  */
 function FFDisplay(options) {
   if (options.eval) {
     cli.setEvalFunction(options.eval);
   }
   setContentDocument(options.contentDocument);
   host.chromeWindow = options.chromeWindow;
 
-  this.onOutput = commandOutputManager.onOutput;
-  this.requisition = new Requisition(options.environment, options.outputDocument);
-
-  // Create a FocusManager for the various parts to register with
+  this.commandOutputManager = options.commandOutputManager;
+  if (this.commandOutputManager == null) {
+    this.commandOutputManager = new CommandOutputManager();
+  }
+
+  this.onOutput = this.commandOutputManager.onOutput;
+  this.requisition = new Requisition(options.environment,
+                                     options.outputDocument,
+                                     this.commandOutputManager);
+
   this.focusManager = new FocusManager(options, {
-    // TODO: can we kill chromeDocument here?
-    document: options.chromeDocument
+    document: options.chromeDocument,
+    requisition: this.requisition,
   });
   this.onVisibilityChange = this.focusManager.onVisibilityChange;
 
   this.inputter = new Inputter(options, {
     requisition: this.requisition,
     focusManager: this.focusManager,
     element: options.inputElement
   });
@@ -9101,17 +9187,17 @@ function FFDisplay(options) {
 }
 
 /**
  * The main Display calls this as part of startup since it registers listeners
  * for output first. The firefox display can't do this, so it has to be a
  * separate method
  */
 FFDisplay.prototype.maybeShowIntro = function() {
-  intro.maybeShowIntro(commandOutputManager);
+  intro.maybeShowIntro(this.commandOutputManager);
 };
 
 /**
  * Called when the page to which we're attached changes
  * @params options Object with the following properties:
  * - contentDocument: Points to the page that we should now work against
  * - environment: A replacement environment for Requisition use
  * - chromeWindow: Allow node type to create overlay
@@ -9146,17 +9232,17 @@ FFDisplay.prototype.destroy = function()
 
   delete this.options;
 
   // We could also delete the following objects if we have hard-to-track-down
   // memory leaks, as a belt-and-braces approach, however this prevents our
   // DOM node hunter script from looking in all the nooks and crannies, so it's
   // better if we can be leak-free without deleting them:
   // - consoleWrap, resizer, tooltip, completer, inputter,
-  // - focusManager, onVisibilityChange, requisition
+  // - focusManager, onVisibilityChange, requisition, commandOutputManager
 };
 
 /**
  * Called on chrome window resize, or on divider slide
  */
 FFDisplay.prototype.resizer = function() {
   // Bug 705109: There are several numbers hard-coded in this function.
   // This is simpler than calculating them, but error-prone when the UI setup,
@@ -9940,17 +10026,18 @@ function Completer(options, components) 
   this.document = this.element.ownerDocument;
 
   this.inputter = components.inputter;
 
   this.inputter.onInputChange.add(this.update, this);
   this.inputter.onAssignmentChange.add(this.update, this);
   this.inputter.onChoiceChange.add(this.update, this);
 
-  if (components.autoResize) {
+  this.autoResize = components.autoResize;
+  if (this.autoResize) {
     this.inputter.onResize.add(this.resized, this);
 
     var dimensions = this.inputter.getDimensions();
     if (dimensions) {
       this.resized(dimensions);
     }
   }
 
@@ -9963,17 +10050,20 @@ function Completer(options, components) 
 
 /**
  * Avoid memory leaks
  */
 Completer.prototype.destroy = function() {
   this.inputter.onInputChange.remove(this.update, this);
   this.inputter.onAssignmentChange.remove(this.update, this);
   this.inputter.onChoiceChange.remove(this.update, this);
-  this.inputter.onResize.remove(this.resized, this);
+
+  if (this.autoResize) {
+    this.inputter.onResize.remove(this.resized, this);
+  }
 
   delete this.document;
   delete this.element;
   delete this.template;
   delete this.inputter;
 };
 
 /**
--- a/browser/devtools/commandline/test/browser_cmd_addon.js
+++ b/browser/devtools/commandline/test/browser_cmd_addon.js
@@ -1,15 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests that the addon commands works as they should
 
 let imported = {};
-Components.utils.import("resource:///modules/devtools/CmdAddon.jsm", imported);
+Components.utils.import("resource:///modules/devtools/BuiltinCommands.jsm", imported);
 
 function test() {
   DeveloperToolbarTest.test("about:blank", [ GAT_test ]);
 }
 
 function GAT_test() {
   var GAT_ready = DeveloperToolbarTest.checkCalled(function() {
     Services.obs.removeObserver(GAT_ready, "gcli_addon_commands_ready", false);
@@ -91,17 +91,17 @@ function GAT_test() {
       }
     });
 
     DeveloperToolbarTest.exec({ completed: false });
   });
 
   Services.obs.addObserver(GAT_ready, "gcli_addon_commands_ready", false);
 
-  if (imported.Flags.addonsLoaded) {
+  if (imported.CmdAddonFlags.addonsLoaded) {
     info("The getAllAddons command has already completed and we have missed ");
     info("the notification. Let's send the gcli_addon_commands_ready ");
     info("notification ourselves.");
 
     Services.obs.notifyObservers(null, "gcli_addon_commands_ready", null);
   } else {
     info("gcli_addon_commands_ready notification has not yet been received.");
   }
--- a/browser/devtools/commandline/test/browser_gcli_exec.js
+++ b/browser/devtools/commandline/test/browser_gcli_exec.js
@@ -37,51 +37,54 @@ function test() {
   tests = tests.map(function(test) { return exports[test]; });
   DeveloperToolbarTest.test(TEST_URI, tests, true);
 }
 
 // <INJECTED SOURCE:END>
 
 
 var Requisition = require('gcli/cli').Requisition;
-var canon = require('gcli/canon');
+var CommandOutputManager = require('gcli/canon').CommandOutputManager;
 // var mockCommands = require('gclitest/mockCommands');
 var nodetype = require('gcli/types/node');
 
 // var assert = require('test/assert');
 
 var actualExec;
 var actualOutput;
 var hideExec = false;
 var skip = 'skip';
 
-exports.setup = function() {
+var environment = { value: 'example environment data' };
+var commandOutputManager = new CommandOutputManager();
+var requisition = new Requisition(environment, null, commandOutputManager);
+
+exports.setup = function(options) {
   mockCommands.setup();
   mockCommands.onCommandExec.add(commandExeced);
-  canon.commandOutputManager.onOutput.add(commandOutputed);
+
+  commandOutputManager.onOutput.add(commandOutputed);
 };
 
-exports.shutdown = function() {
+exports.shutdown = function(options) {
   mockCommands.shutdown();
   mockCommands.onCommandExec.remove(commandExeced);
-  canon.commandOutputManager.onOutput.remove(commandOutputed);
+
+  commandOutputManager.onOutput.remove(commandOutputed);
 };
 
 function commandExeced(ev) {
   actualExec = ev;
 }
 
 function commandOutputed(ev) {
   actualOutput = ev.output;
 }
 
 function exec(command, expectedArgs) {
-  var environment = {};
-
-  var requisition = new Requisition(environment);
   var outputObject = requisition.exec({ typed: command, hidden: hideExec });
 
   assert.is(command.indexOf(actualExec.command.name), 0, 'Command name: ' + command);
 
   assert.is(command, outputObject.typed, 'outputObject.command for: ' + command);
   assert.ok(outputObject.completed, 'outputObject.completed false for: ' + command);
 
   if (expectedArgs == null) {
--- a/browser/devtools/debugger/debugger-panes.js
+++ b/browser/devtools/debugger/debugger-panes.js
@@ -1734,22 +1734,21 @@ create({ constructor: GlobalSearchView, 
   /**
    * Starts a bounce animation for a match.
    *
    * @param nsIDOMNode aMatch
    *        The match to start a bounce animation for.
    */
   _bounceMatch: function DVGS__bounceMatch(aMatch) {
     Services.tm.currentThread.dispatch({ run: function() {
-      aMatch.setAttribute("focused", "");
-
       aMatch.addEventListener("transitionend", function onEvent() {
         aMatch.removeEventListener("transitionend", onEvent);
         aMatch.removeAttribute("focused");
       });
+      aMatch.setAttribute("focused", "");
     }}, 0);
   },
 
   _splitter: null,
   _currentlyFocusedMatch: -1,
   _forceExpandResults: false,
   _searchTimeout: null,
   _searchFunction: null,
--- a/browser/devtools/debugger/debugger-toolbar.js
+++ b/browser/devtools/debugger/debugger-toolbar.js
@@ -108,17 +108,18 @@ ToolbarView.prototype = {
   },
 
   /**
    * Listener handling the toggle button click event.
    */
   _onTogglePanesPressed: function DVT__onTogglePanesPressed() {
     DebuggerView.togglePanes({
       visible: DebuggerView.panesHidden,
-      animated: true
+      animated: true,
+      delayed: true
     });
   },
 
   /**
    * Listener handling the pause/resume button click event.
    */
   _onResumePressed: function DVT__onResumePressed() {
     if (DebuggerController.activeThread.paused) {
@@ -1051,16 +1052,17 @@ create({ constructor: FilteredSourcesVie
    * Initialization function, called when the debugger is started.
    */
   initialize: function DVFS_initialize() {
     dumpn("Initializing the FilteredSourcesView");
 
     let panel = this._panel = document.createElement("panel");
     panel.id = "filtered-sources-panel";
     panel.setAttribute("noautofocus", "true");
+    panel.setAttribute("level", "top");
     panel.setAttribute("position", FILTERED_SOURCES_POPUP_POSITION);
     document.documentElement.appendChild(panel);
 
     this._searchbox = document.getElementById("searchbox");
     this._container = new StackList(panel);
 
     this._container.itemFactory = this._createItemView;
     this._container.itemType = "vbox";
--- a/browser/devtools/debugger/debugger-view.js
+++ b/browser/devtools/debugger/debugger-view.js
@@ -389,72 +389,87 @@ let DebuggerView = {
 
   /**
    * Sets all the panes hidden or visible.
    *
    * @param object aFlags [optional]
    *        An object containing some of the following boolean properties:
    *        - visible: true if the pane should be shown, false for hidden
    *        - animated: true to display an animation on toggle
+   *        - delayed: true to wait a few cycles before toggle
    *        - callback: a function to invoke when the panes toggle finishes
    */
   togglePanes: function DV__togglePanes(aFlags = {}) {
     // Avoid useless toggles.
     if (aFlags.visible == !this.panesHidden) {
-      aFlags.callback && aFlags.callback();
+      if (aFlags.callback) aFlags.callback();
       return;
     }
 
-    if (aFlags.visible) {
-      this._stackframesAndBreakpoints.style.marginLeft = "0";
-      this._variablesAndExpressions.style.marginRight = "0";
-      this._togglePanesButton.removeAttribute("panesHidden");
-      this._togglePanesButton.setAttribute("tooltiptext", L10N.getStr("collapsePanes"));
-    } else {
-      let marginL = ~~(this._stackframesAndBreakpoints.getAttribute("width")) + 1;
-      let marginR = ~~(this._variablesAndExpressions.getAttribute("width")) + 1;
-      this._stackframesAndBreakpoints.style.marginLeft = -marginL + "px";
-      this._variablesAndExpressions.style.marginRight = -marginR + "px";
-      this._togglePanesButton.setAttribute("panesHidden", "true");
-      this._togglePanesButton.setAttribute("tooltiptext", L10N.getStr("expandPanes"));
+    // Computes and sets the panes margins in order to hide or show them.
+    function set() {
+      if (aFlags.visible) {
+        this._stackframesAndBreakpoints.style.marginLeft = "0";
+        this._variablesAndExpressions.style.marginRight = "0";
+        this._togglePanesButton.removeAttribute("panesHidden");
+        this._togglePanesButton.setAttribute("tooltiptext", L10N.getStr("collapsePanes"));
+      } else {
+        let marginL = ~~(this._stackframesAndBreakpoints.getAttribute("width")) + 1;
+        let marginR = ~~(this._variablesAndExpressions.getAttribute("width")) + 1;
+        this._stackframesAndBreakpoints.style.marginLeft = -marginL + "px";
+        this._variablesAndExpressions.style.marginRight = -marginR + "px";
+        this._togglePanesButton.setAttribute("panesHidden", "true");
+        this._togglePanesButton.setAttribute("tooltiptext", L10N.getStr("expandPanes"));
+      }
+
+      if (aFlags.animated) {
+        // Displaying the panes may have the effect of triggering scrollbars to
+        // appear in the source editor, which would render the currently
+        // highlighted line to appear behind them in some cases.
+        window.addEventListener("transitionend", function onEvent() {
+          window.removeEventListener("transitionend", onEvent, false);
+          DebuggerView.updateEditor();
+
+          // Invoke the callback when the transition ended.
+          if (aFlags.callback) aFlags.callback();
+        }, false);
+      } else {
+        // Invoke the callback immediately since there's no transition.
+        if (aFlags.callback) aFlags.callback();
+      }
     }
 
     if (aFlags.animated) {
       this._stackframesAndBreakpoints.setAttribute("animated", "");
       this._variablesAndExpressions.setAttribute("animated", "");
-
-      // Displaying the panes may have the effect of triggering scrollbars to
-      // appear in the source editor, which would render the currently
-      // highlighted line to appear behind them in some cases.
-      let self = this;
-
-      window.addEventListener("transitionend", function onEvent() {
-        window.removeEventListener("transitionend", onEvent, false);
-        aFlags.callback && aFlags.callback();
-        self.updateEditor();
-      }, false);
     } else {
       this._stackframesAndBreakpoints.removeAttribute("animated");
       this._variablesAndExpressions.removeAttribute("animated");
-      aFlags.callback && aFlags.callback();
+    }
+
+    if (aFlags.delayed) {
+      window.setTimeout(set.bind(this), PANES_APPEARANCE_DELAY);
+    } else {
+      set.call(this);
     }
   },
 
   /**
    * Sets all the panes visible after a short period of time.
    *
    * @param function aCallback
    *        A function to invoke when the panes toggle finishes.
    */
   showPanesSoon: function DV__showPanesSoon(aCallback) {
     // Try to keep animations as smooth as possible, so wait a few cycles.
     window.setTimeout(function() {
       DebuggerView.togglePanes({
         visible: true,
         animated: true,
+        delayed: true,
         callback: aCallback
       });
     }, PANES_APPEARANCE_DELAY);
   },
 
   /**
    * Handles any initialization on a tab navigation event issued by the client.
    */
--- a/browser/devtools/debugger/debugger.xul
+++ b/browser/devtools/debugger/debugger.xul
@@ -233,16 +233,17 @@
                      tabindex="0"/>
       <toolbarbutton id="debugger-options"
                      class="devtools-option-toolbarbutton"
                      tooltiptext="&debuggerUI.optsButton.tooltip;"
                      popup="debuggerPrefsContextMenu"/>
     </toolbar>
 
     <panel id="searchbox-panel"
+           level="top"
            type="arrow"
            noautofocus="true"
            position="before_start">
       <vbox>
         <label class="description" value="&debuggerUI.searchPanelTitle;"/>
         <hbox align="center">
           <button id="global-operator-button" class="operator"
                   command="globalSearchCommand"/>
@@ -262,16 +263,17 @@
           <button id="variable-operator-button" class="operator"
                   command="variableSearchCommand"/>
           <label id="variable-operator-label" class="plain operator"/>
         </hbox>
       </vbox>
     </panel>
 
     <panel id="conditional-breakpoint-panel"
+           level="top"
            type="arrow"
            noautofocus="true"
            position="after_start">
       <vbox>
         <label class="description" value="&debuggerUI.condBreakPanelTitle;"/>
         <textbox id="conditional-breakpoint-textbox"/>
       </vbox>
     </panel>
--- a/browser/devtools/debugger/test/Makefile.in
+++ b/browser/devtools/debugger/test/Makefile.in
@@ -82,17 +82,17 @@ MOCHITEST_BROWSER_TESTS = \
 	browser_dbg_bug786070_hide_nonenums.js \
 	browser_dbg_displayName.js \
 	browser_dbg_iframes.js \
 	browser_dbg_pause-exceptions.js \
 	browser_dbg_multiple-windows.js \
 	browser_dbg_breakpoint-new-script.js \
 	browser_dbg_bug737803_editor_actual_location.js \
 	browser_dbg_progress-listener-bug.js \
-	$(filter disabled-for-intermittent-crashes--bug-821701, browser_dbg_chrome-debugging.js) \
+	browser_dbg_chrome-debugging.js \
 	$(filter disabled-for-intermittent-failures--bug-753225, browser_dbg_createRemote.js) \
 	head.js \
 	$(NULL)
 
 ifneq ($(OS_ARCH),WINNT)
 MOCHITEST_BROWSER_TESTS += \
 	browser_dbg_bfcache.js \
 	$(NULL)
--- a/browser/devtools/debugger/test/browser_dbg_chrome-debugging.js
+++ b/browser/devtools/debugger/test/browser_dbg_chrome-debugging.js
@@ -11,19 +11,16 @@ var gTab = null;
 var gThreadClient = null;
 var gNewGlobal = false;
 var gAttached = false;
 var gChromeScript = false;
 const DEBUGGER_TAB_URL = EXAMPLE_URL + "browser_dbg_debuggerstatement.html";
 
 function test()
 {
-  // Make sure there is enough time for findAllGlobals.
-  requestLongerTimeout(3);
-
   let transport = DebuggerServer.connectPipe();
   gClient = new DebuggerClient(transport);
   gClient.connect(function(aType, aTraits) {
     gTab = addTab(DEBUGGER_TAB_URL, function() {
       gClient.listTabs(function(aResponse) {
         let dbg = aResponse.chromeDebugger;
         ok(dbg, "Found a chrome debugging actor.");
 
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-filter-05.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-filter-05.js
@@ -40,18 +40,18 @@ function testVariablesFiltering()
     is(innerScope.querySelectorAll(".variable:not([non-match])").length, 1,
       "There should be 1 variable displayed in the inner scope");
     is(mathScope.querySelectorAll(".variable:not([non-match])").length, 0,
       "There should be 0 variables displayed in the math scope");
     is(testScope.querySelectorAll(".variable:not([non-match])").length, 0,
       "There should be 0 variables displayed in the test scope");
     is(loadScope.querySelectorAll(".variable:not([non-match])").length, 1,
       "There should be 1 variable displayed in the load scope");
-    is(globalScope.querySelectorAll(".variable:not([non-match])").length, 3,
-      "There should be 3 variables displayed in the global scope");
+    is(globalScope.querySelectorAll(".variable:not([non-match])").length, 5,
+      "There should be 5 variables displayed in the global scope");
 
     is(innerScope.querySelectorAll(".property:not([non-match])").length, 0,
       "There should be 0 properties displayed in the inner scope");
     is(mathScope.querySelectorAll(".property:not([non-match])").length, 0,
       "There should be 0 properties displayed in the math scope");
     is(testScope.querySelectorAll(".property:not([non-match])").length, 0,
       "There should be 0 properties displayed in the test scope");
     is(loadScope.querySelectorAll(".property:not([non-match])").length, 0,
--- a/browser/devtools/framework/Target.jsm
+++ b/browser/devtools/framework/Target.jsm
@@ -281,17 +281,18 @@ TabWebProgressListener.prototype = {
     let isNetwork = flag & Ci.nsIWebProgressListener.STATE_IS_NETWORK;
     let isRequest = flag & Ci.nsIWebProgressListener.STATE_IS_REQUEST;
 
     // Skip non-interesting states.
     if (!isStart || !isDocument || !isRequest || !isNetwork) {
       return;
     }
 
-    if (this.target) {
+    // emit event if the top frame is navigating
+    if (this.target && this.target.window == progress.DOMWindow) {
       this.target.emit("will-navigate", request);
     }
   },
 
   onProgressChange: function() {},
   onSecurityChange: function() {},
   onStatusChange: function() {},
 
--- a/browser/devtools/framework/ToolDefinitions.jsm
+++ b/browser/devtools/framework/ToolDefinitions.jsm
@@ -130,38 +130,34 @@ let styleEditorDefinition = {
   accesskey: l10n("open.accesskey", styleEditorStrings),
   modifiers: "shift",
   label: l10n("ToolboxStyleEditor.label", styleEditorStrings),
   icon: "chrome://browser/skin/devtools/tool-styleeditor.png",
   url: "chrome://browser/content/styleeditor.xul",
   tooltip: l10n("ToolboxStyleEditor.tooltip", styleEditorStrings),
 
   isTargetSupported: function(target) {
-    return !target.isRemote && !target.isChrome;
+    return target.isLocalTab;
   },
 
   build: function(iframeWindow, toolbox) {
     let panel = new StyleEditorPanel(iframeWindow, toolbox);
     return panel.open();
   }
 };
 
 let profilerDefinition = {
   id: "jsprofiler",
   killswitch: "devtools.profiler.enabled",
   url: "chrome://browser/content/profiler.xul",
   label: l10n("profiler.label", profilerStrings),
   tooltip: l10n("profiler.tooltip", profilerStrings),
 
   isTargetSupported: function (target) {
-    if (target.isRemote || target.isChrome) {
-      return false;
-    }
-
-    return true;
+    return !target.isRemote;
   },
 
   build: function (frame, target) {
     let panel = new ProfilerPanel(frame, target);
     return panel.open();
   }
 };
 
--- a/browser/devtools/framework/Toolbox.jsm
+++ b/browser/devtools/framework/Toolbox.jsm
@@ -11,35 +11,35 @@ Cu.import("resource://gre/modules/Servic
 Cu.import("resource://gre/modules/commonjs/promise/core.js");
 Cu.import("resource:///modules/devtools/EventEmitter.jsm");
 Cu.import("resource:///modules/devtools/gDevTools.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Hosts",
                                   "resource:///modules/devtools/ToolboxHosts.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "CommandUtils",
                                   "resource:///modules/devtools/DeveloperToolbar.jsm");
+
 XPCOMUtils.defineLazyGetter(this, "toolboxStrings", function() {
   let bundle = Services.strings.createBundle("chrome://browser/locale/devtools/toolbox.properties");
   let l10n = function(name) {
     try {
       return bundle.GetStringFromName(name);
     } catch (ex) {
       Services.console.logStringMessage("Error reading '" + name + "'");
     }
   };
   return l10n;
 });
 
-// DO NOT put Require.jsm or gcli.jsm into lazy getters as this breaks the
-// requisition import a few lines down.
-Cu.import("resource:///modules/devtools/gcli.jsm");
-Cu.import("resource://gre/modules/devtools/Require.jsm");
+XPCOMUtils.defineLazyGetter(this, "Requisition", function() {
+  Cu.import("resource://gre/modules/devtools/Require.jsm");
+  Cu.import("resource:///modules/devtools/gcli.jsm");
 
-let Requisition = require('gcli/cli').Requisition;
-let CommandOutputManager = require('gcli/canon').CommandOutputManager;
+  return require('gcli/cli').Requisition;
+});
 
 this.EXPORTED_SYMBOLS = [ "Toolbox" ];
 
 // This isn't the best place for this, but I don't know what is right now
 
 /**
  * Implementation of 'promised', while we wait for bug 790195 to be fixed.
  * @see Consuming promises in https://addons.mozilla.org/en-US/developers/docs/sdk/latest/packages/api-utils/promise.html
@@ -239,36 +239,41 @@ Toolbox.prototype = {
   },
 
   /**
    * Open the toolbox
    */
   open: function TBOX_open() {
     let deferred = Promise.defer();
 
-    this._host.open().then(function(iframe) {
-      let onload = function() {
-        iframe.removeEventListener("DOMContentLoaded", onload, true);
+    this._host.create().then(function(iframe) {
+      let domReady = function() {
+        iframe.removeEventListener("DOMContentLoaded", domReady, true);
+
+        let vbox = this.doc.getElementById("toolbox-panel-" + this._currentToolId);
+        if (vbox) {
+          this.doc.commandDispatcher.advanceFocusIntoSubtree(vbox);
+        }
 
         this.isReady = true;
 
         let closeButton = this.doc.getElementById("toolbox-close");
         closeButton.addEventListener("command", this.destroy, true);
 
         this._buildDockButtons();
         this._buildTabs();
-        this._buildButtons(this.frame);
+        this._buildButtons();
 
         this.selectTool(this._defaultToolId).then(function(panel) {
           this.emit("ready");
           deferred.resolve();
         }.bind(this));
       }.bind(this);
 
-      iframe.addEventListener("DOMContentLoaded", onload, true);
+      iframe.addEventListener("DOMContentLoaded", domReady, true);
       iframe.setAttribute("src", this._URL);
     }.bind(this));
 
     return deferred.promise;
   },
 
   /**
    * Build the buttons for changing hosts. Called every time
@@ -312,31 +317,27 @@ Toolbox.prototype = {
   _buildTabs: function TBOX_buildTabs() {
     for (let [id, definition] of gDevTools.getToolDefinitions()) {
       this._buildTabForTool(definition);
     }
   },
 
   /**
    * Add buttons to the UI as specified in the devtools.window.toolbarSpec pref
-   *
-   * @param {iframe} frame
-   *        The iframe to contain the buttons
    */
-  _buildButtons: function TBOX_buildButtons(frame) {
-    if (this.target.isRemote) {
+  _buildButtons: function TBOX_buildButtons() {
+    if (!this.target.isLocalTab) {
       return;
     }
 
     let toolbarSpec = CommandUtils.getCommandbarSpec("devtools.toolbox.toolbarSpec");
-    let environment = { chromeDocument: frame.ownerDocument };
+    let environment = { chromeDocument: this.target.tab.ownerDocument };
     let requisition = new Requisition(environment);
-    requisition.commandOutputManager = new CommandOutputManager();
 
-    let buttons = CommandUtils.createButtons(toolbarSpec, this.doc, requisition);
+    let buttons = CommandUtils.createButtons(toolbarSpec, this._target, this.doc, requisition);
 
     let container = this.doc.getElementById("toolbox-buttons");
     buttons.forEach(function(button) {
       container.appendChild(button);
     }.bind(this));
   },
 
   /**
@@ -468,21 +469,20 @@ Toolbox.prototype = {
    *
    * @param {string} hostType
    *        The host type of the new host object
    *
    * @return {Host} host
    *        The created host object
    */
   _createHost: function TBOX_createHost(hostType) {
-    let hostTab = this._getHostTab();
     if (!Hosts[hostType]) {
       throw new Error('Unknown hostType: '+ hostType);
     }
-    let newHost = new Hosts[hostType](hostTab);
+    let newHost = new Hosts[hostType](this.target.tab);
 
     // clean up the toolbox if its window is closed
     newHost.on("window-closed", this.destroy);
 
     return newHost;
   },
 
   /**
@@ -497,17 +497,17 @@ Toolbox.prototype = {
       return;
     }
 
     if (!this._target.isLocalTab) {
       return;
     }
 
     let newHost = this._createHost(hostType);
-    return newHost.open().then(function(iframe) {
+    return newHost.create().then(function(iframe) {
       // change toolbox document's parent to the new host
       iframe.QueryInterface(Ci.nsIFrameLoaderOwner);
       iframe.swapFrameLoaders(this.frame);
 
       this._host.off("window-closed", this.destroy);
       this._host.destroy();
 
       this._host = newHost;
@@ -516,28 +516,16 @@ Toolbox.prototype = {
 
       this._buildDockButtons();
 
       this.emit("host-changed");
     }.bind(this));
   },
 
   /**
-   * Get the most appropriate host tab, either the target or the current tab
-   */
-  _getHostTab: function TBOX_getHostTab() {
-    if (!this._target.isRemote && !this._target.isChrome) {
-      return this._target.tab;
-    } else {
-      let win = Services.wm.getMostRecentWindow("navigator:browser");
-      return win.gBrowser.selectedTab;
-    }
-  },
-
-  /**
    * Handler for the tool-registered event.
    * @param  {string} event
    *         Name of the event ("tool-registered")
    * @param  {string} toolId
    *         Id of the tool that was registered
    */
   _toolRegistered: function TBOX_toolRegistered(event, toolId) {
     let defs = gDevTools.getToolDefinitions();
--- a/browser/devtools/framework/ToolboxHosts.jsm
+++ b/browser/devtools/framework/ToolboxHosts.jsm
@@ -12,17 +12,17 @@ Cu.import("resource:///modules/devtools/
 
 this.EXPORTED_SYMBOLS = [ "Hosts" ];
 
 /**
  * A toolbox host represents an object that contains a toolbox (e.g. the
  * sidebar or a separate window). Any host object should implement the
  * following functions:
  *
- * open() - create the UI and emit a 'ready' event when the UI is ready to use
+ * create() - create the UI and emit a 'ready' event when the UI is ready to use
  * destroy() - destroy the host's UI
  */
 
 this.Hosts = {
   "bottom": BottomHost,
   "side": SidebarHost,
   "window": WindowHost
 }
@@ -39,27 +39,27 @@ function BottomHost(hostTab) {
 BottomHost.prototype = {
   type: "bottom",
 
   heightPref: "devtools.toolbox.footer.height",
 
   /**
    * Create a box at the bottom of the host tab.
    */
-  open: function BH_open() {
+  create: function BH_create() {
     let deferred = Promise.defer();
 
     let gBrowser = this.hostTab.ownerDocument.defaultView.gBrowser;
     let ownerDocument = gBrowser.ownerDocument;
 
     this._splitter = ownerDocument.createElement("splitter");
     this._splitter.setAttribute("class", "devtools-horizontal-splitter");
 
     this.frame = ownerDocument.createElement("iframe");
-    this.frame.id = "devtools-toolbox-bottom-iframe";
+    this.frame.className = "devtools-toolbox-bottom-iframe";
     this.frame.height = Services.prefs.getIntPref(this.heightPref);
 
     this._nbox = gBrowser.getNotificationBox(this.hostTab.linkedBrowser);
     this._nbox.appendChild(this._splitter);
     this._nbox.appendChild(this.frame);
 
     let frameLoad = function() {
       this.frame.removeEventListener("DOMContentLoaded", frameLoad, true);
@@ -107,27 +107,27 @@ function SidebarHost(hostTab) {
 SidebarHost.prototype = {
   type: "side",
 
   widthPref: "devtools.toolbox.sidebar.width",
 
   /**
    * Create a box in the sidebar of the host tab.
    */
-  open: function RH_open() {
+  create: function SH_create() {
     let deferred = Promise.defer();
 
     let gBrowser = this.hostTab.ownerDocument.defaultView.gBrowser;
     let ownerDocument = gBrowser.ownerDocument;
 
     this._splitter = ownerDocument.createElement("splitter");
     this._splitter.setAttribute("class", "devtools-side-splitter");
 
     this.frame = ownerDocument.createElement("iframe");
-    this.frame.id = "devtools-toolbox-side-iframe";
+    this.frame.className = "devtools-toolbox-side-iframe";
     this.frame.width = Services.prefs.getIntPref(this.widthPref);
 
     this._sidebar = gBrowser.getSidebarContainer(this.hostTab.linkedBrowser);
     this._sidebar.appendChild(this._splitter);
     this._sidebar.appendChild(this.frame);
 
     let frameLoad = function() {
       this.frame.removeEventListener("DOMContentLoaded", frameLoad, true);
@@ -142,17 +142,17 @@ SidebarHost.prototype = {
     focusTab(this.hostTab);
 
     return deferred.promise;
   },
 
   /**
    * Destroy the sidebar.
    */
-  destroy: function RH_destroy() {
+  destroy: function SH_destroy() {
     if (!this._destroyed) {
       this._destroyed = true;
 
       Services.prefs.setIntPref(this.widthPref, this.frame.width);
       this._sidebar.removeChild(this._splitter);
       this._sidebar.removeChild(this.frame);
     }
 
@@ -172,17 +172,17 @@ function WindowHost() {
 WindowHost.prototype = {
   type: "window",
 
   WINDOW_URL: "chrome://browser/content/devtools/framework/toolbox-window.xul",
 
   /**
    * Create a new xul window to contain the toolbox.
    */
-  open: function WH_open() {
+  create: function WH_create() {
     let deferred = Promise.defer();
 
     let flags = "chrome,centerscreen,resizable,dialog=no";
     let win = Services.ww.openWindow(null, this.WINDOW_URL, "_blank",
                                      flags, null);
 
     let frameLoad = function(event) {
       win.removeEventListener("load", frameLoad, true);
--- a/browser/devtools/framework/gDevTools.jsm
+++ b/browser/devtools/framework/gDevTools.jsm
@@ -424,17 +424,17 @@ let gDevToolsBrowser = {
 
       let mp = doc.getElementById("menuWebDeveloperPopup");
       let mps = doc.getElementById("menu_devtools_separator");
       mp.insertBefore(menuitem, mps);
     }
   },
 
   /**
-   * Update the "Toggle Toolbox" checkbox in the developer tools menu. This is
+   * Update the "Toggle Tools" checkbox in the developer tools menu. This is
    * called when a toolbox is created or destroyed.
    */
   _updateMenuCheckbox: function DT_updateMenuCheckbox() {
     for (let win of gDevToolsBrowser._trackedBrowserWindows) {
 
       let hasToolbox = false;
       if (TargetFactory.isKnownTab(win.gBrowser.selectedTab)) {
         let target = TargetFactory.forTab(win.gBrowser.selectedTab);
--- a/browser/devtools/framework/test/browser_toolbox_hosts.js
+++ b/browser/devtools/framework/test/browser_toolbox_hosts.js
@@ -33,45 +33,48 @@ function test()
 
 function testBottomHost(aToolbox)
 {
   toolbox = aToolbox;
 
   checkHostType(Toolbox.HostType.BOTTOM);
 
   // test UI presence
-  let iframe = document.getElementById("devtools-toolbox-bottom-iframe");
+  let nbox = gBrowser.getNotificationBox();
+  let iframe = document.getAnonymousElementByAttribute(nbox, "class", "devtools-toolbox-bottom-iframe");
   ok(iframe, "toolbox bottom iframe exists");
 
   checkToolboxLoaded(iframe);
 
   toolbox.switchHost(Toolbox.HostType.SIDE).then(testSidebarHost);
 }
 
 function testSidebarHost()
 {
   checkHostType(Toolbox.HostType.SIDE);
 
   // test UI presence
-  let bottom = document.getElementById("devtools-toolbox-bottom-iframe");
+  let nbox = gBrowser.getNotificationBox();
+  let bottom = document.getAnonymousElementByAttribute(nbox, "class", "devtools-toolbox-bottom-iframe");
   ok(!bottom, "toolbox bottom iframe doesn't exist");
 
-  let iframe = document.getElementById("devtools-toolbox-side-iframe");
+  let iframe = document.getAnonymousElementByAttribute(nbox, "class", "devtools-toolbox-side-iframe");
   ok(iframe, "toolbox side iframe exists");
 
   checkToolboxLoaded(iframe);
 
   toolbox.switchHost(Toolbox.HostType.WINDOW).then(testWindowHost);
 }
 
 function testWindowHost()
 {
   checkHostType(Toolbox.HostType.WINDOW);
 
-  let sidebar = document.getElementById("devtools-toolbox-side-iframe");
+  let nbox = gBrowser.getNotificationBox();
+  let sidebar = document.getAnonymousElementByAttribute(nbox, "class", "devtools-toolbox-side-iframe");
   ok(!sidebar, "toolbox sidebar iframe doesn't exist");
 
   let win = Services.wm.getMostRecentWindow("devtools:toolbox");
   ok(win, "toolbox separate window exists");
 
   let iframe = win.document.getElementById("toolbox-iframe");
   checkToolboxLoaded(iframe);
 
--- a/browser/devtools/inspector/InspectorPanel.jsm
+++ b/browser/devtools/inspector/InspectorPanel.jsm
@@ -223,17 +223,25 @@ InspectorPanel.prototype = {
    */
   preventNavigateAway: function InspectorPanel_preventNavigateAway(event, request) {
     if (!this.isDirty) {
       return;
     }
 
     request.suspend();
 
-    let notificationBox = this._toolbox.getNotificationBox();
+    let notificationBox = null;
+    if (this.target.isLocalTab) {
+      let gBrowser = this.target.tab.ownerDocument.defaultView.gBrowser;
+      notificationBox = gBrowser.getNotificationBox();
+    }
+    else {
+      notificationBox = this._toolbox.getNotificationBox();
+    }
+
     let notification = notificationBox.
       getNotificationWithValue("inspector-page-navigation");
 
     if (notification) {
       notificationBox.removeNotification(notification, true);
     }
 
     let cancelRequest = function onCancelRequest() {
@@ -254,19 +262,17 @@ InspectorPanel.prototype = {
       {
         id: "inspector.confirmNavigationAway.buttonLeave",
         label: this.strings.GetStringFromName("confirmNavigationAway.buttonLeave"),
         accessKey: this.strings.GetStringFromName("confirmNavigationAway.buttonLeaveAccesskey"),
         callback: function onButtonLeave() {
           if (request) {
             request.resume();
             request = null;
-            return true;
           }
-          return false;
         }.bind(this),
       },
       {
         id: "inspector.confirmNavigationAway.buttonStay",
         label: this.strings.GetStringFromName("confirmNavigationAway.buttonStay"),
         accessKey: this.strings.GetStringFromName("confirmNavigationAway.buttonStayAccesskey"),
         callback: cancelRequest
       },
--- a/browser/devtools/inspector/test/browser_inspector_bug_566084_location_changed.js
+++ b/browser/devtools/inspector/test/browser_inspector_bug_566084_location_changed.js
@@ -20,17 +20,17 @@ function test() {
     let para = content.document.querySelector("p");
     ok(para, "found the paragraph element");
     is(para.textContent, "init", "paragraph content is correct");
 
     inspector.markDirty();
 
     let target = TargetFactory.forTab(gBrowser.selectedTab);
     let toolbox = gDevTools.getToolbox(target);
-    notificationBox = toolbox.getNotificationBox();
+    notificationBox = gBrowser.getNotificationBox();
     notificationBox.addEventListener("AlertActive", alertActive1, false);
 
     ok(toolbox, "We have access to the notificationBox");
 
     gBrowser.selectedBrowser.addEventListener("load", onPageLoad, true);
 
     content.location = "data:text/html,<div>location change test 1 for " +
       "inspector</div><p>test1</p>";
--- a/browser/devtools/inspector/test/browser_inspector_bug_665880.js
+++ b/browser/devtools/inspector/test/browser_inspector_bug_665880.js
@@ -31,18 +31,20 @@ function test()
     inspector.highlighter.once("locked", performTestComparison);
     inspector.selection.setNode(objectNode, "");
   }
 
   function performTestComparison()
   {
     is(getActiveInspector().selection.node, objectNode, "selection matches node");
     let target = TargetFactory.forTab(gBrowser.selectedTab);
-    gDevTools.closeToolbox(target);
-    finishUp();
+    executeSoon(function() {
+      gDevTools.closeToolbox(target);
+      finishUp();
+    });
   }
 
 
   function finishUp() {
     doc = objectNode = null;
     gBrowser.removeCurrentTab();
     finish();
   }
--- a/browser/devtools/inspector/test/browser_inspector_bug_672902_keyboard_shortcuts.js
+++ b/browser/devtools/inspector/test/browser_inspector_bug_672902_keyboard_shortcuts.js
@@ -25,17 +25,17 @@ function test()
                      "</h1><p><strong>Greetings, earthlings!</strong> I come" +
                      " in peace.</body></html>";
 
   function setupKeyBindingsTest()
   {
     openInspector(findAndHighlightNode);
   }
 
-  function findAndHighlightNode(aInspector)
+  function findAndHighlightNode(aInspector, aToolbox)
   {
     inspector = aInspector;
 
     executeSoon(function() {
       inspector.selection.once("new-node", highlightBodyNode);
       // Test that navigating around without a selected node gets us to the
       // body element.
       node = doc.querySelector("body");
--- a/browser/devtools/inspector/test/head.js
+++ b/browser/devtools/inspector/test/head.js
@@ -14,17 +14,17 @@ let console = tempScope.console;
 // Import the GCLI test helper
 let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
 Services.scriptloader.loadSubScript(testDir + "/helpers.js", this);
 
 function openInspector(callback)
 {
   let target = TargetFactory.forTab(gBrowser.selectedTab);
   gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
-    callback(toolbox.getCurrentPanel());
+    callback(toolbox.getCurrentPanel(), toolbox);
   }).then(null, console.error);
 }
 
 function getActiveInspector()
 {
   let target = TargetFactory.forTab(gBrowser.selectedTab);
   return gDevTools.getToolbox(target).getPanel("inspector");
 }
--- a/browser/devtools/jar.mn
+++ b/browser/devtools/jar.mn
@@ -35,19 +35,17 @@ browser.jar:
     content/browser/devtools/profiler/cleopatra/css/devtools.css        (profiler/cleopatra/css/devtools.css)
     content/browser/devtools/profiler/cleopatra/js/parser.js            (profiler/cleopatra/js/parser.js)
     content/browser/devtools/profiler/cleopatra/js/parserWorker.js      (profiler/cleopatra/js/parserWorker.js)
     content/browser/devtools/profiler/cleopatra/js/tree.js              (profiler/cleopatra/js/tree.js)
     content/browser/devtools/profiler/cleopatra/js/ui.js                (profiler/cleopatra/js/ui.js)
     content/browser/devtools/profiler/cleopatra/js/ProgressReporter.js  (profiler/cleopatra/js/ProgressReporter.js)
     content/browser/devtools/profiler/cleopatra/js/devtools.js          (profiler/cleopatra/js/devtools.js)
     content/browser/devtools/profiler/cleopatra/images/circlearrow.svg  (profiler/cleopatra/images/circlearrow.svg)
-    content/browser/devtools/profiler/cleopatra/images/filter.png       (profiler/cleopatra/images/filter.png)
     content/browser/devtools/profiler/cleopatra/images/noise.png        (profiler/cleopatra/images/noise.png)
-    content/browser/devtools/profiler/cleopatra/images/showall.png      (profiler/cleopatra/images/showall.png)
     content/browser/devtools/profiler/cleopatra/images/throbber.svg     (profiler/cleopatra/images/throbber.svg)
     content/browser/devtools/profiler/cleopatra/images/treetwisty.svg   (profiler/cleopatra/images/treetwisty.svg)
     content/browser/devtools/commandline.css      (commandline/commandline.css)
     content/browser/devtools/commandlineoutput.xhtml  (commandline/commandlineoutput.xhtml)
     content/browser/devtools/commandlinetooltip.xhtml  (commandline/commandlinetooltip.xhtml)
     content/browser/devtools/framework/toolbox-window.xul    (framework/toolbox-window.xul)
 *   content/browser/devtools/framework/toolbox.xul           (framework/toolbox.xul)
     content/browser/devtools/framework/toolbox.css           (framework/toolbox.css)
--- a/browser/devtools/profiler/cleopatra/cleopatra.html
+++ b/browser/devtools/profiler/cleopatra/cleopatra.html
@@ -12,18 +12,16 @@
     <link rel="stylesheet" type="text/css" href="profiler/cleopatra/css/tree.css">
     <link rel="stylesheet" type="text/css" href="profiler/cleopatra/css/devtools.css">
 
     <script src="profiler/cleopatra/js/parser.js"></script>
     <script src="profiler/cleopatra/js/tree.js"></script>
     <script src="profiler/cleopatra/js/ui.js"></script>
     <script src="profiler/cleopatra/js/ProgressReporter.js"></script>
     <script src="profiler/cleopatra/js/devtools.js"></script>
-
-    <link rel="shortcut icon" href="favicon.png" />
   </head>
 
   <body onload="notifyParent('loaded');">
     <script>
       initUI();
     </script>
   </body>
 </html>
--- a/browser/devtools/profiler/cleopatra/css/tree.css
+++ b/browser/devtools/profiler/cleopatra/css/tree.css
@@ -1,15 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 .treeViewContainer {
   -moz-user-select: none;
-  -webkit-user-select: none;
   user-select: none;
   cursor: default;
   line-height: 16px;
   height: 100%;
   outline: none; /* override the browser's focus styling */
   position: relative;
 }
 
@@ -21,18 +20,16 @@
   height: 16px;
   margin: 0;
   padding: 0;
 }
 
 .treeColumnHeader {
   position: absolute;
   display: block;
-  background: -moz-linear-gradient(#FFF 45%, #EEE 60%);
-  background: -webkit-linear-gradient(#FFF 45%, #EEE 60%);
   background: linear-gradient(#FFF 45%, #EEE 60%);
   margin: 0;
   padding: 0;
   top: 0;
   height: 15px;
   line-height: 15px;
   border: 0 solid #CCC;
   border-bottom-width: 1px;
@@ -88,27 +85,21 @@
 
 .treeViewHorizontalScrollbox {
   padding-left: 150px;
   overflow: hidden;
 }
 
 .treeViewVerticalScrollbox,
 .treeViewHorizontalScrollbox {
-  background: -moz-linear-gradient(white, white 50%, #F0F5FF 50%, #F0F5FF);
-  background: -webkit-linear-gradient(white, white 50%, #F0F5FF 50%, #F0F5FF);
   background: linear-gradient(white, white 50%, #F0F5FF 50%, #F0F5FF);
   background-size: 100px 32px;
 }
 
 .leftColumnBackground {
-  background: -moz-linear-gradient(left, transparent, transparent 98px, #CCC 98px, #CCC 99px, transparent 99px),
-    -moz-linear-gradient(white, white 50%, #F0F5FF 50%, #F0F5FF);
-  background: -webkit-linear-gradient(left, transparent, transparent 98px, #CCC 98px, #CCC 99px, transparent 99px),
-    -webkit-linear-gradient(white, white 50%, #F0F5FF 50%, #F0F5FF);
   background: linear-gradient(left, transparent, transparent 98px, #CCC 98px, #CCC 99px, transparent 99px),
     linear-gradient(white, white 50%, #F0F5FF 50%, #F0F5FF);
   background-size: auto, 100px 32px;
   position: absolute;
   top: 0;
   left: 0;
   width: 146px;
   min-height: 100%;
--- a/browser/devtools/profiler/cleopatra/css/ui.css
+++ b/browser/devtools/profiler/cleopatra/css/ui.css
@@ -27,20 +27,16 @@ body {
 .profileEntryPane {
   overflow: auto;
 }
 .profileEntryPane,
 .profileProgressPane {
   padding: 20px;
   background-color: rgb(229,229,229);
   background-image: url(../images/noise.png),
-                    -moz-linear-gradient(rgba(255,255,255,.5),rgba(255,255,255,.2));
-  background-image: url(../images/noise.png),
-                    -webkit-linear-gradient(rgba(255,255,255,.5),rgba(255,255,255,.2));
-  background-image: url(../images/noise.png),
                     linear-gradient(rgba(255,255,255,.5),rgba(255,255,255,.2));
   text-shadow: rgba(255, 255, 255, 0.4) 0 1px;
 }
 .profileEntryPane h1 {
   margin-top: 0;
   font-size: 13px;
   font-weight: normal;
 }
@@ -57,99 +53,108 @@ body {
 .profileProgressPane progress {
   position: absolute;
   top: 40%;
   left: 30%;
   width: 40%;
   height: 16px;
 }
 .finishedProfilePaneBackgroundCover {
-  -webkit-animation: darken 300ms cubic-bezier(0, 0, 1, 0);
-  -moz-animation: darken 300ms cubic-bezier(0, 0, 1, 0);
+  animation: darken 300ms cubic-bezier(0, 0, 1, 0);
   background-color: rgba(0, 0, 0, 0.5);
 }
+
 .finishedProfilePane {
-  -webkit-animation: appear 300ms ease-out;
-  -moz-animation: appear 300ms ease-out;
+  animation: appear 300ms ease-out;
 }
 
+@keyframes darken {
+  from {
+    opacity: 0;
+  }
+  to {
+    opacity: 1;
+  }
+}
+@keyframes appear {
+  from {
+    transform: scale(0.3);
+    opacity: 0;
+    pointer-events: none;
+  }
+  to {
+    transform: scale(1);
+    opacity: 1;
+    pointer-events: auto;
+  }
+}
 .breadcrumbTrail {
   top: 0;
   right: 0;
   height: 29px;
   left: 0;
-  background: -moz-linear-gradient(#FFF 50%, #F3F3F3 55%);
-  background: -webkit-linear-gradient(#FFF 50%, #F3F3F3 55%);
   background: linear-gradient(#FFF 50%, #F3F3F3 55%);
   border-bottom: 1px solid #CCC;
   margin: 0;
   padding: 0;
   overflow: hidden;
 }
 .breadcrumbTrailItem {
-  background: -moz-linear-gradient(#FFF 50%, #F3F3F3 55%);
-  background: -webkit-linear-gradient(#FFF 50%, #F3F3F3 55%);
   background: linear-gradient(#FFF 50%, #F3F3F3 55%);
   display: block;
   margin: 0;
   padding: 0;
   float: left;
   line-height: 29px;
   padding: 0 10px;
   font-size: 12px;
   -moz-user-select: none;
-  -webkit-user-select: none;
   user-select: none;
   cursor: default;
   border-right: 1px solid #CCC;
   max-width: 250px;
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap;
   position: relative;
 }
-@-webkit-keyframes slide-out {
+@keyframes slide-out {
   from {
     margin-left: -270px;
     opacity: 0;
   }
   to {
     margin-left: 0;
     opacity: 1;
   }
 }
-@-moz-keyframes slide-out {
+@keyframes slide-out {
   from {
     margin-left: -270px;
     opacity: 0;
   }
   to {
     margin-left: 0;
     opacity: 1;
   }
 }
 .breadcrumbTrailItem:not(:first-child) {
-  -moz-animation: slide-out;
-  -moz-animation-duration: 400ms;
-  -moz-animation-timing-function: ease-out;
-  -webkit-animation: slide-out;
-  -webkit-animation-duration: 400ms;
-  -webkit-animation-timing-function: ease-out;
+  animation: slide-out;
+  animation-duration: 400ms;
+  animation-timing-function: ease-out;
 }
 .breadcrumbTrailItem.selected {
   background: linear-gradient(#E5E5E5 50%, #DADADA 55%);
 }
 .breadcrumbTrailItem:not(.selected):active:hover {
   background: linear-gradient(#F2F2F2 50%, #E6E6E6 55%);
 }
 .breadcrumbTrailItem.deleted {
-  -moz-transition: 400ms ease-out;
-  -moz-transition-property: opacity, margin-left;
-  -webkit-transition: 400ms ease-out;
-  -webkit-transition-property: opacity, margin-left;
+  transition: 400ms ease-out;
+  transition-property: opacity, margin-left;
   opacity: 0;
   margin-left: -270px;
 }
 .treeContainer {
   /*For asbolute position child*/
   position: relative;
 }
 .tree {
@@ -194,17 +199,16 @@ body {
   margin-left: 0;
 }
 #infoBar dd::after {
   content: "\a";
   white-space:pre;
 }
 .sideBar {
   -moz-box-sizing: border-box;
-  -webkit-box-sizing: border-box;
   box-sizing: border-box;
   position: absolute;
   left: 0;
   bottom: 0;
   width: 200px;
   height: 480px;
   overflow: auto;
   padding: 3px;
@@ -241,18 +245,16 @@ body {
   height: 100%;
 }
 .histogram {
   position: relative;
   height: 60px;
   right: 0;
   left: 0;
   border-bottom: 1px solid #CCC;
-  background: -moz-linear-gradient(#EEE, #CCC);
-  background: -webkit-linear-gradient(#EEE, #CCC);
   background: linear-gradient(#EEE, #CCC);
 }
 .histogramHilite {
   position: absolute;
   pointer-events: none;
 }
 .histogramHilite:not(.collapsed) {
   background: rgba(150, 150, 150, 0.5);
@@ -282,18 +284,16 @@ body {
 .fileListItem {
   display: block;
   margin: 0;
   padding: 0;
   height: 40px;
   text-indent: 8px;
 }
 .fileListItem.selected {
-  background: -moz-linear-gradient(#4B91D7 1px, #5FA9E4 1px, #5FA9E4 2px, #58A0DE 3px, #2B70C7 39px, #2763B4 39px);
-  background: -webkit-linear-gradient(#4B91D7 1px, #5FA9E4 1px, #5FA9E4 2px, #58A0DE 3px, #2B70C7 39px, #2763B4 39px);
   background: linear-gradient(#4B91D7 1px, #5FA9E4 1px, #5FA9E4 2px, #58A0DE 3px, #2B70C7 39px, #2763B4 39px);
   color: #FFF;
   text-shadow: 0 1px rgba(0, 0, 0, 0.3);
 }
 .fileListItemTitle {
   display: block;
   padding-top: 6px;
   font-size: 12px;
@@ -308,34 +308,31 @@ body {
   top: 0;
   right: 0;
   bottom: 0;
   left: 0;
   visibility: hidden;
   opacity: 0;
   pointer-events: none;
   background: rgba(120, 120, 120, 0.2);
-  -moz-transition: 200ms ease-in-out;
-  -moz-transition-property: visibility, opacity;
-  -webkit-transition: 200ms ease-in-out;
-  -webkit-transition-property: visibility, opacity;
+  transition: 200ms ease-in-out;
+  transition-property: visibility, opacity;
 }
 .busyCover.busy {
   visibility: visible;
   opacity: 1;
 }
 .busyCover::before {
   content: url(../images/throbber.svg);
   position: absolute;
   top: 50%;
   left: 50%;
   margin: -12px;
 }
 label {
-  -webkit-user-select: none;
   -moz-user-select: none;
 }
 .videoPane {
   background-color: white;
   width: 100%;
 }
 .video {
   display: block;
deleted file mode 100755
deleted file mode 100755
--- a/browser/devtools/responsivedesign/CmdResize.jsm
+++ b/browser/devtools/responsivedesign/CmdResize.jsm
@@ -30,16 +30,35 @@ gcli.addCommand({
 
 gcli.addCommand({
   name: 'resize toggle',
   buttonId: "command-button-responsive",
   buttonClass: "command-button",
   tooltipText: gcli.lookup("resizeModeToggleTooltip"),
   description: gcli.lookup('resizeModeToggleDesc'),
   manual: gcli.lookup('resizeModeManual'),
+  state: {
+    isChecked: function(aTarget) {
+      let browserWindow = aTarget.tab.ownerDocument.defaultView;
+      let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
+      return mgr.isActiveForTab(aTarget.tab);
+    },
+    onChange: function(aTarget, aChangeHandler) {
+      let browserWindow = aTarget.tab.ownerDocument.defaultView;
+      let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
+      mgr.on("on", aChangeHandler);
+      mgr.on("off", aChangeHandler);
+    },
+    offChange: function(aTarget, aChangeHandler) {
+      let browserWindow = aTarget.tab.ownerDocument.defaultView;
+      let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
+      mgr.off("on", aChangeHandler);
+      mgr.off("off", aChangeHandler);
+    },
+  },
   exec: gcli_cmd_resize
 });
 
 gcli.addCommand({
   name: 'resize to',
   description: gcli.lookup('resizeModeToDesc'),
   params: [
     {
--- a/browser/devtools/responsivedesign/responsivedesign.jsm
+++ b/browser/devtools/responsivedesign/responsivedesign.jsm
@@ -30,39 +30,48 @@ this.ResponsiveUIManager = {
    *
    * @param aWindow the main window.
    * @param aTab the tab targeted.
    */
   toggle: function(aWindow, aTab) {
     if (aTab.__responsiveUI) {
       aTab.__responsiveUI.close();
     } else {
-      aTab.__responsiveUI = new ResponsiveUI(aWindow, aTab);
+      new ResponsiveUI(aWindow, aTab);
     }
   },
 
   /**
+   * Returns true if responsive view is active for the provided tab.
+   *
+   * @param aTab the tab targeted.
+   */
+  isActiveForTab: function(aTab) {
+    return !!aTab.__responsiveUI;
+  },
+
+  /**
    * Handle gcli commands.
    *
    * @param aWindow the browser window.
    * @param aTab the tab targeted.
    * @param aCommand the command name.
    * @param aArgs command arguments.
    */
   handleGcliCommand: function(aWindow, aTab, aCommand, aArgs) {
     switch (aCommand) {
       case "resize to":
         if (!aTab.__responsiveUI) {
-          aTab.__responsiveUI = new ResponsiveUI(aWindow, aTab);
+          new ResponsiveUI(aWindow, aTab);
         }
         aTab.__responsiveUI.setSize(aArgs.width, aArgs.height);
         break;
       case "resize on":
         if (!aTab.__responsiveUI) {
-          aTab.__responsiveUI = new ResponsiveUI(aWindow, aTab);
+          new ResponsiveUI(aWindow, aTab);
         }
         break;
       case "resize off":
         if (aTab.__responsiveUI) {
           aTab.__responsiveUI.close();
         }
         break;
       case "resize toggle":
@@ -162,16 +171,18 @@ function ResponsiveUI(aWindow, aTab)
     if (Services.prefs.getBoolPref("devtools.responsiveUI.rotate")) {
       this.rotate();
     }
   } catch(e) {}
 
   if (this._floatingScrollbars)
     switchToFloatingScrollbars(this.tab);
 
+  this.tab.__responsiveUI = this;
+
   ResponsiveUIManager.emit("on", this.tab, this);
 }
 
 ResponsiveUI.prototype = {
   _transitionsEnabled: true,
   _floatingScrollbars: false, // See bug 799471
   get transitionsEnabled() this._transitionsEnabled,
   set transitionsEnabled(aValue) {
--- a/browser/devtools/shared/DeveloperToolbar.jsm
+++ b/browser/devtools/shared/DeveloperToolbar.jsm
@@ -23,17 +23,17 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 
 XPCOMUtils.defineLazyModuleGetter(this, "CmdCommands",
                                   "resource:///modules/devtools/CmdCmd.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "PageErrorListener",
                                   "resource://gre/modules/devtools/WebConsoleUtils.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "prefBranch", function() {
-  var prefService = Components.classes["@mozilla.org/preferences-service;1"]
+  let prefService = Components.classes["@mozilla.org/preferences-service;1"]
           .getService(Components.interfaces.nsIPrefService);
   return prefService.getBranch(null)
           .QueryInterface(Components.interfaces.nsIPrefBranch2);
 });
 
 /**
  * A collection of utilities to help working with commands
  */
@@ -46,32 +46,36 @@ this.CommandUtils = {
     let value = prefBranch.getComplexValue(aPref,
                                Components.interfaces.nsISupportsString).data;
     return JSON.parse(value);
   },
 
   /**
    * A toolbarSpec is an array of buttonSpecs. A buttonSpec is an array of
    * strings each of which is a GCLI command (including args if needed).
+   *
+   * Warning: this method uses the unload event of the window that owns the
+   * buttons that are of type checkbox. this means that we don't properly
+   * unregister event handlers until the window is destroyed.
    */
-  createButtons: function CU_createButtons(toolbarSpec, document, requisition) {
-    var reply = [];
+  createButtons: function CU_createButtons(toolbarSpec, target, document, requisition) {
+    let reply = [];
 
     toolbarSpec.forEach(function(buttonSpec) {
-      var button = document.createElement("toolbarbutton");
+      let button = document.createElement("toolbarbutton");
       reply.push(button);
 
       if (typeof buttonSpec == "string") {
         buttonSpec = { typed: buttonSpec };
       }
       // Ask GCLI to parse the typed string (doesn't execute it)
       requisition.update(buttonSpec.typed);
 
       // Ignore invalid commands
-      var command = requisition.commandAssignment.value;
+      let command = requisition.commandAssignment.value;
       if (command == null) {
         // TODO: Have a broken icon
         // button.icon = 'Broken';
         button.setAttribute("label", "X");
         button.setAttribute("tooltip", "Unknown command: " + buttonSpec.typed);
         button.setAttribute("disabled", "true");
       }
       else {
@@ -96,25 +100,34 @@ this.CommandUtils = {
           }
           else {
             console.error('incomplete commands not yet supported');
           }
           */
         }, false);
 
         // Allow the command button to be toggleable
-        /*
-        if (command.checkedState) {
-          button.setAttribute("type", "checkbox");
-          button.setAttribute("checked", command.checkedState.get() ? "true" : "false");
-          command.checkedState.on("change", function() {
-            button.checked = command.checkedState.get();
-          });
+        if (command.state) {
+          button.setAttribute("autocheck", false);
+          let onChange = function(event, eventTab) {
+            if (eventTab == target.tab) {
+              if (command.state.isChecked(target)) {
+                button.setAttribute("checked", true);
+              }
+              else if (button.hasAttribute("checked")) {
+                button.removeAttribute("checked");
+              }
+            }
+          };
+          command.state.onChange(target, onChange);
+          onChange(null, target.tab);
+          document.defaultView.addEventListener("unload", function() {
+            command.state.offChange(target, onChange);
+          }, false);
         }
-        */
       }
     });
 
     requisition.update('');
 
     return reply;
   }
 };
@@ -187,17 +200,17 @@ DeveloperToolbar.prototype.NOTIFICATIONS
  */
 Object.defineProperty(DeveloperToolbar.prototype, 'visible', {
   get: function DT_visible() {
     return !this._element.hidden;
   },
   enumerable: true
 });
 
-var _gSequenceId = 0;
+let _gSequenceId = 0;
 
 /**
  * Getter for a unique ID.
  */
 Object.defineProperty(DeveloperToolbar.prototype, 'sequenceId', {
   get: function DT_visible() {
     return _gSequenceId++;
   },
@@ -234,18 +247,18 @@ DeveloperToolbar.prototype.focus = funct
  * Called from browser.xul in response to menu-click or keyboard shortcut to
  * toggle the toolbar
  */
 DeveloperToolbar.prototype.focusToggle = function DT_focusToggle()
 {
   if (this.visible) {
     // If we have focus then the active element is the HTML input contained
     // inside the xul input element
-    var active = this._chromeWindow.document.activeElement;
-    var position = this._input.compareDocumentPosition(active);
+    let active = this._chromeWindow.document.activeElement;
+    let position = this._input.compareDocumentPosition(active);
     if (position & Node.DOCUMENT_POSITION_CONTAINED_BY) {
       this.hide();
     }
     else {
       this._input.focus();
     }
   } else {
     this.show(true);
@@ -438,17 +451,22 @@ DeveloperToolbar.prototype.hide = functi
   this._notify(NOTIFICATIONS.HIDE);
 };
 
 /**
  * Hide the developer toolbar
  */
 DeveloperToolbar.prototype.destroy = function DT_destroy()
 {
+  if (this._lastState == NOTIFICATIONS.HIDE) {
+    return;
+  }
+
   this._chromeWindow.getBrowser().tabContainer.removeEventListener("TabSelect", this, false);
+  this._chromeWindow.getBrowser().tabContainer.removeEventListener("TabClose", this, false);
   this._chromeWindow.getBrowser().removeEventListener("load", this, true); 
   this._chromeWindow.getBrowser().removeEventListener("beforeunload", this, true);
 
   let tabs = this._chromeWindow.getBrowser().tabs;
   Array.prototype.forEach.call(tabs, this._stopErrorsCount, this);
 
   this.display.focusManager.removeMonitoredElement(this.outputPanel._frame);
   this.display.focusManager.removeMonitoredElement(this._element);
@@ -465,16 +483,18 @@ DeveloperToolbar.prototype.destroy = fun
   // leaks as a belt-and-braces approach, however this prevents our DOM node
   // hunter from looking in all the nooks and crannies, so it's better if we
   // can be leak-free without
   /*
   delete this.display;
   delete this.outputPanel;
   delete this.tooltipPanel;
   */
+
+  this._lastState = NOTIFICATIONS.HIDE;
 };
 
 /**
  * Utility for sending notifications
  * @param aTopic a NOTIFICATION constant
  */
 DeveloperToolbar.prototype._notify = function DT_notify(aTopic)
 {
--- a/browser/devtools/shared/VariablesView.jsm
+++ b/browser/devtools/shared/VariablesView.jsm
@@ -1678,22 +1678,21 @@ VariablesView.prototype.commitHierarchy 
     if (!changed) {
       continue;
     }
 
     // Apply an attribute determining the flash type and duration.
     // Dispatch this action after all the nodes have been drawn, so that
     // the transition efects can take place.
     this.window.setTimeout(function(aTarget) {
-      aTarget.setAttribute("changed", "");
-
       aTarget.addEventListener("transitionend", function onEvent() {
         aTarget.removeEventListener("transitionend", onEvent, false);
         aTarget.removeAttribute("changed");
       }, false);
+      aTarget.setAttribute("changed", "");
     }.bind(this, currVariable.target), LAZY_EMPTY_DELAY + 1);
   }
 };
 
 // Some variables are likely to contain a very large number of properties.
 // It would be a bad idea to re-expand them or perform expensive operations.
 VariablesView.prototype.commitHierarchyIgnoredItems = Object.create(null, {
   "window": { value: true },
--- a/browser/devtools/styleeditor/StyleEditorChrome.jsm
+++ b/browser/devtools/styleeditor/StyleEditorChrome.jsm
@@ -395,17 +395,17 @@ StyleEditorChrome.prototype = {
       // We are in the main initialization phase so we wait for the editor
       // containing the target stylesheet to be added and select the target
       // stylesheet, optionally moving the cursor to a selected line.
       let self = this;
       this.addChromeListener({
         onEditorAdded: function SEC_selectSheet_onEditorAdded(aChrome, aEditor) {
           let sheet = self._styleSheetToSelect.sheet;
           if ((sheet && aEditor.styleSheet == sheet) ||
-              aEditor.styleSheetIndex == 0) {
+              (aEditor.styleSheetIndex == 0 && sheet == null)) {
             aChrome.removeChromeListener(this);
             select(aEditor);
           }
         }
       });
     } else if (aSheet) {
       // We are already initialized and a stylesheet has been specified. Here
       // we iterate through the editors and select the one containing the target
--- a/browser/devtools/styleinspector/CssHtmlTree.jsm
+++ b/browser/devtools/styleinspector/CssHtmlTree.jsm
@@ -57,17 +57,17 @@ function UpdateProcess(aWin, aGenerator,
 }
 
 UpdateProcess.prototype = {
   /**
    * Schedule a new batch on the main loop.
    */
   schedule: function UP_schedule()
   {
-    if (this.cancelled) {
+    if (this.canceled) {
       return;
     }
     this._timeout = this.win.setTimeout(this._timeoutHandler.bind(this), 0);
   },
 
   /**
    * Cancel the running process.  onItem will not be called again,
    * and onCancel will be called.
@@ -95,17 +95,17 @@ UpdateProcess.prototype = {
       }
       throw e;
     }
   },
 
   _runBatch: function Y_runBatch()
   {
     let time = Date.now();
-    while(!this.cancelled) {
+    while(!this.canceled) {
       // Continue until iter.next() throws...
       let next = this.iter.next();
       this.onItem(next[1]);
       if ((Date.now() - time) > this.threshold) {
         this.onBatch();
         return;
       }
     }
@@ -142,17 +142,16 @@ this.CssHtmlTree = function CssHtmlTree(
 
   this.styleDocument.addEventListener("copy", this.siBoundCopy);
   this.styleDocument.addEventListener("mousedown", this.siFocusWindow);
 
   // Nodes used in templating
   this.root = this.styleDocument.getElementById("root");
   this.templateRoot = this.styleDocument.getElementById("templateRoot");
   this.propertyContainer = this.styleDocument.getElementById("propertyContainer");
-  this.panel = aStyleInspector.panel;
 
   // No results text.
   this.noResults = this.styleDocument.getElementById("noResults");
 
   // The element that we're inspecting, and the document that it comes from.
   this.viewedElement = null;
   this.createStyleViews();
   this.createContextMenu();
@@ -252,16 +251,23 @@ CssHtmlTree.prototype = {
    * @param {nsIDOMElement} aElement The highlighted node to get styles for.
    */
   highlight: function CssHtmlTree_highlight(aElement)
   {
     this.viewedElement = aElement;
     this._unmatchedProperties = null;
     this._matchedProperties = null;
 
+    if (!aElement) {
+      if (this._refreshProcess) {
+        this._refreshProcess.cancel();
+      }
+      return;
+    }
+
     if (this.htmlComplete) {
       this.refreshSourceFilter();
       this.refreshPanel();
     } else {
       if (this._refreshProcess) {
         this._refreshProcess.cancel();
       }
 
--- a/browser/devtools/styleinspector/StyleInspector.jsm
+++ b/browser/devtools/styleinspector/StyleInspector.jsm
@@ -75,16 +75,17 @@ this.RuleViewTool = function RVT_RuleVie
       viewSourceUtils.viewSource(href, null, contentDoc, line);
     }
   }.bind(this);
 
   this.view.element.addEventListener("CssRuleViewCSSLinkClicked",
                                      this._cssLinkHandler);
 
   this._onSelect = this.onSelect.bind(this);
+  this.inspector.selection.on("detached", this._onSelect);
   this.inspector.selection.on("new-node", this._onSelect);
   this.refresh = this.refresh.bind(this);
   this.inspector.on("layout-change", this.refresh);
   this.inspector.sidebar.on("ruleview-selected", this.refresh);
   this.inspector.selection.on("pseudoclass", this.refresh);
   if (this.inspector.highlighter) {
     this.inspector.highlighter.on("locked", this._onSelect);
   }
@@ -154,16 +155,17 @@ this.ComputedViewTool = function CVT_Com
   this.inspector = aInspector;
   this.window = aWindow;
   this.document = aWindow.document;
   this.outerIFrame = aIFrame;
   this.cssLogic = new CssLogic();
   this.view = new CssHtmlTree(this);
 
   this._onSelect = this.onSelect.bind(this);
+  this.inspector.selection.on("detached", this._onSelect);
   this.inspector.selection.on("new-node", this._onSelect);
   if (this.inspector.highlighter) {
     this.inspector.highlighter.on("locked", this._onSelect);
   }
   this.refresh = this.refresh.bind(this);
   this.inspector.on("layout-change", this.refresh);
   this.inspector.sidebar.on("computedview-selected", this.refresh);
   this.inspector.selection.on("pseudoclass", this.refresh);
@@ -174,17 +176,17 @@ this.ComputedViewTool = function CVT_Com
   this.onSelect();
 }
 
 ComputedViewTool.prototype = {
   onSelect: function CVT_onSelect(aEvent)
   {
     if (!this.inspector.selection.isConnected() ||
         !this.inspector.selection.isElementNode()) {
-      // FIXME: We should hide view's content
+      this.view.highlight(null);
       return;
     }
 
     if (!aEvent || aEvent == "new-node") {
       if (this.inspector.selection.reason == "highlighter") {
         // FIXME: We should hide view's content
       } else {
         this.cssLogic.highlight(this.inspector.selection.node);
--- a/browser/devtools/tilt/CmdTilt.jsm
+++ b/browser/devtools/tilt/CmdTilt.jsm
@@ -1,20 +1,20 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 this.EXPORTED_SYMBOLS = [ ];
 
+Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
 Components.utils.import("resource:///modules/devtools/gcli.jsm");
-Components.utils.import("resource:///modules/HUDService.jsm");
-Components.utils.import("resource:///modules/devtools/Tilt.jsm");
 
-
+XPCOMUtils.defineLazyModuleGetter(this, "TiltManager",
+                                  "resource:///modules/devtools/Tilt.jsm");
 /**
  * 'tilt' command
  */
 gcli.addCommand({
   name: 'tilt',
   description: gcli.lookup("tiltDesc"),
   manual: gcli.lookup("tiltManual")
 });
@@ -41,16 +41,32 @@ gcli.addCommand({
  * 'tilt toggle' command
  */
 gcli.addCommand({
   name: "tilt toggle",
   buttonId: "command-button-tilt",
   buttonClass: "command-button",
   tooltipText: gcli.lookup("tiltToggleTooltip"),
   hidden: true,
+  state: {
+    isChecked: function(aTarget) {
+      let browserWindow = aTarget.tab.ownerDocument.defaultView;
+      return !!TiltManager.getTiltForBrowser(browserWindow).currentInstance;
+    },
+    onChange: function(aTarget, aChangeHandler) {
+      let browserWindow = aTarget.tab.ownerDocument.defaultView;
+      let tilt = TiltManager.getTiltForBrowser(browserWindow);
+      tilt.on("change", aChangeHandler);
+    },
+    offChange: function(aTarget, aChangeHandler) {
+      let browserWindow = aTarget.tab.ownerDocument.defaultView;
+      let tilt = TiltManager.getTiltForBrowser(browserWindow);
+      tilt.off("change", aChangeHandler);
+    },
+  },
   exec: function(args, context) {
     let chromeWindow = context.environment.chromeDocument.defaultView;
     let Tilt = TiltManager.getTiltForBrowser(chromeWindow);
     Tilt.toggle();
   }
 });
 
 
--- a/browser/devtools/tilt/Tilt.jsm
+++ b/browser/devtools/tilt/Tilt.jsm
@@ -41,16 +41,17 @@ const TILT_NOTIFICATIONS = {
 
   // Fires when a node is removed from the 3D mesh.
   NODE_REMOVED: "tilt-node-removed"
 };
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource:///modules/devtools/TiltGL.jsm");
 Cu.import("resource:///modules/devtools/TiltUtils.jsm");
+Cu.import("resource:///modules/devtools/EventEmitter.jsm");
 Cu.import("resource:///modules/devtools/TiltVisualizer.jsm");
 
 this.EXPORTED_SYMBOLS = ["TiltManager"];
 
 this.TiltManager = {
   _instances: new WeakMap(),
   getTiltForBrowser: function(aChromeWindow)
   {
@@ -82,16 +83,18 @@ this.Tilt = function Tilt(aWindow)
    */
   this.visualizers = {};
 
   /**
    * Shortcut for accessing notifications strings.
    */
   this.NOTIFICATIONS = TILT_NOTIFICATIONS;
 
+  EventEmitter.decorate(this);
+
   this.setup();
 }
 
 Tilt.prototype = {
 
   /**
    * Initializes a visualizer for the current tab or closes it if already open.
    */
@@ -123,16 +126,17 @@ Tilt.prototype = {
 
     // make sure the visualizer object was initialized properly
     if (!this.visualizers[id].isInitialized()) {
       this.destroy(id);
       this.failureCallback && this.failureCallback();
       return;
     }
 
+    this.emit("change", this.chromeWindow.gBrowser.selectedTab);
     Services.obs.notifyObservers(null, TILT_NOTIFICATIONS.INITIALIZING, null);
   },
 
   /**
    * Starts destroying a specific instance of the visualizer.
    *
    * @param {String} aId
    *                 the identifier of the instance in the visualizers array
@@ -178,16 +182,17 @@ Tilt.prototype = {
   _finish: function T__finish(aId)
   {
     this.visualizers[aId].removeOverlay();
     this.visualizers[aId].cleanup();
     this.visualizers[aId] = null;
 
     this._isDestroying = false;
     this.chromeWindow.gBrowser.selectedBrowser.focus();
+    this.emit("change", this.chromeWindow.gBrowser.selectedTab);
     Services.obs.notifyObservers(null, TILT_NOTIFICATIONS.DESTROYED, null);
   },
 
   /**
    * Handles the event fired when a tab is selected.
    */
   _onTabSelect: function T__onTabSelect()
   {
--- a/browser/devtools/webconsole/WebConsolePanel.jsm
+++ b/browser/devtools/webconsole/WebConsolePanel.jsm
@@ -25,20 +25,20 @@ function WebConsolePanel(iframeWindow, t
   EventEmitter.decorate(this);
 }
 
 WebConsolePanel.prototype = {
   /**
    * open is effectively an asynchronous constructor
    */
   open: function StyleEditor_open() {
-    let tab = this._toolbox._getHostTab();
     let parentDoc = this._frameWindow.document.defaultView.parent.document;
     let iframe = parentDoc.getElementById("toolbox-panel-iframe-webconsole");
-    this.hud = HUDService.activateHUDForContext(tab, iframe, this._toolbox.target);
+    this.hud = HUDService.activateHUDForContext(this.target.tab, iframe,
+                                                this._toolbox.target);
 
     let deferred = Promise.defer();
 
     let hudId = this.hud.hudId;
     let onOpen = function _onWebConsoleOpen(aSubject) {
       aSubject.QueryInterface(Ci.nsISupportsString);
       if (hudId == aSubject.data) {
         Services.obs.removeObserver(onOpen, "web-console-created");
--- a/browser/devtools/webconsole/test/Makefile.in
+++ b/browser/devtools/webconsole/test/Makefile.in
@@ -99,17 +99,17 @@ MOCHITEST_BROWSER_FILES = \
 	browser_webconsole_bug_659907_console_dir.js \
 	browser_webconsole_bug_664131_console_group.js \
 	browser_webconsole_bug_704295.js \
 	browser_webconsole_bug_658368_time_methods.js \
 	browser_webconsole_bug_764572_output_open_url.js \
 	browser_webconsole_bug_622303_persistent_filters.js \
 	browser_webconsole_bug_770099_bad_policyuri.js \
 	browser_webconsole_bug_770099_violation.js \
-	$(filter disabled-temporarily--bug-808264, browser_webconsole_bug_782653_CSS_links_in_Style_Editor.js) \
+	browser_webconsole_bug_782653_CSS_links_in_Style_Editor.js \
 	browser_cached_messages.js \
 	browser_bug664688_sandbox_update_after_navigation.js \
 	browser_result_format_as_string.js \
 	browser_webconsole_bug_737873_mixedcontent.js \
 	browser_output_breaks_after_console_dir_uninspectable.js \
 	browser_console_log_inspectable_object.js \
 	browser_bug_638949_copy_link_location.js \
 	browser_output_longstring_expand.js \
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -73,16 +73,17 @@
 #endif
 #ifdef XP_MACOSX
 @BINPATH@/@MOZ_CHILD_PROCESS_NAME@.app/
 @BINPATH@/@DLL_PREFIX@plugin_child_interpose@DLL_SUFFIX@
 #else
 @BINPATH@/@MOZ_CHILD_PROCESS_NAME@
 #endif
 #ifdef XP_WIN32
+@BINPATH@/plugin-hang-ui@BIN_SUFFIX@
 #ifndef MOZ_DEBUG
 #if MOZ_MSVC_REDIST == 1400
 @BINPATH@/Microsoft.VC80.CRT.manifest
 @BINPATH@/msvcm80.dll
 @BINPATH@/msvcp80.dll
 @BINPATH@/msvcr80.dll
 #elif MOZ_MSVC_REDIST == 1500
 @BINPATH@/Microsoft.VC90.CRT.manifest
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -229,21 +229,22 @@ These should match what Safari and other
 <!ENTITY scratchpad.keycode           "VK_F4">
 <!ENTITY scratchpad.keytext           "F4">
 
 <!ENTITY devToolbarCloseButton.tooltiptext "Close Developer Toolbar">
 <!ENTITY devToolbarMenu.label              "Developer Toolbar">
 <!ENTITY devToolbarMenu.accesskey          "v">
 <!ENTITY devToolbar.keycode                "VK_F2">
 <!ENTITY devToolbar.keytext                "F2">
-<!ENTITY devToolbarToolsButton.label       "Toggle Toolbox">
+<!ENTITY devToolboxMenuItem.label          "Toggle Tools">
+<!ENTITY devToolboxMenuItem.accesskey      "T">
+
+<!ENTITY devToolbarToolsButton.tooltip     "Toggle developer tools">
 <!ENTITY devToolbarOtherToolsButton.label  "More Tools">
 
-<!ENTITY devToolbox.accesskey              "B">
-
 <!ENTITY getMoreDevtoolsCmd.label        "Get More Tools">
 <!ENTITY getMoreDevtoolsCmd.accesskey    "M">
 
 <!ENTITY fileMenu.label         "File"> 
 <!ENTITY fileMenu.accesskey       "F">
 <!ENTITY newNavigatorCmd.label        "New Window">
 <!ENTITY newNavigatorCmd.key        "N">
 <!ENTITY newNavigatorCmd.accesskey      "N">
--- a/browser/locales/en-US/chrome/browser/downloads/downloads.dtd
+++ b/browser/locales/en-US/chrome/browser/downloads/downloads.dtd
@@ -59,16 +59,21 @@
 <!ENTITY cmd.goToDownloadPage.label       "Go To Download Page">
 <!ENTITY cmd.goToDownloadPage.accesskey   "G">
 <!ENTITY cmd.copyDownloadLink.label       "Copy Download Link">
 <!ENTITY cmd.copyDownloadLink.accesskey   "L">
 <!ENTITY cmd.removeFromHistory.label      "Remove From History">
 <!ENTITY cmd.removeFromHistory.accesskey  "e">
 <!ENTITY cmd.clearList.label              "Clear List">
 <!ENTITY cmd.clearList.accesskey          "a">
+<!ENTITY cmd.clearDownloads.label         "Clear Downloads">
+<!ENTITY cmd.clearDownloads.accesskey     "D">
 
 <!-- LOCALIZATION NOTE (downloadsHistory.label, downloadsHistory.accesskey):
      This string is shown at the bottom of the Downloads Panel when all the
      downloads fit in the available space, or when there are no downloads in
      the panel at all.
      -->
 <!ENTITY downloadsHistory.label           "Show All Downloads">
 <!ENTITY downloadsHistory.accesskey       "S">
+
+<!ENTITY clearDownloadsButton.label       "Clear Downloads">
+<!ENTITY clearDownloadsButton.tooltip     "Clears completed, canceled and failed downloads">
--- a/browser/themes/gnomestripe/browser.css
+++ b/browser/themes/gnomestripe/browser.css
@@ -50,17 +50,17 @@
 }
 
 #nav-bar:not(:-moz-lwtheme),
 #nav-bar[collapsed=true] + toolbar:not(:-moz-lwtheme),
 #nav-bar[collapsed=true] + #customToolbars + #PersonalToolbar:not(:-moz-lwtheme),
 #nav-bar[tabsontop=true],
 #nav-bar[tabsontop=true][collapsed=true]:not([customizing]) + toolbar,
 #nav-bar[tabsontop=true][collapsed=true]:not([customizing]) + #customToolbars + #PersonalToolbar {
-  background-image: -moz-linear-gradient(@toolbarHighlight@, rgba(255,255,255,0));
+  background-image: linear-gradient(@toolbarHighlight@, rgba(255,255,255,0));
 }
 
 #personal-bookmarks {
   min-height: 29px;
 }
 
 #browser-bottombox {
   /* opaque for layers optimization */
@@ -1052,20 +1052,20 @@ toolbar[iconsize="small"] #feed-button {
   -moz-padding-start: 2px;
   -moz-padding-end: 5px;
 }
 
 #urlbar[pageproxystate="valid"] > #identity-box.verifiedIdentity {
   background-color: #fff;
   color: hsl(92,100%,30%);
   -moz-margin-end: 4px;
-  background-image: -moz-linear-gradient(hsla(92,81%,16%,0),
-                                         hsla(92,81%,16%,.2) 25%,
-                                         hsla(92,81%,16%,.2) 75%,
-                                         hsla(92,81%,16%,0));
+  background-image: linear-gradient(hsla(92,81%,16%,0),
+                                    hsla(92,81%,16%,.2) 25%,
+                                    hsla(92,81%,16%,.2) 75%,
+                                    hsla(92,81%,16%,0));
   background-position: right;
   background-size: 1px;
   background-repeat: no-repeat;
 }
 
 #identity-box.verifiedIdentity:-moz-locale-dir(rtl) {
   background-position: left;
 }
@@ -1476,17 +1476,17 @@ richlistitem[type~="action"][actiontype=
 #editBMPanel_folderTree {
   min-width: 27em;
 }
 
 .panel-promo-box {
   margin: 8px -10px -10px -10px;
   padding: 8px 10px;
   border-top: 1px solid ThreeDShadow;
-  background-image: -moz-linear-gradient(hsla(0,0%,0%,.15), hsla(0,0%,0%,.08) 6px);
+  background-image: linear-gradient(hsla(0,0%,0%,.15), hsla(0,0%,0%,.08) 6px);
 }
 
 .panel-promo-icon {
   list-style-image: url("chrome://browser/skin/sync-notification-24.png");
   -moz-margin-end: 10px;
   vertical-align: middle;
 }
 
@@ -1535,87 +1535,86 @@ richlistitem[type~="action"][actiontype=
   box-shadow: 0 -1px 0 rgba(0,0,0,.1) inset;
 }
 
 #TabsToolbar[tabsontop=true]:not(:-moz-lwtheme):-moz-system-metric(menubar-drag) {
   -moz-binding: url("chrome://global/content/bindings/toolbar.xml#toolbar-drag");
 }
 
 #TabsToolbar[tabsontop=false] {
-  background-image:
-    -moz-linear-gradient(bottom, rgba(0,0,0,.3) 1px, rgba(0,0,0,.05) 1px, transparent 50%);
+  background-image: linear-gradient(to top, rgba(0,0,0,.3) 1px, rgba(0,0,0,.05) 1px, transparent 50%);
 }
 
 .tabbrowser-tab,
 .tabs-newtab-button {
   position: static;
   -moz-appearance: none;
-  background: -moz-linear-gradient(hsla(0,0%,100%,.2), hsla(0,0%,45%,.2) 2px, hsla(0,0%,32%,.2) 80%);
+  background: linear-gradient(hsla(0,0%,100%,.2), hsla(0,0%,45%,.2) 2px, hsla(0,0%,32%,.2) 80%);
   background-origin: border-box;
   background-position: 1px 2px;
   background-size: 100% calc(100% - 2px);
   background-repeat: no-repeat;
   color: inherit;
   margin: 0;
   padding: 0;
   border-width: 4px 5px 3px 6px;
   border-style: solid;
   -moz-border-image: url(tabbrowser/tab.png) 4 5 3 6 fill repeat stretch;
   border-radius: 10px 8px 0 0;
   min-height: 25px; /* reserve space for the sometimes hidden close button */
 }
 
 .tabbrowser-tab:hover,
 .tabs-newtab-button:hover {
-  background-image: -moz-linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,100%,.2) 4px, hsla(0,0%,75%,.2) 80%);
+  background-image: linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,100%,.2) 4px, hsla(0,0%,75%,.2) 80%);
 }
 
 .tabbrowser-tab[selected="true"] {
-  background-image: -moz-linear-gradient(@selectedTabHighlight@, @toolbarHighlight@ 32%),
-                    -moz-linear-gradient(-moz-dialog, -moz-dialog);
+  background-image: linear-gradient(@selectedTabHighlight@, @toolbarHighlight@ 32%),
+                    linear-gradient(-moz-dialog, -moz-dialog);
   color: -moz-dialogtext;
 }
 
 #main-window[tabsontop=false]:not([disablechrome]) .tabbrowser-tab[selected=true]:not(:-moz-lwtheme) {
-  background-image: -moz-linear-gradient(bottom, rgba(0,0,0,.3) 1px, transparent 1px),
-                    -moz-linear-gradient(@selectedTabHighlight@, @toolbarHighlight@ 32%),
-                    -moz-linear-gradient(-moz-dialog, -moz-dialog);
+  background-image: linear-gradient(to top, rgba(0,0,0,.3) 1px, transparent 1px),
+                    linear-gradient(@selectedTabHighlight@, @toolbarHighlight@ 32%),
+                    linear-gradient(-moz-dialog, -moz-dialog);
 }
 
 .tabbrowser-tab[selected="true"]:-moz-lwtheme {
-  background-image: -moz-linear-gradient(@selectedTabHighlight@, @toolbarHighlight@ 32%);
+  background-image: linear-gradient(@selectedTabHighlight@, @toolbarHighlight@ 32%);
   color: inherit;
 }
 
 .tabbrowser-tab:-moz-lwtheme-brighttext:not([selected="true"]),
 .tabs-newtab-button:-moz-lwtheme-brighttext {
-  background-image: -moz-linear-gradient(hsla(0,0%,60%,.6), hsla(0,0%,40%,.6) 4px, hsla(0,0%,30%,.6) 80%);
+  background-image: linear-gradient(hsla(0,0%,60%,.6), hsla(0,0%,40%,.6) 4px, hsla(0,0%,30%,.6) 80%);
 }
 
 .tabbrowser-tab:-moz-lwtheme-brighttext:not([selected="true"]):hover,
 .tabs-newtab-button:-moz-lwtheme-brighttext:hover {
-  background-image: -moz-linear-gradient(hsla(0,0%,80%,.6), hsla(0,0%,60%,.6) 4px, hsla(0,0%,45%,.6) 80%);
+  background-image: linear-gradient(hsla(0,0%,80%,.6), hsla(0,0%,60%,.6) 4px, hsla(0,0%,45%,.6) 80%);
 }
 
 .tabbrowser-tab:-moz-lwtheme-darktext:not([selected="true"]),
 .tabs-newtab-button:-moz-lwtheme-darktext {
-  background-image: -moz-linear-gradient(hsla(0,0%,100%,.5), hsla(0,0%,60%,.5) 4px, hsla(0,0%,45%,.5) 80%);
+  background-image: linear-gradient(hsla(0,0%,100%,.5), hsla(0,0%,60%,.5) 4px, hsla(0,0%,45%,.5) 80%);
 }
 
 .tabbrowser-tab:-moz-lwtheme-darktext:not([selected="true"]):hover,
 .tabs-newtab-button:-moz-lwtheme-darktext:hover {
-  background-image: -moz-linear-gradient(hsla(0,0%,100%,.5), hsla(0,0%,80%,.5) 4px, hsla(0,0%,60%,.5) 80%);
+  background-image: linear-gradient(hsla(0,0%,100%,.5), hsla(0,0%,80%,.5) 4px, hsla(0,0%,60%,.5) 80%);
 }
 
 .tabbrowser-tab[pinned][titlechanged]:not([selected="true"]) {
-  background-image: -moz-radial-gradient(center 3px, circle cover, rgba(233,242,252,1) 3%, rgba(172,206,255,.75) 40%, rgba(87,151,201,.5) 80%, rgba(87,151,201,0));
+  background-image: radial-gradient(circle farthest-corner at 50% 3px, rgba(233,242,252,1) 3%, rgba(172,206,255,.75) 40%, rgba(87,151,201,.5) 80%, rgba(87,151,201,0));
 }
 .tabbrowser-tab[pinned][titlechanged]:not([selected="true"]):hover {
-  background-image: -moz-linear-gradient(hsla(0,0%,100%,.8), hsla(0,0%,100%,.6) 2px, hsla(0,0%,75%,.2) 80%),
-                    -moz-radial-gradient(center 3px, circle cover, rgba(233,242,252,1) 3%, rgba(172,206,255,.75) 40%, rgba(87,151,201,.5) 80%, rgba(87,151,201,0));
+  background-image: linear-gradient(hsla(0,0%,100%,.8), hsla(0,0%,100%,.6) 2px, hsla(0,0%,75%,.2) 80%),
+                    radial-gradient(circle farthest-corner at 50% 3px, rgba(233,242,252,1) 3%, rgba(172,206,255,.75) 40%, rgba(87,151,201,.5) 80%, rgba(87,151,201,0));
 }
 
 #tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-tab > .tab-stack > .tab-content[pinned] {
   min-height: 18px; /* corresponds to the max. height of non-textual tab contents, i.e. the tab close button */
 }
 
 .tabbrowser-tab:focus > .tab-stack {
   outline: 1px dotted;
@@ -1934,19 +1933,19 @@ toolbar[mode="text"] toolbarbutton.chevr
   min-height: 0;
   -moz-appearance: none;
   background-color: transparent;
   border: none;
 }
 
 #addon-bar[customizing] > #status-bar {
   opacity: .5;
-  background-image: -moz-repeating-linear-gradient(-45deg,
-                                                   rgba(255,255,255,.3), rgba(255,255,255,.3) 5px,
-                                                   rgba(0,0,0,.3) 5px, rgba(0,0,0,.3) 10px);
+  background-image: repeating-linear-gradient(135deg,
+                                              rgba(255,255,255,.3), rgba(255,255,255,.3) 5px,
+                                              rgba(0,0,0,.3) 5px, rgba(0,0,0,.3) 10px);
 }
 
 #status-bar > statusbarpanel {
   border-width: 0;
   -moz-appearance: none;
 }
 
 #addonbar-closebutton {
@@ -1958,17 +1957,17 @@ toolbar[mode="text"] toolbarbutton.chevr
   margin-bottom: -2px;
 }
 
 /* Status panel */
 
 .statuspanel-label {
   margin: 0;
   padding: 2px 4px;
-  background: -moz-linear-gradient(white, #ddd);
+  background: linear-gradient(#fff, #ddd);
   border: 1px none #ccc;
   border-top-style: solid;
   color: #333;
   text-shadow: none;
 }
 
 .statuspanel-label:-moz-locale-dir(ltr):not([mirror]),
 .statuspanel-label:-moz-locale-dir(rtl)[mirror] {
@@ -2004,17 +2003,17 @@ toolbar[mode="text"] toolbarbutton.chevr
 }
 
 /* Highlighter - Node Infobar */
 
 .highlighter-nodeinfobar {
   color: hsl(200, 100%, 65%);
   border: 1px solid hsla(210, 19%, 63%, .5);
   border-radius: 3px;
-  background: -moz-linear-gradient(hsl(209, 18%, 30%), hsl(210, 24%, 16%)) no-repeat padding-box;
+  background: linear-gradient(hsl(209, 18%, 30%), hsl(210, 24%, 16%)) no-repeat padding-box;
 }
 
 /* Highlighter - Node Infobar - text */
 
 .highlighter-nodeinfobar-text {
   /* 100% - size of the buttons and margins */
   max-width: calc(100% - 2 * (26px + 6px));
   padding-bottom: 1px;
@@ -2088,25 +2087,25 @@ html|*.highlighter-nodeinfobar-pseudo-cl
   background-repeat: no-repeat;
 }
 
 .highlighter-nodeinfobar-arrow-top {
   margin-bottom: -8px;
   margin-top: 8px;
   border-right-color: hsla(210, 19%, 63%, .5);
   border-top-color: hsla(210, 19%, 63%, .5);
-  background-image: -moz-linear-gradient(bottom left, transparent 50%, hsl(209, 18%, 30%) 50%);
+  background-image: linear-gradient(to top right, transparent 50%, hsl(209, 18%, 30%) 50%);
 }
 
 .highlighter-nodeinfobar-arrow-bottom {
   margin-top: -8px;
   margin-bottom: 8px;
   border-left-color: hsla(210, 19%, 63%, .5);
   border-bottom-color: hsla(210, 19%, 63%, .5);
-  background-image: -moz-linear-gradient(top right, transparent 50%, hsl(210, 24%, 16%) 50%);
+  background-image: linear-gradient(to bottom left, transparent 50%, hsl(210, 24%, 16%) 50%);
 }
 
 .highlighter-nodeinfobar-container[position="top"] > .highlighter-nodeinfobar,
 .highlighter-nodeinfobar-container[position="overlap"] > .highlighter-nodeinfobar {
   box-shadow: 0 1px 0 hsla(0, 0%, 100%, .1) inset;
 }
 
 .highlighter-nodeinfobar-container[hide-arrow] > .highlighter-nodeinfobar {
@@ -2285,16 +2284,24 @@ html|*#gcli-output-frame {
 }
 
 .web-console-frame[animated] {
   transition: height 100ms;
 }
 
 /* Developer Toolbar */
 
+#developer-toolbar-toolbox-button {
+  min-width: 18px;
+}
+
+#developer-toolbar-toolbox-button > .toolbarbutton-text {
+  display: none;
+}
+
 .developer-toolbar-button {
   -moz-appearance: none;
   min-width: 78px;
   min-height: 22px;
   text-shadow: 0 -1px 0 hsla(210,8%,5%,.45);
   border-radius: 3px;
   color: inherit;
   border: 1px solid transparent;
@@ -2327,17 +2334,17 @@ html|*#gcli-output-frame {
 }
 
 /* Error counter */
 
 #developer-toolbar-toolbox-button[error-count]:before {
   color: #FDF3DE;
   min-width: 16px;
   text-shadow: none;
-  background-image: -moz-linear-gradient(top, #B4211B, #8A1915);
+  background-image: linear-gradient(#B4211B, #8A1915);
   border-radius: 1px;
   -moz-margin-end: 2px;
 }
 
 #social-toolbar-item {
   -moz-box-orient: horizontal;
 }
 
--- a/browser/themes/gnomestripe/devtools/toolbox.css
+++ b/browser/themes/gnomestripe/devtools/toolbox.css
@@ -67,64 +67,64 @@
 .command-button:hover {
   background-color: hsla(206,37%,4%,.2);
 }
 .command-button:hover:active {
   background-color: hsla(206,37%,4%,.4);
 }
 
 #command-button-responsive {
-  list-style-image: url(chrome://browser/skin/devtools/command-responsivemode.png);
+  list-style-image: url("chrome://browser/skin/devtools/command-responsivemode.png");
   -moz-image-region: rect(0px, 16px, 16px, 0px);
 }
 #command-button-responsive:hover {
   -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
 #command-button-responsive:hover:active {
   -moz-image-region: rect(0px, 48px, 16px, 32px);
 }
 #command-button-responsive[checked=true] {
   -moz-image-region: rect(0px, 64px, 16px, 48px);
 }
 
 #command-button-tilt {
-  list-style-image: url(chrome://browser/skin/devtools/command-tilt.png);
+  list-style-image: url("chrome://browser/skin/devtools/command-tilt.png");
   -moz-image-region: rect(0px, 16px, 16px, 0px);
 }
 #command-button-tilt:hover {
   -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
 
 #command-button-tilt:hover:active {
   -moz-image-region: rect(0px, 48px, 16px, 32px);
 }
 
 #command-button-tilt[checked=true] {
   -moz-image-region: rect(0px, 64px, 16px, 48px);
 }
 
 #command-button-scratchpad {
-  list-style-image: url(chrome://browser/skin/devtools/command-scratchpad.png);
+  list-style-image: url("chrome://browser/skin/devtools/command-scratchpad.png");
   -moz-image-region: rect(0px, 16px, 16px, 0px);
 }
 
 #command-button-scratchpad:hover {
   -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
 
 #command-button-scratchpad:hover:active {
   -moz-image-region: rect(0px, 48px, 16px, 32px);
 }
 
 
 /* Tabs */
 
 .devtools-tabbar {
   -moz-appearance: none;
-  background-image: url(background-noise-toolbar.png),
+  background-image: url("background-noise-toolbar.png"),
                     linear-gradient(#303840, #2d3640);
   border-top: 1px solid #060a0d;
   box-shadow: 0 1px 0 hsla(204,45%,98%,.05) inset,
               0 -1px 0 hsla(206,37%,4%,.1) inset;
   min-height: 32px;
   padding: 0;
 }
 
@@ -168,34 +168,34 @@
 .radio-icon {
   opacity: 1;
 }
 
 .devtools-tab:hover {
   background-image: linear-gradient(hsla(204,45%,98%,.05), hsla(204,45%,98%,.1)),
                     linear-gradient(hsla(204,45%,98%,.05), hsla(204,45%,98%,.1)),
                     linear-gradient(hsla(206,37%,4%,.1), hsla(206,37%,4%,.2));
-  background size: 1px 100%,
+  background-size: 1px 100%,
                    1px 100%,
                    100%;
   background-repeat: no-repeat,
                      no-repeat,
                      repeat-x;
   background-position: left, right;
   color: #ced3d9;
 }
 .devtools-tab:hover:active {
   background-color: hsla(206,37%,4%,.2);
   color: #f5f7fa;
 }
 
 .devtools-tab[selected=true] {
   color: #f5f7fa;
-  background-image: radial-gradient(ellipse farthest-corner at center top, #9fdfff, hsla(200,100%,70%,.3)),
-                    radial-gradient(ellipse farthest-side at center top, hsla(200,100%,70%,.4), hsla(200,100%,70%,0)),
+  background-image: radial-gradient(farthest-corner at center top, #9fdfff, hsla(200,100%,70%,.3)),
+                    radial-gradient(farthest-side at center top, hsla(200,100%,70%,.4), hsla(200,100%,70%,0)),
                     linear-gradient(hsla(204,45%,98%,.05), hsla(204,45%,98%,.1)),
                     linear-gradient(hsla(204,45%,98%,.02), hsla(204,45%,98%,.04)),
                     linear-gradient(hsla(206,37%,4%,.2), hsla(206,37%,4%,.3));
   background-size: 100% 1px,
                    100% 5px,
                    1px 100%,
                    1px 100%,
                    100%;
index 0c8eafda08acf20c21eeef8ae63cc6630590084b..8bc5b3acaed5f864dd06c36ae9350dd15524df9a
GIT binary patch
literal 224
zc%17D@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`%ROBjLn>~qy==&JC_sSaLMDr}
zw6}Ku3r-b90S*?X#t)qLj$9IsxEWp9;c_hUh7yaD-A}RgGg4>dIT~^P+UNgqf8*?$
zR_=ZG8gHKtZ4hXZY}ICaFZcAJ`GVJ0hdt6OeT^<`TbsD#ybiPPWr;kNE2X(R1Oq~+
zCNBA|!<-r^<z{uVcv9mcjWY@{h85ox%J(x?&YP{UxZvOm*&TCZSWaxx@qA^zjQ<Zq
Y&ZE>XZOY%IfKF!cboFyt=akR{086x1>Hq)$
index a1a51b8d8f580a7c97b449aed9ae60207a6a5373..d125789fbce71eff4c4d5af890dd5ed6a862c50e
GIT binary patch
literal 1097
zc$@)A1h)H$P)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF000CKNkl<Zc-rln
zO-NKx7>2J<M35Cx;G$Iv>1WX@+|)K&xHF<fD~V{Kjzl>A>p1?8qvQBHo1st`+_Vs4
zCZR<Vf(#^5x-<g8n83)A%;|P}-<W|*I-WB_I>*~tJZR&5_rBkA&pr3tLxyEp|20~G
z7N7-a0a}0-pap0FT0pL}wzlRIEnvR{@Zcrw?d`GN-rjG0eSMbS?>|s@PMrIz*Xw<b
zEY}WF01tc*0g@vlBi8u%xD^V8@&eDz49tQ|cXJfL@0|p<K&enbOH0cYnBN{99c2I|
zU>0QBLbhUH*bp_(@053UcW?Cf_gftu9hOi)S65eLXlRHhRtjWd1Cx>h__qS!VdJTb
z$&n-$fG>UGup1j2QwnDC`Fx4y=4QjjZq4)aqZsbtfq?-w&w9dou>cG;Q?cgl4VVG}
z{H(C8t?fl15U@8dFQBKVhlNVQY)wr~h7Egm{<{cIt~Y3&BW6cEF0RxFP*wo4WfH*O
zFJb=rFgQ54SH08-pgkpFw#LRr!v-_+=XEr{j^;)6VgYz$Si{4^N`h=V1b{MpzJ=yx
z>K!M*g{x`?gF)GPsdWIKxk|!p4Gj$jC_wXm-qX19+0=^#bar-HFsdZHhwJO>k72@_
zN;RKVJ$gIb0<fy%Fn)#Sxv2Tv1z@?!gDVN1?`d+WmwOk$LV_o7B<M{}0M^h>L<^7-
zfE^f4HjV_ni3Q+Iid#~S1igs`csw3%95@p6CKSN^Grl)F67;48$ZU%8z1fkVH=zJ-
zDRIs1NYI;50C!fn-c}L5&2c@?pE=c|x5F)f&+%|L9LK#(3Hu^|n+!a-ilm2d>BPju
zOWe<Vxyh;?y$J<yvw_1*Ntms=x|%s}Oixcg!xjCBQISo(lmMDllC*%7gsZc&vriyl
z3oAUCdglnRNw~1MxERFkuz^+HzY%~fC%!c)3A4FeF2e>h7p<(UcrgkR5W$IZuX?e7
zy1F_ZL`j&fs;bJck<NW8kw`qoME9OEJ!E967YnGZtyNY4vSkuLj&E*m-p6b2JIwZ!
zkh1`j#R|d(%*x72!^YqFkC>);Clm_JVYqYcZ?C67sfEzzRH0HJ6W0Oj0s*7|+>Asb
zQAqfOy6gmC>u8Qc2(zkEFcY%9uBfOmY%p^sN}|!|6q-&#+@E8(-EOgfcs%|9McbHB
zm1&+?km<+5!a{i#0?6h0`S}p)Ki1UL@DVB$K+eQsu}KspX&v?$ATRLT$iOR?oSB(<
zifpH|6hO{{hihwVzSY%Lzl;EKacOBOh;5{|SUh~e<nuir@Z8L>yu2JhreZdnQGl2e
zpiou-IR|coN5GvYc<wTAmd);h{=dRnfEJ(yXaQP)7N7-a0a}0-kQ=`NqXz$3vl*3;
P00000NkvXXu0mjfSQP=H
--- a/browser/themes/pinstripe/browser.css
+++ b/browser/themes/pinstripe/browser.css
@@ -72,17 +72,17 @@ toolbar[mode="full"] toolbarseparator {
 #nav-bar[tabsontop=true],
 #nav-bar[tabsontop=true][collapsed=true]:not([customizing]) + toolbar,
 #nav-bar[tabsontop=true][collapsed=true]:not([customizing]) + #customToolbars + #PersonalToolbar {
   -moz-appearance: none;
   margin-top: 0; /* don't overlay the bottom border of the tabs toolbar */
   padding-top: 4px !important;
   border-bottom: 1px solid rgba(0, 0, 0, 0.57);
   background-color: -moz-mac-chrome-active;
-  background-image: -moz-linear-gradient(rgba(255,255,255,.43), rgba(255,255,255,0)) !important; /* override lwtheme style */
+  background-image: linear-gradient(rgba(255,255,255,.43), rgba(255,255,255,0)) !important; /* override lwtheme style */
   background-origin: border-box !important;
 }
 
 #PersonalToolbar:-moz-lwtheme,
 #nav-bar[tabsontop=true]:-moz-lwtheme,
 #nav-bar[tabsontop=true][collapsed=true]:not([customizing]) + toolbar:-moz-lwtheme,
 #nav-bar[tabsontop=true][collapsed=true]:not([customizing]) + #customToolbars + #PersonalToolbar:-moz-lwtheme {
   background-color: transparent;
@@ -366,26 +366,26 @@ toolbarbutton.bookmark-item > menupopup 
 .toolbarbutton-1:not([type="menu-button"]):-moz-lwtheme,
 .toolbarbutton-1 > .toolbarbutton-menubutton-button:-moz-lwtheme,
 .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker:-moz-lwtheme,
 #restore-button:-moz-lwtheme {
   -moz-appearance: none;
   padding: 0 3px;
   border: 1px solid rgba(0, 0, 0, 0.4);
   border-radius: @toolbarbuttonCornerRadius@;
-  background: -moz-linear-gradient(rgba(255,255,255,0.5), rgba(255,255,255,0.2) 50%, rgba(255,255,255,0.1) 50%, rgba(255,255,255,0.2)) repeat-x;
+  background: linear-gradient(rgba(255,255,255,0.5), rgba(255,255,255,0.2) 50%, rgba(255,255,255,0.1) 50%, rgba(255,255,255,0.2)) repeat-x;
   background-origin: border-box;
   box-shadow: inset 0 1px rgba(255,255,255,0.3), 0 1px rgba(255,255,255,0.2);
 }
 
 .toolbarbutton-1:not([type="menu-button"]):-moz-lwtheme-darktext,
 .toolbarbutton-1 > .toolbarbutton-menubutton-button:-moz-lwtheme-darktext,
 .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker:-moz-lwtheme-darktext,
 #restore-button:-moz-lwtheme-darktext {
-  background-image: -moz-linear-gradient(rgba(255,255,255,0.3), rgba(50,50,50,0.2) 50%, rgba(0,0,0,0.2) 50%, rgba(0,0,0,0.13));
+  background-image: linear-gradient(rgba(255,255,255,0.3), rgba(50,50,50,0.2) 50%, rgba(0,0,0,0.2) 50%, rgba(0,0,0,0.13));
 }
 
 .toolbarbutton-1[type="menu-button"] {
   padding: 0;
 }
 
 .toolbarbutton-1 > .toolbarbutton-menubutton-button,
 .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
@@ -645,17 +645,17 @@ toolbar[mode="icons"] #forward-button {
 
 #navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #forward-button {
   clip-path: url(chrome://browser/content/browser.xul#pinstripe-keyhole-forward-clip-path);
 }
 
 @conditionalForwardWithUrlbar@ > #forward-button:not(:-moz-lwtheme) {
   -moz-appearance: none;
   -moz-padding-start: 2px;
-  background: -moz-linear-gradient(hsl(0,0%,99%), hsl(0,0%,67%)) padding-box;
+  background: linear-gradient(hsl(0,0%,99%), hsl(0,0%,67%)) padding-box;
   border: 1px solid;
   border-color: hsl(0,0%,31%) hsla(0,0%,29%,.6) hsl(0,0%,27%);
   box-shadow: inset 0 1px 0 hsla(0,0%,100%,.35),
               0 1px 0 hsla(0,0%,100%,.2);
 }
 
 @conditionalForwardWithUrlbar@ > #forward-button {
   border-radius: 0;
@@ -667,44 +667,44 @@ toolbar[mode="icons"] #forward-button {
   -moz-padding-end: 0;
 }
 
 @conditionalForwardWithUrlbar@:not([switchingtabs]) > #forward-button {
   transition: opacity @forwardTransitionLength@ ease-out;
 }
 
 @conditionalForwardWithUrlbar@ > #forward-button:hover:active:not(:-moz-lwtheme) {
-  background-image: -moz-linear-gradient(hsl(0,0%,74%), hsl(0,0%,61%));
+  background-image: linear-gradient(hsl(0,0%,74%), hsl(0,0%,61%));
   box-shadow: inset rgba(0,0,0,.3) 0 -6px 10px,
               inset #000 0 1px 3px,
               inset rgba(0,0,0,.2) 0 1px 3px,
               0 1px 0 hsla(0,0%,100%,.2);
 }
 
 @conditionalForwardWithUrlbar@ > #forward-button:-moz-window-inactive:not(:-moz-lwtheme) {
   border-color: hsl(0,0%,64%) hsl(0,0%,65%) hsl(0,0%,66%);
-  background-image: -moz-linear-gradient(hsl(0,0%,99%), hsl(0,0%,82%));
+  background-image: linear-gradient(hsl(0,0%,99%), hsl(0,0%,82%));
   box-shadow: inset 0 1px 0 hsla(0,0%,100%,.35);
 }
 
 @conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] {
   opacity: 0;
 }
 
 @media (-moz-mac-lion-theme) {
   @conditionalForwardWithUrlbar@ > #forward-button:not(:-moz-lwtheme) {
-    background-image: -moz-linear-gradient(hsla(0,0%,100%,.73), hsla(0,0%,100%,.05) 85%);
+    background-image: linear-gradient(hsla(0,0%,100%,.73), hsla(0,0%,100%,.05) 85%);
     border-color: hsla(0,0%,0%,.35) hsla(0,0%,0%,.25) hsla(0,0%,0%,.2);
     box-shadow: inset 0 1px 0 hsla(0,0%,100%,.2),
                 inset 0 0 1px hsla(0,0%,100%,.1),
                 0 1px 0 hsla(0,0%,100%,.2);
   }
 
   @conditionalForwardWithUrlbar@ > #forward-button:hover:active:not(:-moz-lwtheme) {
-    background-image: -moz-linear-gradient(hsla(0,0%,60%,.37), hsla(0,0%,100%,.35) 95%);
+    background-image: linear-gradient(hsla(0,0%,60%,.37), hsla(0,0%,100%,.35) 95%);
     border-color: hsla(0,0%,0%,.43) hsla(0,0%,0%,.25) hsla(0,0%,0%,.37);
     box-shadow: inset 0 1px 0 hsla(0,0%,0%,.02),
                 inset 0 1px 2px hsla(0,0%,0%,.2),
                 0 1px 0 hsla(0,0%,100%,.2);
   }
 
   @conditionalForwardWithUrlbar@ > #forward-button:-moz-window-inactive:not(:-moz-lwtheme) {
     background-image: none;
@@ -1121,17 +1121,17 @@ toolbar[mode="icons"] #zoom-in-button {
   border: 1px solid;
   border-color: #626262 #787878 #8c8c8c;
   background-clip: padding-box;
 }
 
 @media (-moz-mac-lion-theme) {
   #urlbar,
   .searchbar-textbox {
-    background-image: -moz-linear-gradient(hsl(0,0%,97%), hsl(0,0%,100%));
+    background-image: linear-gradient(hsl(0,0%,97%), hsl(0,0%,100%));
     border-color: hsla(0,0%,0%,.35) hsla(0,0%,0%,.25) hsla(0,0%,0%,.15);
     box-shadow: 0 1px 0 hsla(0,0%,100%,.2),
                 inset 0 0 1px hsla(0,0%,0%,.05),
                 inset 0 1px 2px hsla(0,0%,0%,.1);
   }
 }
 
 @media not all and (-moz-mac-lion-theme) {
@@ -1252,20 +1252,20 @@ toolbar[mode="icons"] #zoom-in-button {
 
 @conditionalForwardWithUrlbar@[forwarddisabled]:not(:hover) + #urlbar-container > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) {
   padding-right: 10.01px;
 }
 
 #urlbar[pageproxystate="valid"] > #identity-box.verifiedIdentity {
   color: hsl(92,100%,30%);
   -moz-padding-end: 4px;
-  background-image: -moz-linear-gradient(hsla(92,81%,16%,0),
-                                         hsla(92,81%,16%,.2) 25%,
-                                         hsla(92,81%,16%,.2) 75%,
-                                         hsla(92,81%,16%,0));
+  background-image: linear-gradient(hsla(92,81%,16%,0),
+                                    hsla(92,81%,16%,.2) 25%,
+                                    hsla(92,81%,16%,.2) 75%,
+                                    hsla(92,81%,16%,0));
   background-position: right;
   background-size: 1px;
   background-repeat: no-repeat;
 }
 
 #identity-box.verifiedIdentity:-moz-locale-dir(rtl) {
   background-position: left;
 }
@@ -1291,17 +1291,17 @@ toolbar[mode="icons"] #zoom-in-button {
   padding: 0 3px;
   list-style-image: url("chrome://browser/skin/urlbar-history-dropmarker.png");
   -moz-image-region: rect(0px, 11px, 14px, 0px);
 }
 
 .urlbar-history-dropmarker[open="true"],
 .urlbar-history-dropmarker:hover:active {
   -moz-image-region: rect(0px, 22px, 14px, 11px);
-  background-image: -moz-radial-gradient(center, circle closest-side, hsla(205,100%,70%,.3), hsla(205,100%,70%,0));
+  background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.3), hsla(205,100%,70%,0));
 }
 
 @media (min-resolution: 2dppx) {
   .urlbar-history-dropmarker {
     list-style-image: url("chrome://browser/skin/urlbar-history-dropmarker@2x.png");
     -moz-image-region: rect(0px, 22px, 28px, 0px);
   }
 
@@ -1320,17 +1320,17 @@ toolbar[mode="icons"] #zoom-in-button {
 }
 
 .urlbar-icon {
   padding: 0 3px;
 }
 
 .urlbar-icon[open="true"],
 .urlbar-icon:hover:active {
-  background-image: -moz-radial-gradient(center, circle closest-side, hsla(205,100%,70%,.3), hsla(205,100%,70%,0));
+  background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.3), hsla(205,100%,70%,0));
 }
 
 #urlbar-search-splitter {
   min-width: 8px;
   width: 8px;
   background-image: none;
   margin: 0 -4px;
   position: relative;
@@ -1526,17 +1526,17 @@ window[tabsontop="false"] richlistitem[t
   margin: 0;
   -moz-padding-start: 2px;
   -moz-padding-end: 1px;
   background-origin: border-box;
   list-style-image: url("chrome://browser/skin/reload-stop-go.png");
 }
 
 #urlbar > toolbarbutton:not([disabled]):hover:active {
-  background-image: -moz-radial-gradient(center, circle closest-side, hsla(205,100%,70%,.3), hsla(205,100%,70%,0));
+  background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.3), hsla(205,100%,70%,0));
 }
 
 #go-button {
   padding: 0 3px;
 }
 
 #go-button,
 #urlbar-go-button {
@@ -2266,37 +2266,37 @@ toolbarbutton.chevron > .toolbarbutton-m
 .tab-background-start[selected="true"]:not(:-moz-lwtheme):-moz-window-inactive,
 .tab-background-middle[selected="true"]:not(:-moz-lwtheme):-moz-window-inactive,
 .tab-background-end[selected="true"]:not(:-moz-lwtheme):-moz-window-inactive {
   background-color: -moz-mac-chrome-inactive;
 }
 
 .tab-background-start[pinned][titlechanged]:not([selected="true"]),
 .tab-background-end[pinned][titlechanged]:not([selected="true"]) {
-  background-image: -moz-linear-gradient(rgba(148,205,253,.2), rgba(148,205,253,.2)) !important;
+  background-image: linear-gradient(rgba(148,205,253,.2), rgba(148,205,253,.2)) !important;
 }
 
 @TABSONBOTTOM_TAB_STACK@ > .tab-background > .tab-background-middle[pinned][titlechanged]:not([selected="true"]) {
-  background-image: -moz-radial-gradient(center 99%, circle cover, rgba(254,254,255,1) 3%, rgba(210,235,255,.9) 12%, rgba(148,205,253,.6) 30%, rgba(148,205,253,.2) 70%);
+  background-image: radial-gradient(circle farthest-corner at 50% 99%, rgba(254,254,255,1) 3%, rgba(210,235,255,.9) 12%, rgba(148,205,253,.6) 30%, rgba(148,205,253,.2) 70%);
 }
 
 @TABSONTOP_TAB_STACK@ > .tab-background > .tab-background-middle[pinned][titlechanged]:not([selected="true"]) {
-  background-image: -moz-radial-gradient(center 2px, circle cover, rgba(254,254,255,1) 3%, rgba(210,235,255,.9) 12%, rgba(148,205,253,.6) 30%, rgba(148,205,253,.2) 70%);
+  background-image: radial-gradient(circle farthest-corner at 50% 2px, rgba(254,254,255,1) 3%, rgba(210,235,255,.9) 12%, rgba(148,205,253,.6) 30%, rgba(148,205,253,.2) 70%);
 }
 
 .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-start:-moz-lwtheme-brighttext:not([selected="true"]),
 .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle:-moz-lwtheme-brighttext:not([selected="true"]),
 .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-end:-moz-lwtheme-brighttext:not([selected="true"]) {
-  background-image: -moz-linear-gradient(hsla(0,0%,40%,.6), hsla(0,0%,30%,.6) 50%);
+  background-image: linear-gradient(hsla(0,0%,40%,.6), hsla(0,0%,30%,.6) 50%);
 }
 
 .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-start:-moz-lwtheme-darktext:not([selected="true"]),
 .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle:-moz-lwtheme-darktext:not([selected="true"]),
 .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-end:-moz-lwtheme-darktext:not([selected="true"]) {
-  background-image: -moz-linear-gradient(hsla(0,0%,60%,.5), hsla(0,0%,45%,.5) 50%);
+  background-image: linear-gradient(hsla(0,0%,60%,.5), hsla(0,0%,45%,.5) 50%);
 }
 
 @TABSONTOP_TAB_STACK@ > .tab-content,
 @TABSONTOP_NEWTAB_BUTTON@ > .toolbarbutton-icon {
   -moz-border-image: url(chrome://browser/skin/tabbrowser/tab-top-normal-active.png) 0 11 fill repeat stretch;
 }
 
 @TABSONTOP_TAB@:hover > .tab-stack > .tab-content:not([selected="true"]),
@@ -2418,22 +2418,22 @@ toolbarbutton.chevron > .toolbarbutton-m
 
 /* For tabs-on-top, only fill the bottom 2px with the chrome background
  * color, so that the borders in tabbar-top-bg-*.png can mix with it.
  * In the top 24px the unified toolbar (from the ::before above) will show.
  */
 #TabsToolbar[tabsontop="true"]:not(:-moz-lwtheme) {
   padding-bottom: 2px;
   background: url(chrome://browser/skin/tabbrowser/tabbar-top-bg-active.png),
-              -moz-linear-gradient(bottom, -moz-mac-chrome-active 2px, transparent 2px);
+              linear-gradient(to top, -moz-mac-chrome-active 2px, transparent 2px);
 }
 
 #TabsToolbar[tabsontop="true"]:not(:-moz-lwtheme):-moz-window-inactive {
   background: url(chrome://browser/skin/tabbrowser/tabbar-top-bg-inactive.png),
-              -moz-linear-gradient(bottom, -moz-mac-chrome-inactive 2px, transparent 2px);
+              linear-gradient(to top, -moz-mac-chrome-inactive 2px, transparent 2px);
 }
 
 /* In tabs-on-bottom mode, fill the whole toolbar with the chrome
  * background color.
  */
 #TabsToolbar[tabsontop="false"]:not(:-moz-lwtheme) {
   background: url(chrome://browser/skin/tabbrowser/tabbar-bottom-bg-active.png) -moz-mac-chrome-active;
 }
@@ -2663,26 +2663,26 @@ toolbarbutton.chevron > .toolbarbutton-m
   padding: 0 1px;
 }
 
 .tabbrowser-arrowscrollbox > .scrollbutton-up:not([disabled]):hover,
 .tabbrowser-arrowscrollbox > .scrollbutton-down:not([disabled]):hover,
 :-moz-any(#TabsToolbar, #addon-bar) .toolbarbutton-1:not([type="menu-button"]):not([disabled]):not([open]):hover,
 :-moz-any(#TabsToolbar, #addon-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled]):hover,
 :-moz-any(#TabsToolbar, #addon-bar) .toolbarbutton-1:not([disabled]):not([buttonover]):hover > .toolbarbutton-menubutton-dropmarker {
-  background-image: -moz-linear-gradient(transparent, rgba(0,0,0,.15)) !important;
+  background-image: linear-gradient(transparent, rgba(0,0,0,.15)) !important;
 }
 
 .tabbrowser-arrowscrollbox > .scrollbutton-up:not([disabled]):hover:active,
 .tabbrowser-arrowscrollbox > .scrollbutton-down:not([disabled]):hover:active,
 :-moz-any(#TabsToolbar, #addon-bar) .toolbarbutton-1:not([type="menu-button"]):not([disabled]):hover:active,
 :-moz-any(#TabsToolbar, #addon-bar) .toolbarbutton-1[type="menu"][open],
 :-moz-any(#TabsToolbar, #addon-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled]):hover:active,
 :-moz-any(#TabsToolbar, #addon-bar) .toolbarbutton-1[open]:not([disabled]):hover > .toolbarbutton-menubutton-dropmarker {
-  background-image: -moz-linear-gradient(transparent, rgba(0,0,0,.3)) !important;
+  background-image: linear-gradient(transparent, rgba(0,0,0,.3)) !important;
 }
 
 .tabs-newtab-button,
 #TabsToolbar > #new-tab-button,
 #TabsToolbar > toolbarpaletteitem > #new-tab-button {
   list-style-image: url(chrome://browser/skin/tabbrowser/newtab.png);
   -moz-image-region: rect(0, 18px, 20px, 0);
 }
@@ -3342,19 +3342,19 @@ toolbarbutton.chevron > .toolbarbutton-m
 
 #status-bar {
   -moz-appearance: none;
   padding-right: 0;
 }
 
 #addon-bar[customizing] > #status-bar {
   opacity: .5;
-  background-image: -moz-repeating-linear-gradient(-45deg,
-                                                   rgba(255,255,255,.3), rgba(255,255,255,.3) 5px,
-                                                   rgba(0,0,0,.3) 5px, rgba(0,0,0,.3) 10px);
+  background-image: repeating-linear-gradient(135deg,
+                                              rgba(255,255,255,.3), rgba(255,255,255,.3) 5px,
+                                              rgba(0,0,0,.3) 5px, rgba(0,0,0,.3) 10px);
 }
 
 #status-bar > statusbarpanel {
   border-width: 0;
   -moz-appearance: none;
 }
 
 #addonbar-closebutton {
@@ -3392,17 +3392,17 @@ toolbarbutton.chevron > .toolbarbutton-m
   }
 }
 
 /* Status panel */
 
 .statuspanel-label {
   margin: 0;
   padding: 2px 4px;
-  background: -moz-linear-gradient(white, #ddd);
+  background: linear-gradient(#fff, #ddd);
   border: 1px none #ccc;
   border-top-style: solid;
   color: #333;
   text-shadow: none;
 }
 
 .statuspanel-label:-moz-locale-dir(ltr):not([mirror]),
 .statuspanel-label:-moz-locale-dir(rtl)[mirror] {
@@ -3465,17 +3465,17 @@ toolbarbutton.chevron > .toolbarbutton-m
 }
 
 /* Highlighter - Node Infobar */
 
 .highlighter-nodeinfobar {
   color: hsl(200, 100%, 65%);
   border: 1px solid hsla(210, 19%, 63%, .5);
   border-radius: 3px;
-  background: -moz-linear-gradient(hsl(209, 18%, 30%), hsl(210, 24%, 16%)) no-repeat padding-box;
+  background: linear-gradient(hsl(209, 18%, 30%), hsl(210, 24%, 16%)) no-repeat padding-box;
 }
 
 /* Highlighter - Node Infobar - text */
 
 .highlighter-nodeinfobar-text {
   /* 100% - size of the buttons + margins */
   max-width: calc(100% - 2 * (26px + 6px));
   padding-bottom: 1px;
@@ -3550,25 +3550,25 @@ html|*.highlighter-nodeinfobar-pseudo-cl
   background-repeat: no-repeat;
 }
 
 .highlighter-nodeinfobar-arrow-top {
   margin-bottom: -8px;
   margin-top: 8px;
   border-right-color: hsla(210, 19%, 63%, .5);
   border-top-color: hsla(210, 19%, 63%, .5);
-  background-image: -moz-linear-gradient(bottom left, transparent 50%, hsl(209, 18%, 30%) 50%);
+  background-image: linear-gradient(to top right, transparent 50%, hsl(209, 18%, 30%) 50%);
 }
 
 .highlighter-nodeinfobar-arrow-bottom {
   margin-top: -8px;
   margin-bottom: 8px;
   border-left-color: hsla(210, 19%, 63%, .5);
   border-bottom-color: hsla(210, 19%, 63%, .5);
-  background-image: -moz-linear-gradient(top right, transparent 50%, hsl(210, 24%, 16%) 50%);
+  background-image: linear-gradient(to bottom left, transparent 50%, hsl(210, 24%, 16%) 50%);
 }
 
 .highlighter-nodeinfobar-container[position="top"] > .highlighter-nodeinfobar,
 .highlighter-nodeinfobar-container[position="overlap"] > .highlighter-nodeinfobar {
   box-shadow: 0 1px 0 hsla(0, 0%, 100%, .1) inset;
 }
 
 .highlighter-nodeinfobar-container[hide-arrow] > .highlighter-nodeinfobar {
@@ -3747,16 +3747,24 @@ html|*#gcli-output-frame {
 }
 
 .web-console-frame[animated] {
   transition: height 100ms;
 }
 
 /* Developer Toolbar */
 
+#developer-toolbar-toolbox-button {
+  min-width: 18px;
+}
+
+#developer-toolbar-toolbox-button > .toolbarbutton-text {
+  display: none;
+}
+
 .developer-toolbar-button {
   -moz-appearance: none;
   min-width: 78px;
   min-height: 22px;
   text-shadow: 0 -1px 0 hsla(210,8%,5%,.45);
   border-radius: @toolbarbuttonCornerRadius@;
   color: inherit;
   border: 1px solid transparent;
@@ -3784,17 +3792,17 @@ html|*#gcli-output-frame {
 }
 
 /* Error counter */
 
 #developer-toolbar-toolbox-button[error-count]:before {
   color: #FDF3DE;
   min-width: 16px;
   text-shadow: none;
-  background-image: -moz-linear-gradient(top, #B4211B, #8A1915);
+  background-image: linear-gradient(#B4211B, #8A1915);
   border-radius: 1px;
 }
 
 /* === social toolbar button === */
 
 /* button icon for the service */
 #social-toolbar-item {
   -moz-box-orient: horizontal;
--- a/browser/themes/pinstripe/devtools/toolbox.css
+++ b/browser/themes/pinstripe/devtools/toolbox.css
@@ -54,64 +54,64 @@
 .command-button:hover {
   background-color: hsla(206,37%,4%,.2);
 }
 .command-button:hover:active {
   background-color: hsla(206,37%,4%,.4);
 }
 
 #command-button-responsive {
-  list-style-image: url(chrome://browser/skin/devtools/command-responsivemode.png);
+  list-style-image: url("chrome://browser/skin/devtools/command-responsivemode.png");
   -moz-image-region: rect(0px, 16px, 16px, 0px);
 }
 #command-button-responsive:hover {
   -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
 #command-button-responsive:hover:active {
   -moz-image-region: rect(0px, 48px, 16px, 32px);
 }
 #command-button-responsive[checked=true] {
   -moz-image-region: rect(0px, 64px, 16px, 48px);
 }
 
 #command-button-tilt {
-  list-style-image: url(chrome://browser/skin/devtools/command-tilt.png);
+  list-style-image: url("chrome://browser/skin/devtools/command-tilt.png");
   -moz-image-region: rect(0px, 16px, 16px, 0px);
 }
 #command-button-tilt:hover {
   -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
 
 #command-button-tilt:hover:active {
   -moz-image-region: rect(0px, 48px, 16px, 32px);
 }
 
 #command-button-tilt[checked=true] {
   -moz-image-region: rect(0px, 64px, 16px, 48px);
 }
 
 #command-button-scratchpad {
-  list-style-image: url(chrome://browser/skin/devtools/command-scratchpad.png);
+  list-style-image: url("chrome://browser/skin/devtools/command-scratchpad.png");
   -moz-image-region: rect(0px, 16px, 16px, 0px);
 }
 
 #command-button-scratchpad:hover {
   -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
 
 #command-button-scratchpad:hover:active {
   -moz-image-region: rect(0px, 48px, 16px, 32px);
 }
 
 
 /* Tabs */
 
 .devtools-tabbar {
   -moz-appearance: none;
-  background-image: url(background-noise-toolbar.png),
+  background-image: url("background-noise-toolbar.png"),
                     linear-gradient(#303840, #2d3640);
   border-top: 1px solid #060a0d;
   box-shadow: 0 1px 0 hsla(204,45%,98%,.05) inset,
               0 -1px 0 hsla(206,37%,4%,.1) inset;
   min-height: 32px;
   padding: 0;
 }
 
@@ -152,34 +152,34 @@
 .devtools-tab[selected=true] > .radio-label-box > .radio-icon {
   opacity: 1;
 }
 
 .devtools-tab:hover {
   background-image: linear-gradient(hsla(204,45%,98%,.05), hsla(204,45%,98%,.1)),
                     linear-gradient(hsla(204,45%,98%,.05), hsla(204,45%,98%,.1)),
                     linear-gradient(hsla(206,37%,4%,.1), hsla(206,37%,4%,.2));
-  background size: 1px 100%,
+  background-size: 1px 100%,
                    1px 100%,
                    100%;
   background-repeat: no-repeat,
                      no-repeat,
                      repeat-x;
   background-position: left, right;
   color: #ced3d9;
 }
 .devtools-tab:hover:active {
   background-color: hsla(206,37%,4%,.2);
   color: #f5f7fa;
 }
 
 .devtools-tab[selected=true] {
   color: #f5f7fa;
-  background-image: radial-gradient(ellipse farthest-corner at center top, #9fdfff, hsla(200,100%,70%,.3)),
-                    radial-gradient(ellipse farthest-side at center top, hsla(200,100%,70%,.4), hsla(200,100%,70%,0)),
+  background-image: radial-gradient(farthest-corner at center top, #9fdfff, hsla(200,100%,70%,.3)),
+                    radial-gradient(farthest-side at center top, hsla(200,100%,70%,.4), hsla(200,100%,70%,0)),
                     linear-gradient(hsla(204,45%,98%,.05), hsla(204,45%,98%,.1)),
                     linear-gradient(hsla(204,45%,98%,.02), hsla(204,45%,98%,.04)),
                     linear-gradient(hsla(206,37%,4%,.2), hsla(206,37%,4%,.3));
   background-size: 100% 1px,
                    100% 5px,
                    1px 100%,
                    1px 100%,
                    100%;
--- a/browser/themes/pinstripe/downloads/contentAreaDownloadsView.css
+++ b/browser/themes/pinstripe/downloads/contentAreaDownloadsView.css
@@ -1,6 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 @import url("chrome://global/skin/inContentUI.css");
 
+.downloadButton {
+  box-shadow: none;
+}
+
+.downloadButton:not([disabled="true"]):hover:active,
+.downloadButton:not([disabled]):hover:active {
+  background: transparent;
+  border: none;
+  box-shadow: none;
+}
index 0c8eafda08acf20c21eeef8ae63cc6630590084b..8bc5b3acaed5f864dd06c36ae9350dd15524df9a
GIT binary patch
literal 224
zc%17D@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`%ROBjLn>~qy==&JC_sSaLMDr}
zw6}Ku3r-b90S*?X#t)qLj$9IsxEWp9;c_hUh7yaD-A}RgGg4>dIT~^P+UNgqf8*?$
zR_=ZG8gHKtZ4hXZY}ICaFZcAJ`GVJ0hdt6OeT^<`TbsD#ybiPPWr;kNE2X(R1Oq~+
zCNBA|!<-r^<z{uVcv9mcjWY@{h85ox%J(x?&YP{UxZvOm*&TCZSWaxx@qA^zjQ<Zq
Y&ZE>XZOY%IfKF!cboFyt=akR{086x1>Hq)$
index d13fb930a397810c8884b9882bbd5f6cb8ef8fcd..72d53e6d99366fab0c2b65044554b8c74e97e9a8
GIT binary patch
literal 367
zc$@)m0g(QQP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F80003tNkl<Zc-rmO
zJxat-6vc7D&Q_;Za0eEy!Nx_{xDE4RLPA19hI|z+KoD^X3oDo40^ESuh%kyGj>l6x
z;gK7s7%tHwfnPHR?)#Us2H;PP0b{`b3257PLf5n)tY|?uH2Lj8ZtJuy0-C0o5tLl^
zJ<i{E=#C%)>bia-D0ww^?fZN5V0IZ$RTVVxvu_{J+}dS8S(eab-94g@&MpI{(<wBW
zn<w<uv&(>@D4^_Y$tDBxJjZ}!K$c|~kPJxE6a$h0Ns?edG9Zp)3`hn<QG@}>fG`Z9
z>~zT{1A-ucCUf(cK6`c<;QKx_S$7ZVrL)Tb&-0*(pM86u9<5ylxUTz5Q1WC4nEShQ
zZ+02rIL-w@$$2-xys<^MBm>NNMRUT6-f2dgBEZ6ZWBgY<28;nez5z0dDd6-7ujl{(
N002ovPDHLkV1m(6ohASP
index a1a51b8d8f580a7c97b449aed9ae60207a6a5373..d125789fbce71eff4c4d5af890dd5ed6a862c50e
GIT binary patch
literal 1097
zc$@)A1h)H$P)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF000CKNkl<Zc-rln
zO-NKx7>2J<M35Cx;G$Iv>1WX@+|)K&xHF<fD~V{Kjzl>A>p1?8qvQBHo1st`+_Vs4
zCZR<Vf(#^5x-<g8n83)A%;|P}-<W|*I-WB_I>*~tJZR&5_rBkA&pr3tLxyEp|20~G
z7N7-a0a}0-pap0FT0pL}wzlRIEnvR{@Zcrw?d`GN-rjG0eSMbS?>|s@PMrIz*Xw<b
zEY}WF01tc*0g@vlBi8u%xD^V8@&eDz49tQ|cXJfL@0|p<K&enbOH0cYnBN{99c2I|
zU>0QBLbhUH*bp_(@053UcW?Cf_gftu9hOi)S65eLXlRHhRtjWd1Cx>h__qS!VdJTb
z$&n-$fG>UGup1j2QwnDC`Fx4y=4QjjZq4)aqZsbtfq?-w&w9dou>cG;Q?cgl4VVG}
z{H(C8t?fl15U@8dFQBKVhlNVQY)wr~h7Egm{<{cIt~Y3&BW6cEF0RxFP*wo4WfH*O
zFJb=rFgQ54SH08-pgkpFw#LRr!v-_+=XEr{j^;)6VgYz$Si{4^N`h=V1b{MpzJ=yx
z>K!M*g{x`?gF)GPsdWIKxk|!p4Gj$jC_wXm-qX19+0=^#bar-HFsdZHhwJO>k72@_
zN;RKVJ$gIb0<fy%Fn)#Sxv2Tv1z@?!gDVN1?`d+WmwOk$LV_o7B<M{}0M^h>L<^7-
zfE^f4HjV_ni3Q+Iid#~S1igs`csw3%95@p6CKSN^Grl)F67;48$ZU%8z1fkVH=zJ-
zDRIs1NYI;50C!fn-c}L5&2c@?pE=c|x5F)f&+%|L9LK#(3Hu^|n+!a-ilm2d>BPju
zOWe<Vxyh;?y$J<yvw_1*Ntms=x|%s}Oixcg!xjCBQISo(lmMDllC*%7gsZc&vriyl
z3oAUCdglnRNw~1MxERFkuz^+HzY%~fC%!c)3A4FeF2e>h7p<(UcrgkR5W$IZuX?e7
zy1F_ZL`j&fs;bJck<NW8kw`qoME9OEJ!E967YnGZtyNY4vSkuLj&E*m-p6b2JIwZ!
zkh1`j#R|d(%*x72!^YqFkC>);Clm_JVYqYcZ?C67sfEzzRH0HJ6W0Oj0s*7|+>Asb
zQAqfOy6gmC>u8Qc2(zkEFcY%9uBfOmY%p^sN}|!|6q-&#+@E8(-EOgfcs%|9McbHB
zm1&+?km<+5!a{i#0?6h0`S}p)Ki1UL@DVB$K+eQsu}KspX&v?$ATRLT$iOR?oSB(<
zifpH|6hO{{hihwVzSY%Lzl;EKacOBOh;5{|SUh~e<nuir@Z8L>yu2JhreZdnQGl2e
zpiou-IR|coN5GvYc<wTAmd);h{=dRnfEJ(yXaQP)7N7-a0a}0-kQ=`NqXz$3vl*3;
P00000NkvXXu0mjfSQP=H
--- a/browser/themes/winstripe/browser-aero.css
+++ b/browser/themes/winstripe/browser-aero.css
@@ -45,34 +45,34 @@
   #navigator-toolbox > toolbar:not(:-moz-lwtheme),
   #browser-bottombox:not(:-moz-lwtheme) {
     background-color: @customToolbarColor@;
   }
 
   .tabbrowser-tab:not(:-moz-lwtheme),
   .tabs-newtab-button:not(:-moz-lwtheme) {
     background-image: @toolbarShadowOnTab@, @bgTabTexture@,
-                      -moz-linear-gradient(@customToolbarColor@, @customToolbarColor@);
+                      linear-gradient(@customToolbarColor@, @customToolbarColor@);
   }
 
   .tabbrowser-tab:not(:-moz-lwtheme):hover,
   .tabs-newtab-button:not(:-moz-lwtheme):hover {
     background-image: @toolbarShadowOnTab@, @bgTabTextureHover@,
-                      -moz-linear-gradient(@customToolbarColor@, @customToolbarColor@);
+                      linear-gradient(@customToolbarColor@, @customToolbarColor@);
   }
 
   .tabbrowser-tab[selected="true"]:not(:-moz-lwtheme) {
-    background-image: -moz-linear-gradient(white, @toolbarHighlight@ 50%),