Merge mozilla-inbound and mozilla-central
authorMarco Bonardo <mbonardo@mozilla.com>
Wed, 04 Jan 2012 13:30:58 +0100
changeset 83753 ebe9f8508d67567f5bd6f1df664b8738421a8d0c
parent 83752 e4fe4d48518fd965c7fcd48142c54ace1d396d0e (current diff)
parent 83730 0eec6ba6a87aa3149854bb7680eff9ac0cb924f4 (diff)
child 83754 05785aed9ca1f8d7faf8c128b43b6065a196278d
push id21790
push userbmo@edmorley.co.uk
push dateThu, 05 Jan 2012 01:00:04 +0000
treeherdermozilla-central@0cdaf0773073 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone12.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-inbound and mozilla-central
--- a/browser/devtools/styleinspector/CssHtmlTree.jsm
+++ b/browser/devtools/styleinspector/CssHtmlTree.jsm
@@ -35,16 +35,17 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+const Ci = Components.interfaces;
 const Cu = Components.utils;
 const FILTER_CHANGED_TIMEOUT = 300;
 
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/PluralForm.jsm");
@@ -284,17 +285,18 @@ CssHtmlTree.prototype = {
       let fragment = this.doc.createDocumentFragment();
       this._refreshProcess = new UpdateProcess(this.win, CssHtmlTree.propertyNames, {
         onItem: function(aPropertyName) {
           // Per-item callback.
           if (this.viewedElement != aElement || !this.styleInspector.isOpen()) {
             return false;
           }
           let propView = new PropertyView(this, aPropertyName);
-          fragment.appendChild(propView.build());
+          fragment.appendChild(propView.buildMain());
+          fragment.appendChild(propView.buildSelectorContainer());
           if (propView.visible) {
             this.numVisibleProperties++;
           }
           propView.refreshAllSelectors();
           this.propertyViews.push(propView);
         }.bind(this),
         onDone: function() {
           // Completed callback.
@@ -512,16 +514,19 @@ function PropertyView(aTree, aName)
 
 PropertyView.prototype = {
   // The parent element which contains the open attribute
   element: null,
 
   // Property header node
   propertyHeader: null,
 
+  // Destination for property names
+  nameNode: null,
+
   // Destination for property values
   valueNode: null,
 
   // Are matched rules expanded?
   matchedExpanded: false,
 
   // Are unmatched rules expanded?
   unmatchedExpanded: false,
@@ -606,109 +611,146 @@ PropertyView.prototype = {
     return true;
   },
 
   /**
    * Returns the className that should be assigned to the propertyView.
    *
    * @return string
    */
-  get className()
+  get propertyHeaderClassName()
   {
     if (this.visible) {
       this.tree._darkStripe = !this.tree._darkStripe;
       let darkValue = this.tree._darkStripe ?
                       "property-view darkrow" : "property-view";
       return darkValue;
     }
     return "property-view-hidden";
   },
 
-  build: function PropertyView_build()
+  /**
+   * Returns the className that should be assigned to the propertyView content
+   * container.
+   * @return string
+   */
+  get propertyContentClassName()
+  {
+    if (this.visible) {
+      let darkValue = this.tree._darkStripe ?
+                      "property-content darkrow" : "property-content";
+      return darkValue;
+    }
+    return "property-content-hidden";
+  },
+
+  buildMain: function PropertyView_buildMain()
   {
     let doc = this.tree.doc;
-    this.element = doc.createElementNS(HTML_NS, "div");
-    this.element.setAttribute("class", this.className);
+    this.element = doc.createElementNS(HTML_NS, "tr");
+    this.element.setAttribute("class", this.propertyHeaderClassName);
+    this.element.addEventListener("click", this.propertyRowClick.bind(this), false);
 
-    this.propertyHeader = doc.createElementNS(XUL_NS, "hbox");
+    this.propertyHeader = doc.createElementNS(HTML_NS, "td");
     this.element.appendChild(this.propertyHeader);
     this.propertyHeader.setAttribute("class", "property-header");
-    this.propertyHeader.addEventListener("click", this.propertyHeaderClick.bind(this), false);
 
     this.matchedExpander = doc.createElementNS(HTML_NS, "div");
     this.propertyHeader.appendChild(this.matchedExpander);
     this.matchedExpander.setAttribute("class", "match expander");
 
-    let name = doc.createElementNS(HTML_NS, "div");
-    this.propertyHeader.appendChild(name);
-    name.setAttribute("class", "property-name");
-    name.textContent = this.name;
+    this.nameNode = doc.createElementNS(HTML_NS, "div");
+    this.propertyHeader.appendChild(this.nameNode);
+    this.nameNode.setAttribute("tabindex", "0");
+    this.nameNode.addEventListener("keydown", function(aEvent) {
+      let keyEvent = Ci.nsIDOMKeyEvent;
+      if (aEvent.keyCode == keyEvent.DOM_VK_F1) {
+        this.mdnLinkClick();
+      }
+      if (aEvent.keyCode == keyEvent.DOM_VK_RETURN ||
+          aEvent.keyCode == keyEvent.DOM_VK_SPACE) {
+        this.propertyRowClick(aEvent);
+      }
+    }.bind(this), false);
 
-    let helpcontainer = doc.createElementNS(HTML_NS, "div");
-    this.propertyHeader.appendChild(helpcontainer);
+    this.nameNode.setAttribute("class", "property-name");
+    this.nameNode.textContent = this.name;
+
+    let helpcontainer = doc.createElementNS(HTML_NS, "td");
+    this.element.appendChild(helpcontainer);
     helpcontainer.setAttribute("class", "helplink-container");
 
     let helplink = doc.createElementNS(HTML_NS, "a");
     helpcontainer.appendChild(helplink);
     helplink.setAttribute("class", "helplink");
     helplink.setAttribute("title", CssHtmlTree.HELP_LINK_TITLE);
     helplink.textContent = CssHtmlTree.HELP_LINK_TITLE;
     helplink.addEventListener("click", this.mdnLinkClick.bind(this), false);
 
-    this.valueNode = doc.createElementNS(HTML_NS, "div");
-    this.propertyHeader.appendChild(this.valueNode);
+    this.valueNode = doc.createElementNS(HTML_NS, "td");
+    this.element.appendChild(this.valueNode);
     this.valueNode.setAttribute("class", "property-value");
     this.valueNode.setAttribute("dir", "ltr");
     this.valueNode.textContent = this.value;
 
-    this.matchedSelectorsContainer = doc.createElementNS(HTML_NS, "div");
-    this.element.appendChild(this.matchedSelectorsContainer);
+    return this.element;
+  },
+
+  buildSelectorContainer: function PropertyView_buildSelectorContainer()
+  {
+    let doc = this.tree.doc;
+    let element = doc.createElementNS(HTML_NS, "tr");
+    element.setAttribute("class", this.propertyContentClassName);
+    this.matchedSelectorsContainer = doc.createElementNS(HTML_NS, "td");
+    this.matchedSelectorsContainer.setAttribute("colspan", "0");
     this.matchedSelectorsContainer.setAttribute("class", "rulelink");
+    element.appendChild(this.matchedSelectorsContainer);
 
-    return this.element;
+    return element;
   },
 
   /**
    * Refresh the panel's CSS property value.
    */
   refresh: function PropertyView_refresh()
   {
-    this.element.className = this.className;
+    this.element.className = this.propertyHeaderClassName;
+    this.element.nextElementSibling.className = this.propertyContentClassName;
 
     if (this.prevViewedElement != this.tree.viewedElement) {
       this._matchedSelectorViews = null;
       this._unmatchedSelectorViews = null;
       this.prevViewedElement = this.tree.viewedElement;
     }
 
     if (!this.tree.viewedElement || !this.visible) {
       this.valueNode.innerHTML = "";
-      this.matchedSelectorsContainer.hidden = true;
+      this.matchedSelectorsContainer.parentNode.hidden = true;
       this.matchedSelectorsContainer.innerHTML = "";
       this.matchedExpander.removeAttribute("open");
       return;
     }
 
     this.tree.numVisibleProperties++;
     this.valueNode.innerHTML = this.propertyInfo.value;
     this.refreshAllSelectors();
   },
 
   /**
    * Refresh the panel matched rules.
    */
   refreshMatchedSelectors: function PropertyView_refreshMatchedSelectors()
   {
     let hasMatchedSelectors = this.hasMatchedSelectors;
-    this.matchedSelectorsContainer.hidden = !hasMatchedSelectors;
+    this.matchedSelectorsContainer.parentNode.hidden = !hasMatchedSelectors;
 
     if (hasMatchedSelectors) {
-      this.propertyHeader.classList.add("expandable");
+      this.propertyHeader.parentNode.classList.add("expandable");
     } else {
-      this.propertyHeader.classList.remove("expandable");
+      this.propertyHeader.parentNode.classList.remove("expandable");
     }
 
     if (this.matchedExpanded && hasMatchedSelectors) {
       CssHtmlTree.processTemplate(this.templateMatchedSelectors,
         this.matchedSelectorsContainer, this);
       this.matchedExpander.setAttribute("open", "");
     } else {
       this.matchedSelectorsContainer.innerHTML = "";
@@ -797,21 +839,22 @@ PropertyView.prototype = {
 
   /**
    * The action when a user expands matched selectors.
    *
    * @param {Event} aEvent Used to determine the class name of the targets click
    * event. If the class name is "helplink" then the event is allowed to bubble
    * to the mdn link icon.
    */
-  propertyHeaderClick: function PropertyView_propertyHeaderClick(aEvent)
+  propertyRowClick: function PropertyView_propertyRowClick(aEvent)
   {
     if (aEvent.target.className != "helplink") {
       this.matchedExpanded = !this.matchedExpanded;
       this.refreshAllSelectors();
+      this.nameNode.focus();
       aEvent.preventDefault();
     }
   },
 
   /**
    * The action when a user expands unmatched selectors.
    */
   unmatchedSelectorsClick: function PropertyView_unmatchedSelectorsClick(aEvent)
--- a/browser/devtools/styleinspector/csshtmltree.xul
+++ b/browser/devtools/styleinspector/csshtmltree.xul
@@ -64,18 +64,18 @@
 <div id="root"></div>
 
 <!-- When no properties are found the following block is displayed. -->
 <div id="noResults" hidden="">
   &noPropertiesFound;
 </div>
 
 <!-- The output from #templateProperty (below) is appended here. -->
-<div id="propertyContainer">
-</div>
+<table id="propertyContainer">
+</table>
 
 <xul:hbox id="footer">
   <xul:label class="legendKey bestmatch">&bestMatch;</xul:label>
   <xul:label class="legendKey matched">&matched;</xul:label>
   <xul:label class="legendKey parentmatch">&parentMatch;</xul:label>
 </xul:hbox>
 <!--
 To visually debug the templates without running firefox, alter the display:none
--- a/browser/devtools/styleinspector/test/Makefile.in
+++ b/browser/devtools/styleinspector/test/Makefile.in
@@ -45,16 +45,17 @@ relativesrcdir  = browser/devtools/style
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_TEST_FILES = \
   browser_styleinspector.js \
   browser_bug683672.js \
   browser_styleinspector_bug_672746_default_styles.js \
   browser_styleinspector_bug_672744_search_filter.js \
+  browser_bug589375_keybindings.js \
   browser_styleinspector_bug_689759_no_results_placeholder.js \
   browser_bug_692400_element_style.js \
   browser_csslogic_inherited.js \
   browser_ruleview_editor.js \
   browser_ruleview_inherit.js \
   browser_ruleview_manipulation.js \
   browser_ruleview_override.js \
   browser_ruleview_ui.js \
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_bug589375_keybindings.js
@@ -0,0 +1,149 @@
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Tests that the key bindings work properly.
+
+let doc;
+let stylePanel;
+
+function createDocument()
+{
+  doc.body.innerHTML = '<style type="text/css"> ' +
+    '.matches {color: #F00;}</style>' +
+    '<span class="matches">Some styled text</span>' +
+    '</div>';
+  doc.title = "Style Inspector key binding test";
+  ok(window.StyleInspector, "StyleInspector exists");
+  stylePanel = new StyleInspector(window);
+  Services.obs.addObserver(runStyleInspectorTests, "StyleInspector-opened", false);
+  stylePanel.createPanel(false, function() {
+    stylePanel.open(doc.body);
+  });
+}
+
+function runStyleInspectorTests()
+{
+  Services.obs.removeObserver(runStyleInspectorTests, "StyleInspector-opened", false);
+
+  ok(stylePanel.isOpen(), "style inspector is open");
+
+  Services.obs.addObserver(SI_test, "StyleInspector-populated", false);
+  SI_inspectNode();
+}
+
+function SI_inspectNode()
+{
+  var span = doc.querySelector(".matches");
+  ok(span, "captain, we have the matches span");
+
+  let htmlTree = stylePanel.cssHtmlTree;
+  stylePanel.selectNode(span);
+
+  is(span, htmlTree.viewedElement,
+    "style inspector node matches the selected node");
+  is(htmlTree.viewedElement, stylePanel.cssLogic.viewedElement,
+     "cssLogic node matches the cssHtmlTree node");
+}
+
+function SI_test()
+{
+  Services.obs.removeObserver(SI_test, "StyleInspector-populated", false);
+
+  info("checking keybindings");
+
+  let iframe = stylePanel.iframe;
+  let searchbar = stylePanel.cssHtmlTree.searchField;
+  let propView = getFirstVisiblePropertyView();
+  let rulesTable = propView.matchedSelectorsContainer;
+  let nameNode = propView.nameNode;
+
+  info("Adding focus event handler to property name node");
+  nameNode.addEventListener("focus", function nameFocused() {
+    this.removeEventListener("focus", nameFocused);
+    info("property name is focused");
+    info("checking expand / collapse");
+    testKey(iframe.contentWindow, "VK_SPACE", rulesTable);
+    testKey(iframe.contentWindow, "VK_RETURN", rulesTable);
+
+    checkHelpLinkKeybinding();
+    Services.obs.addObserver(finishUp, "StyleInspector-closed", false);
+    stylePanel.close();
+  });
+
+  info("Adding focus event handler to search filter");
+  searchbar.addEventListener("focus", function searchbarFocused() {
+    this.removeEventListener("focus", searchbarFocused);
+    info("search filter is focused");
+    info("tabbing to property name node");
+    EventUtils.synthesizeKey("VK_TAB", {}, iframe.contentWindow);
+  });
+
+  info("Making sure that the style inspector panel is focused");
+  SimpleTest.waitForFocus(function windowFocused() {
+    info("window is focused");
+    info("focusing search filter");
+    searchbar.focus();
+  }, stylePanel.iframe.contentWindow);
+}
+
+function getFirstVisiblePropertyView()
+{
+  let propView = null;
+  stylePanel.cssHtmlTree.propertyViews.some(function(aPropView) {
+    if (aPropView.visible) {
+      propView = aPropView;
+      return true;
+    }
+  });
+
+  return propView;
+}
+
+function testKey(aContext, aVirtKey, aRulesTable)
+{
+  info("testing " + aVirtKey + " key");
+  info("expanding rules table");
+  EventUtils.synthesizeKey(aVirtKey, {}, aContext);
+  isnot(aRulesTable.innerHTML, "", "rules Table is populated");
+  info("collapsing rules table");
+  EventUtils.synthesizeKey(aVirtKey, {}, aContext);
+  is(aRulesTable.innerHTML, "", "rules Table is not populated");
+}
+
+function checkHelpLinkKeybinding()
+{
+  info("checking help link keybinding");
+  let iframe = stylePanel.iframe;
+  let propView = getFirstVisiblePropertyView();
+
+  info("check that MDN link is opened on \"F1\"");
+  let linkClicked = false;
+  propView.mdnLinkClick = function(aEvent) {
+    linkClicked = true;
+  };
+  EventUtils.synthesizeKey("VK_F1", {}, iframe.contentWindow);
+  is(linkClicked, true, "MDN link will be shown");
+}
+
+function finishUp()
+{
+  Services.obs.removeObserver(finishUp, "StyleInspector-closed", false);
+  ok(!stylePanel.isOpen(), "style inspector is closed");
+  doc = stylePanel = null;
+  gBrowser.removeCurrentTab();
+  finish();
+}
+
+function test()
+{
+  waitForExplicitFinish();
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
+    gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
+    doc = content.document;
+    waitForFocus(createDocument, content);
+  }, true);
+
+  content.location = "data:text/html,default styles test";
+}
--- a/browser/devtools/tilt/TiltGL.jsm
+++ b/browser/devtools/tilt/TiltGL.jsm
@@ -509,17 +509,17 @@ TiltGL.Renderer.prototype = {
    *                 the x amount of scaling
    * @param {Number} y
    *                 the y amount of scaling
    * @param {Number} z
    *                 optional, the z amount of scaling
    */
   scale: function TGLR_scale(x, y, z)
   {
-    mat4.scale(this.mvMatrix, [x, y, z || 0]);
+    mat4.scale(this.mvMatrix, [x, y, z || 1]);
   },
 
   /**
    * Performs a custom interpolation between two matrices.
    * The result is saved in the first operand.
    *
    * @param {Array} aMat
    *                the first matrix
--- a/browser/devtools/tilt/TiltUtils.jsm
+++ b/browser/devtools/tilt/TiltUtils.jsm
@@ -646,21 +646,34 @@ TiltUtils.getWindowId = function TU_getW
   }
 
   return aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                 .getInterface(Ci.nsIDOMWindowUtils)
                 .currentInnerWindowID;
 };
 
 /**
+ * Gets the markup document viewer zoom for the currently selected browser.
+ *
+ * @return {Number} the zoom ammount
+ */
+TiltUtils.getDocumentZoom = function TU_getDocumentZoom() {
+  let browserWindow = Cc["@mozilla.org/appshell/window-mediator;1"]
+    .getService(Ci.nsIWindowMediator)
+    .getMostRecentWindow("navigator:browser");
+
+  return browserWindow.gBrowser.selectedBrowser.markupDocumentViewer.fullZoom;
+};
+
+/**
  * Performs a garbage collection.
  */
 TiltUtils.gc = function TU_gc()
 {
-  var browserWindow = Cc["@mozilla.org/appshell/window-mediator;1"]
+  let browserWindow = Cc["@mozilla.org/appshell/window-mediator;1"]
     .getService(Ci.nsIWindowMediator)
     .getMostRecentWindow("navigator:browser");
 
   browserWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                .getInterface(Ci.nsIDOMWindowUtils)
                .garbageCollect();
 };
 
--- a/browser/devtools/tilt/TiltVisualizer.jsm
+++ b/browser/devtools/tilt/TiltVisualizer.jsm
@@ -216,16 +216,17 @@ TiltVisualizer.Presenter = function TV_P
     v3: vec3.create()
   };
 
   /**
    * Scene transformations, exposing offset, translation and rotation.
    * Modified by events in the controller through delegate functions.
    */
   this.transforms = {
+    zoom: TiltUtils.getDocumentZoom(),
     offset: vec3.create(),      // mesh offset, aligned to the viewport center
     translation: vec3.create(), // scene translation, on the [x, y, z] axis
     rotation: quat4.create()    // scene rotation, expressed as a quaternion
   };
 
   /**
    * Variables holding information about the initial and current node selected.
    */
@@ -333,16 +334,18 @@ TiltVisualizer.Presenter.prototype = {
                        transforms.translation[2]);
 
     renderer.transform(quat4.toMat4(transforms.rotation));
 
     // offset the visualization mesh to center
     renderer.translate(transforms.offset[0],
                        transforms.offset[1] + transforms.translation[1], 0);
 
+    renderer.scale(transforms.zoom, transforms.zoom);
+
     // draw the visualization mesh
     renderer.strokeWeight(2);
     renderer.depthTest(true);
     this.drawMeshStacks();
     this.drawMeshWireframe();
     this.drawHighlight();
 
     // make sure the initial transition is drawn until finished
@@ -487,22 +490,23 @@ TiltVisualizer.Presenter.prototype = {
     };
 
     // if there's no initial selection made, highlight the required node
     if (!this._initialSelection) {
       this._initialSelection = true;
       this.highlightNode(this.inspectorUI.selection);
     }
 
-    let width = renderer.width;
-    let height = renderer.height;
+    let zoom = TiltUtils.getDocumentZoom();
+    let width = Math.min(aData.meshWidth * zoom, renderer.width);
+    let height = Math.min(aData.meshHeight * zoom, renderer.height);
 
     // set the necessary mesh offsets
-    this.transforms.offset[0] = -Math.min(aData.meshWidth, width) * 0.5;
-    this.transforms.offset[1] = -Math.min(aData.meshHeight, height) * 0.5;
+    this.transforms.offset[0] = -width * 0.5;
+    this.transforms.offset[1] = -height * 0.5;
 
     // make sure the canvas is opaque now that the initialization is finished
     this.canvas.style.background = TiltVisualizerStyle.canvas.background;
 
     this.drawVisualization();
     this.redraw = true;
   },
 
@@ -554,18 +558,19 @@ TiltVisualizer.Presenter.prototype = {
     this.contentWindow.addEventListener("resize", this.onResize, false);
   },
 
   /**
    * Called when the content window of the current browser is resized.
    */
   onResize: function TVP_onResize(e)
   {
-    let width = e.target.innerWidth;
-    let height = e.target.innerHeight;
+    let zoom = TiltUtils.getDocumentZoom();
+    let width = e.target.innerWidth * zoom;
+    let height = e.target.innerHeight * zoom;
 
     // handle aspect ratio changes to update the projection matrix
     this.renderer.width = width;
     this.renderer.height = height;
 
     this.redraw = true;
   },
 
@@ -698,19 +703,22 @@ TiltVisualizer.Presenter.prototype = {
         }
       } else {
         if ("function" === typeof aProperties.onfail) {
           aProperties.onfail();
         }
       }
     }, false);
 
-    let width = this.renderer.width;
-    let height = this.renderer.height;
+    let zoom = TiltUtils.getDocumentZoom();
+    let width = this.renderer.width * zoom;
+    let height = this.renderer.height * zoom;
     let mesh = this.meshStacks;
+    x *= zoom;
+    y *= zoom;
 
     // create a ray following the mouse direction from the near clipping plane
     // to the far clipping plane, to check for intersections with the mesh,
     // and do all the heavy lifting in a separate thread
     worker.postMessage({
       thickness: STACK_THICKNESS,
       vertices: mesh.vertices.components,
 
@@ -983,17 +991,21 @@ TiltVisualizer.Controller.prototype = {
   onKeyDown: function TVC_onKeyDown(e)
   {
     let code = e.keyCode || e.which;
 
     if (code >= e.DOM_VK_LEFT && code <= e.DOM_VK_DOWN) {
       e.preventDefault();
       e.stopPropagation();
     }
-    this.arcball.keyDown(code);
+    if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) {
+      this.arcball.cancelKeyEvents();
+    } else {
+      this.arcball.keyDown(code);
+    }
   },
 
   /**
    * Called when a key is released.
    */
   onKeyUp: function TVC_onKeyUp(e)
   {
     let code = e.keyCode || e.which;
@@ -1008,26 +1020,27 @@ TiltVisualizer.Controller.prototype = {
     }
     this.arcball.keyUp(code);
   },
 
   /**
    * Called when the canvas looses focus.
    */
   onBlur: function TVC_onBlur(e) {
-    this.arcball._keyCode = {};
+    this.arcball.cancelKeyEvents();
   },
 
   /**
    * Called when the content window of the current browser is resized.
    */
   onResize: function TVC_onResize(e)
   {
-    let width = e.target.innerWidth;
-    let height = e.target.innerHeight;
+    let zoom = TiltUtils.getDocumentZoom();
+    let width = e.target.innerWidth * zoom;
+    let height = e.target.innerHeight * zoom;
 
     this.arcball.resize(width, height);
   },
 
   /**
    * Checks if this object was initialized properly.
    *
    * @return {Boolean} true if the object was initialized properly
@@ -1464,16 +1477,23 @@ TiltVisualizer.Arcball.prototype = {
       // set the vector to a point mapped inside the sphere
       aSphereVec[0] = x;
       aSphereVec[1] = y;
       aSphereVec[2] = Math.sqrt(1 - sqlength);
     }
   },
 
   /**
+   * Cancels all pending transformations caused by key events.
+   */
+  cancelKeyEvents: function TVA_cancelKeyEvents() {
+    this._keyCode = {};
+  },
+
+  /**
    * Resize this implementation to use different bounds.
    * This function is automatically called when the arcball is created.
    *
    * @param {Number} newWidth
    *                 the new width of canvas
    * @param {Number} newHeight
    *                 the new  height of canvas
    * @param {Number} newRadius
--- a/browser/devtools/tilt/test/Makefile.in
+++ b/browser/devtools/tilt/test/Makefile.in
@@ -71,12 +71,13 @@ include $(topsrcdir)/config/rules.mk
 	browser_tilt_math07.js \
 	browser_tilt_utils01.js \
 	browser_tilt_utils02.js \
 	browser_tilt_utils03.js \
 	browser_tilt_utils04.js \
 	browser_tilt_utils05.js \
 	browser_tilt_utils06.js \
 	browser_tilt_visualizer.js \
+	browser_tilt_zoom.js \
 	$(NULL)
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
--- a/browser/devtools/tilt/test/browser_tilt_controller.js
+++ b/browser/devtools/tilt/test/browser_tilt_controller.js
@@ -40,46 +40,65 @@ function test() {
         }
 
         ok(isEqualVec(tran(), prev_tran),
           "At init, the translation should be zero.");
         ok(isEqualVec(rot(), prev_rot),
           "At init, the rotation should be zero.");
 
 
-        EventUtils.synthesizeKey("VK_A", { type: "keydown" });
-        EventUtils.synthesizeKey("VK_LEFT", { type: "keydown" });
-        instance.controller.update();
+        function testEventCancel(cancellingEvent) {
+          EventUtils.synthesizeKey("VK_A", { type: "keydown" });
+          EventUtils.synthesizeKey("VK_LEFT", { type: "keydown" });
+          instance.controller.update();
+
+          ok(!isEqualVec(tran(), prev_tran),
+            "After a translation key is pressed, the vector should change.");
+          ok(!isEqualVec(rot(), prev_rot),
+            "After a rotation key is pressed, the quaternion should change.");
 
-        ok(!isEqualVec(tran(), prev_tran),
-          "After a translation key is pressed, the vector should change.");
-        ok(!isEqualVec(rot(), prev_rot),
-          "After a rotation key is pressed, the quaternion should change.");
+          save();
+
+
+          cancellingEvent();
+          instance.controller.update();
 
-        save();
+          ok(!isEqualVec(tran(), prev_tran),
+            "Even if the canvas lost focus, the vector has some inertia.");
+          ok(!isEqualVec(rot(), prev_rot),
+            "Even if the canvas lost focus, the quaternion has some inertia.");
+
+          save();
 
 
-        gBrowser.selectedBrowser.contentWindow.focus();
-        instance.controller.update();
+          while (!isEqualVec(tran(), prev_tran) ||
+                 !isEqualVec(rot(), prev_rot)) {
+            instance.controller.update();
+            save();
+          }
 
-        ok(!isEqualVec(tran(), prev_tran),
-          "Even if the canvas lost focus, the vector has some inertia.");
-        ok(!isEqualVec(rot(), prev_rot),
-          "Even if the canvas lost focus, the quaternion has some inertia.");
-
-        save();
-
-
-        while (!isEqualVec(tran(), prev_tran) || !isEqualVec(rot(), prev_rot)) {
-          instance.controller.update();
-          save();
+          ok(isEqualVec(tran(), prev_tran) && isEqualVec(rot(), prev_rot),
+            "After focus lost, the transforms inertia eventually stops.");
         }
 
-        ok(isEqualVec(tran(), prev_tran) && isEqualVec(rot(), prev_rot),
-          "After the focus is lost, the transforms inertia eventually stops.");
+        testEventCancel(function() {
+          EventUtils.synthesizeKey("T", { type: "keydown", altKey: 1 });
+        });
+        testEventCancel(function() {
+          EventUtils.synthesizeKey("I", { type: "keydown", ctrlKey: 1 });
+        });
+        testEventCancel(function() {
+          EventUtils.synthesizeKey("L", { type: "keydown", metaKey: 1 });
+        });
+        testEventCancel(function() {
+          EventUtils.synthesizeKey("T", { type: "keydown", shiftKey: 1 });
+        });
+        testEventCancel(function() {
+          gBrowser.selectedBrowser.contentWindow.focus();
+        });
       },
       onEnd: function()
       {
         gBrowser.removeCurrentTab();
         finish();
       }
     }, true);
   });
--- a/browser/devtools/tilt/test/browser_tilt_gl04.js
+++ b/browser/devtools/tilt/test/browser_tilt_gl04.js
@@ -108,9 +108,19 @@ function test() {
     -0.6889029145240784, 0.6511549949645996, 1.7610820531845093, 0,
     1.5683804750442505, -0.8317608833312988, 0.9210627675056458, 0, 1, 1, 1, 1
   ]), "The identity matrix transformation wasn't applied correctly.");
 
   renderer.origin(1, 1, 1);
   ok(isApproxVec(renderer.mvMatrix, [
     1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1
   ]), "The origin wasn't reset to identity correctly.");
+
+  renderer.translate(1, 2);
+  ok(isApproxVec(renderer.mvMatrix, [
+    1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 2, 0, 1
+  ]), "The second translation transformation wasn't applied correctly.");
+
+  renderer.scale(3, 4);
+  ok(isApproxVec(renderer.mvMatrix, [
+    3, 0, 0, 0, 0, 4, 0, 0, 0, 0, 1, 0, 1, 2, 0, 1
+  ]), "The second scale transformation wasn't applied correctly.");
 }
--- a/browser/devtools/tilt/test/browser_tilt_visualizer.js
+++ b/browser/devtools/tilt/test/browser_tilt_visualizer.js
@@ -94,16 +94,18 @@ function testPresenter(presenter) {
   ok(isApproxVec(presenter.highlight.v1, [0, 0, 0]),
     "The presenter highlight second vertex should be initially zeroed.");
   ok(isApproxVec(presenter.highlight.v2, [0, 0, 0]),
     "The presenter highlight third vertex should be initially zeroed.");
   ok(isApproxVec(presenter.highlight.v3, [0, 0, 0]),
     "The presenter highlight fourth vertex should be initially zeroed.");
   ok(presenter.transforms,
     "The presenter transforms wasn't initialized properly.");
+  ok(isApproxVec(presenter.transforms.zoom, 1),
+    "The presenter transforms zoom should be initially 1.");
   ok(isApproxVec(presenter.transforms.offset, [0, 0, 0]),
     "The presenter transforms offset should be initially zeroed.");
   ok(isApproxVec(presenter.transforms.translation, [0, 0, 0]),
     "The presenter transforms translation should be initially zeroed.");
   ok(isApproxVec(presenter.transforms.rotation, [0, 0, 0, 1]),
     "The presenter transforms rotation should be initially set to identity.");
 
   presenter.setTranslation([1, 2, 3]);
new file mode 100644
--- /dev/null
+++ b/browser/devtools/tilt/test/browser_tilt_zoom.js
@@ -0,0 +1,98 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/*global ok, is, info, waitForExplicitFinish, finish, executeSoon, gBrowser */
+/*global isApprox, isTiltEnabled, isWebGLSupported, createTab, createTilt */
+/*global Services, EventUtils, TiltUtils, InspectorUI, TILT_DESTROYED */
+"use strict";
+
+const ZOOM = 2;
+const RESIZE = 50;
+
+function setZoom(value) {
+  gBrowser.selectedBrowser.markupDocumentViewer.fullZoom = value;
+}
+
+function getZoom() {
+  return gBrowser.selectedBrowser.markupDocumentViewer.fullZoom;
+}
+
+function test() {
+  setZoom(Math.random());
+  is(getZoom(), TiltUtils.getDocumentZoom(),
+    "The getDocumentZoom utility function didn't return the expected results.");
+
+  if (!isTiltEnabled()) {
+    info("Skipping controller test because Tilt isn't enabled.");
+    return;
+  }
+  if (!isWebGLSupported()) {
+    info("Skipping controller test because WebGL isn't supported.");
+    return;
+  }
+
+  waitForExplicitFinish();
+
+  createTab(function() {
+    createTilt({
+      onInspectorOpen: function()
+      {
+        setZoom(ZOOM);
+      },
+      onTiltOpen: function(instance)
+      {
+        ok(isApprox(instance.presenter.transforms.zoom, ZOOM),
+          "The presenter transforms zoom wasn't initially set correctly.");
+
+        let contentWindow = gBrowser.selectedBrowser.contentWindow;
+        let initialWidth = contentWindow.innerWidth;
+        let initialHeight = contentWindow.innerHeight;
+
+        let renderer = instance.presenter.renderer;
+        let arcball = instance.controller.arcball;
+
+        ok(isApprox(contentWindow.innerWidth * ZOOM, renderer.width, 1),
+          "The renderer width wasn't set correctly.");
+        ok(isApprox(contentWindow.innerHeight * ZOOM, renderer.height, 1),
+          "The renderer height wasn't set correctly.");
+
+        ok(isApprox(contentWindow.innerWidth * ZOOM, arcball.width, 1),
+          "The arcball width wasn't set correctly.");
+        ok(isApprox(contentWindow.innerHeight * ZOOM, arcball.height, 1),
+          "The arcball height wasn't set correctly.");
+
+
+        window.resizeBy(-RESIZE * ZOOM, -RESIZE * ZOOM);
+
+        executeSoon(function() {
+          ok(isApprox(contentWindow.innerWidth + RESIZE, initialWidth, 1),
+            "The content window width wasn't set correctly.");
+          ok(isApprox(contentWindow.innerHeight + RESIZE, initialHeight, 1),
+            "The content window height wasn't set correctly.");
+
+          ok(isApprox(contentWindow.innerWidth * ZOOM, renderer.width, 1),
+            "The renderer width wasn't set correctly.");
+          ok(isApprox(contentWindow.innerHeight * ZOOM, renderer.height, 1),
+            "The renderer height wasn't set correctly.");
+
+          ok(isApprox(contentWindow.innerWidth * ZOOM, arcball.width, 1),
+            "The arcball width wasn't set correctly.");
+          ok(isApprox(contentWindow.innerHeight * ZOOM, arcball.height, 1),
+            "The arcball height wasn't set correctly.");
+
+
+          window.resizeBy(RESIZE * ZOOM, RESIZE * ZOOM);
+
+          Services.obs.addObserver(cleanup, TILT_DESTROYED, false);
+          InspectorUI.closeInspectorUI();
+        });
+      },
+    });
+  });
+}
+
+function cleanup() {
+  Services.obs.removeObserver(cleanup, TILT_DESTROYED);
+  gBrowser.removeCurrentTab();
+  finish();
+}
--- a/browser/devtools/tilt/test/head.js
+++ b/browser/devtools/tilt/test/head.js
@@ -1,12 +1,12 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
-/*global Services, Components, gBrowser, executeSoon */
+/*global Services, Components, gBrowser, executeSoon, info */
 /*global InspectorUI, Tilt, TiltGL, EPSILON */
 "use strict";
 
 Components.utils.import("resource:///modules/devtools/TiltGL.jsm");
 Components.utils.import("resource:///modules/devtools/TiltMath.jsm");
 Components.utils.import("resource:///modules/devtools/TiltUtils.jsm");
 Components.utils.import("resource:///modules/devtools/TiltVisualizer.jsm");
 
@@ -48,38 +48,50 @@ const INSP_ENABLED = Services.prefs.getB
 function isTiltEnabled() {
   return TILT_ENABLED && INSP_ENABLED;
 }
 
 function isWebGLSupported() {
   return TiltGL.isWebGLSupported() && TiltGL.create3DContext(createCanvas());
 }
 
-function isApprox(num1, num2) {
-  return Math.abs(num1 - num2) < EPSILON;
+function isApprox(num1, num2, delta) {
+  if (Math.abs(num1 - num2) > (delta || EPSILON)) {
+    info("isApprox expected " + num1 + ", got " + num2 + " instead.");
+    return false;
+  }
+  return true;
 }
 
-function isApproxVec(vec1, vec2) {
+function isApproxVec(vec1, vec2, delta) {
+  vec1 = Array.prototype.slice.call(vec1);
+  vec2 = Array.prototype.slice.call(vec2);
+
   if (vec1.length !== vec2.length) {
     return false;
   }
   for (let i = 0, len = vec1.length; i < len; i++) {
-    if (!isApprox(vec1[i], vec2[i])) {
+    if (!isApprox(vec1[i], vec2[i], delta)) {
+      info("isApproxVec expected [" + vec1 + "], got [" + vec2 + "] instead.");
       return false;
     }
   }
   return true;
 }
 
 function isEqualVec(vec1, vec2) {
+  vec1 = Array.prototype.slice.call(vec1);
+  vec2 = Array.prototype.slice.call(vec2);
+
   if (vec1.length !== vec2.length) {
     return false;
   }
   for (let i = 0, len = vec1.length; i < len; i++) {
     if (vec1[i] !== vec2[i]) {
+      info("isEqualVec expected [" + vec1 + "], got [" + vec2 + "] instead.");
       return false;
     }
   }
   return true;
 }
 
 function createCanvas() {
   return document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
--- a/browser/themes/gnomestripe/browser.css
+++ b/browser/themes/gnomestripe/browser.css
@@ -2117,16 +2117,17 @@ panel[dimmed="true"] {
      This negative margin compensate the extra row of pixels created
      by the shadow.*/
   margin-bottom: -1px;
 }
 
 .inspector-breadcrumbs-button {
   -moz-appearance: none;
   background-color: transparent;
+  border-style: solid;
   border-width: 1px 13px 2px 13px;
   color: hsl(210,30%,85%);
   max-width: 85px;
   /* The content of the button can be larger than the button */
   overflow: hidden;
   min-height: 25px;
 
   margin: 0 -11px 0 0;
@@ -2148,120 +2149,120 @@ panel[dimmed="true"] {
 
 /* Highlighter toolbar - breadcrumbs - LTR */
 
 .inspector-breadcrumbs-button:-moz-locale-dir(ltr):first-of-type {
   margin-left: 0;
 }
 
 .inspector-breadcrumbs-button {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:not([checked]),
 .inspector-breadcrumbs-button:not([checked]):hover:active {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-pressed.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-pressed.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[checked] {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-selected.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-selected.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[checked][siblings-menu-open],
 .inspector-breadcrumbs-button[checked]:hover:active {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-selected-pressed.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-selected-pressed.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:first-of-type {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:first-of-type:not([checked]),
 .inspector-breadcrumbs-button:first-of-type:not([checked]):hover:active {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-pressed.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-pressed.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:first-of-type[checked] {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-selected.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-selected.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:first-of-type[checked],
 .inspector-breadcrumbs-button:first-of-type[checked]:hover:active {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-selected-pressed.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-selected-pressed.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:last-of-type {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:last-of-type:not([checked]),
 .inspector-breadcrumbs-button:last-of-type:not([checked]):hover:active {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-pressed.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-pressed.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:last-of-type[checked] {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-selected.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-selected.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:last-of-type[checked],
 .inspector-breadcrumbs-button:last-of-type[checked]:hover:active {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-selected-pressed.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-selected-pressed.png") 1 13 2 13 fill stretch;
 }
 
 /* Highlighter toolbar - breadcrumbs - RTL */
 
 .inspector-breadcrumbs-button:-moz-locale-dir(rtl):first-of-type {
   margin-right: 0;
 }
 
 .inspector-breadcrumbs-button:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:not([checked]):-moz-locale-dir(rtl),
 .inspector-breadcrumbs-button:not([checked]):hover:active:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-pressed.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-pressed.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[checked]:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-selected.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-selected.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[checked][siblings-menu-open]:-moz-locale-dir(rtl),
 .inspector-breadcrumbs-button[checked]:hover:active:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-selected-pressed.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-selected-pressed.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:first-of-type:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:first-of-type:not([checked]):-moz-locale-dir(rtl),
 .inspector-breadcrumbs-button:first-of-type:not([checked]):hover:active:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-pressed.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-pressed.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:first-of-type[checked]:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-selected.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-selected.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:first-of-type[checked]:-moz-locale-dir(rtl),
 .inspector-breadcrumbs-button:first-of-type[checked]:hover:active:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-selected-pressed.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-selected-pressed.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:last-of-type:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:last-of-type:not([checked]):-moz-locale-dir(rtl),
 .inspector-breadcrumbs-button:last-of-type:not([checked]):hover:active:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-pressed.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-pressed.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:last-of-type[checked]:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-selected.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-selected.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:last-of-type[checked]:-moz-locale-dir(rtl),
 .inspector-breadcrumbs-button:last-of-type[checked]:hover:active:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-selected-pressed.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-selected-pressed.png") 1 13 2 13 fill stretch;
 }
--- a/browser/themes/gnomestripe/devtools/csshtmltree.css
+++ b/browser/themes/gnomestripe/devtools/csshtmltree.css
@@ -46,170 +46,147 @@
 }
 
 #root {
   display: -moz-box;
 }
 
 
 .property-header {
-  padding: 4px;
-  -moz-padding-start: 0;
-  -moz-padding-end: 5px;
-}
-
-.rule-unmatched {
-  cursor: pointer;
-  padding: 2px;
-  -moz-padding-start: 4px;
-  -moz-padding-end: 0;
+  padding: 5px 0;
   white-space: nowrap;
+  vertical-align: text-top;
 }
 
 /* Take away these two :visited rules to get a core dumper     */
 /* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
 .link,
 .link:visited {
   color: #0091ff;
 }
 .link,
 .helplink,
 .link:visited,
 .helplink:visited {
   text-decoration: none;
 }
 
-.helplink-container {
-  position: relative;
-  top: 2px;
-}
-
 .helplink {
   display: block;
   height: 14px;
   width: 0;
   overflow: hidden;
   -moz-padding-start: 14px;
   background-image: url("chrome://browser/skin/devtools/goto-mdn.png");
   -moz-margin-end: 2px;
+  cursor: pointer;
 }
 
-.property-header:not(:hover) > .helplink-container {
+.property-view:not(:hover) > .helplink-container {
   visibility: hidden;
 }
 
-.unmatchedSelectorTable {
-  -moz-margin-start: 15px;
-}
-
 .rulelink {
   color: -moz-dialogtext;
-  -moz-margin-start: 12px;
+  padding: 0;
 }
 
 .expander {
   -moz-appearance: treetwisty;
-  -moz-margin-start: 10px;
+  padding-top: 12px;
+  -moz-margin-start: 5px;
   -moz-margin-end: 5px;
+  display: inline-block;
+  vertical-align: middle;
 }
 
 .expander[open] {
   -moz-appearance: treetwistyopen;
 }
 
 .expandable {
   cursor: pointer;
 }
 
 .match {
   visibility: hidden;
 }
 
-.expandable > .match {
+.expandable > .property-header > .match {
   visibility: visible;
 }
 
-.only-unmatched {
-  -moz-margin-start: 0;
-}
-
 .property-name {
   font-size: 12px;
   color: -moz-FieldText;
-  width: 220px;
+  display: inline-block;
 }
 .property-value {
+  padding: 0;
   font-size: 10px;
   color: grey;
+  vertical-align: text-top;
+  width: 100%;
 }
 
-.property-view-hidden {
+.property-view-hidden,
+.property-content-hidden {
   display: none;
 }
 
 .rule-link {
   text-align: end;
   -moz-padding-start: 10px;
 }
 
 /* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
 .rule-text {
   direction: ltr;
-  -moz-padding-start: 15px;
+  padding: 0;
+  -moz-padding-start: 20px;
 }
 
 .bestmatch {
   color: black;
 }
 .matched {
   text-decoration: line-through;
 }
 .parentmatch {
   color: #666;
 }
-.unmatched {
-  color: brown;
-}
 
 #propertyContainer {
   display: -moz-box;
   -moz-box-orient: vertical;
   -moz-box-flex: 1;
   overflow-y: auto;
+  border-collapse: collapse;
 }
 
 .darkrow {
   background-color: rgba(0,0,0,.022);
 }
 
 #noResults {
   font-size: 18px;
   margin-top: 5px;
   text-align: center;
 }
 
 .headerControls {
   color: -moz-dialogtext;
   background-color: -moz-dialog;
-  padding-top: 5px;
 }
 
 .onlyuserstyles {
   cursor: pointer;
   font-size: 11px;
 }
 
-.searchfield {
-  -moz-margin-start: 10px;
-}
-
-.styleinspector-legend {
-  -moz-margin-start: 12px;
-}
-
 #footer {
   border-top: 1px solid -moz-dialog;
 }
 
 .legendKey {
   margin: 0 5px;
 }
 
--- a/browser/themes/pinstripe/browser.css
+++ b/browser/themes/pinstripe/browser.css
@@ -2853,16 +2853,17 @@ panel[dimmed="true"] {
      inspector-breadcrumbs-buttons, to match toolbar-buttons style.
      This negative margin compensate the extra row of pixels created
      by the shadow.*/
   margin-bottom: -1px;
 }
 
 .inspector-breadcrumbs-button {
   -moz-appearance: none;
+  border-style: solid;
   border-width: 1px 13px 2px 13px;
   color: hsl(210,30%,85%);
   max-width: 85px;
   /* The content of the button can be larger than the button */
   overflow: hidden;
   min-height: 25px;
 
   margin: 0 -11px 0 0;
@@ -2884,120 +2885,120 @@ panel[dimmed="true"] {
 
 /* Highlighter toolbar - breadcrumbs - LTR */
 
 .inspector-breadcrumbs-button:-moz-locale-dir(ltr):first-of-type {
   margin-left: 0;
 }
 
 .inspector-breadcrumbs-button {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:not([checked]),
 .inspector-breadcrumbs-button:not([checked]):hover:active {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-pressed.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-pressed.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[checked] {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-selected.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-selected.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[checked][siblings-menu-open],
 .inspector-breadcrumbs-button[checked]:hover:active {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-selected-pressed.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-selected-pressed.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:first-of-type {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:first-of-type:not([checked]),
 .inspector-breadcrumbs-button:first-of-type:not([checked]):hover:active {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-pressed.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-pressed.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:first-of-type[checked] {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-selected.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-selected.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:first-of-type[checked],
 .inspector-breadcrumbs-button:first-of-type[checked]:hover:active {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-selected-pressed.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-selected-pressed.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:last-of-type {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:last-of-type:not([checked]),
 .inspector-breadcrumbs-button:last-of-type:not([checked]):hover:active {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-pressed.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-pressed.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:last-of-type[checked] {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-selected.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-selected.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:last-of-type[checked],
 .inspector-breadcrumbs-button:last-of-type[checked]:hover:active {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-selected-pressed.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-selected-pressed.png") 1 13 2 13 fill stretch;
 }
 
 /* Highlighter toolbar - breadcrumbs - RTL */
 
 .inspector-breadcrumbs-button:-moz-locale-dir(rtl):first-of-type {
   margin-right: 0;
 }
 
 .inspector-breadcrumbs-button:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:not([checked]):-moz-locale-dir(rtl),
 .inspector-breadcrumbs-button:not([checked]):hover:active:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-pressed.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-pressed.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[checked]:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-selected.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-selected.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[checked][siblings-menu-open]:-moz-locale-dir(rtl),
 .inspector-breadcrumbs-button[checked]:hover:active:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-selected-pressed.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-selected-pressed.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:first-of-type:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:first-of-type:not([checked]):-moz-locale-dir(rtl),
 .inspector-breadcrumbs-button:first-of-type:not([checked]):hover:active:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-pressed.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-pressed.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:first-of-type[checked]:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-selected.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-selected.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:first-of-type[checked]:-moz-locale-dir(rtl),
 .inspector-breadcrumbs-button:first-of-type[checked]:hover:active:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-selected-pressed.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-selected-pressed.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:last-of-type:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:last-of-type:not([checked]):-moz-locale-dir(rtl),
 .inspector-breadcrumbs-button:last-of-type:not([checked]):hover:active:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-pressed.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-pressed.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:last-of-type[checked]:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-selected.png") 1 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-selected.png") 1 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:last-of-type[checked]:-moz-locale-dir(rtl),
 .inspector-breadcrumbs-button:last-of-type[checked]:hover:active:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-selected-pressed.png") 1 13 2 13 stretch;
-}
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-selected-pressed.png") 1 13 2 13 fill stretch;
+}
--- a/browser/themes/pinstripe/devtools/csshtmltree.css
+++ b/browser/themes/pinstripe/devtools/csshtmltree.css
@@ -46,172 +46,149 @@
 }
 
 #root {
   display: -moz-box;
 }
 
 
 .property-header {
-  padding: 4px;
-  -moz-padding-start: 0;
-  -moz-padding-end: 5px;
-}
-
-.rule-unmatched {
-  cursor: pointer;
-  padding: 2px;
-  -moz-padding-start: 4px;
-  -moz-padding-end: 0;
+  padding: 5px 0;
   white-space: nowrap;
+  vertical-align: text-top;
 }
 
 /* Take away these two :visited rules to get a core dumper     */
 /* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
 .link,
 .link:visited {
   color: #0091ff;
 }
 .link,
 .helplink,
 .link:visited,
 .helplink:visited {
   text-decoration: none;
 }
 
-.helplink-container {
-  position: relative;
-  top: 2px;
-}
-
 .helplink {
   display: block;
   height: 14px;
   width: 0;
   overflow: hidden;
   -moz-padding-start: 14px;
   background-image: url("chrome://browser/skin/devtools/goto-mdn.png");
   -moz-margin-end: 2px;
+  cursor: pointer;
 }
 
-.property-header:not(:hover) > .helplink-container {
+.property-view:not(:hover) > .helplink-container {
   visibility: hidden;
 }
 
-.unmatchedSelectorTable {
-  -moz-margin-start: 15px;
-}
-
 .rulelink {
   color: -moz-dialogtext;
-  -moz-margin-start: 12px;
+  padding: 0;
 }
 
 .expander {
   -moz-appearance: treetwisty;
   width: 12px;
   height: 12px;
+  padding-top: 12px;
   -moz-margin-start: 5px;
   -moz-margin-end: 5px;
+  display: inline-block;
+  vertical-align: middle;
 }
 
 .expander[open] {
   -moz-appearance: treetwistyopen;
 }
 
 .expandable {
   cursor: pointer;
 }
 
 .match {
   visibility: hidden;
 }
 
-.expandable > .match {
+.expandable > .property-header > .match {
   visibility: visible;
 }
 
-.only-unmatched {
-  -moz-margin-start: 0;
-}
-
 .property-name {
   font-size: 12px;
   color: -moz-FieldText;
-  width: 220px;
+  display: inline-block;
 }
 .property-value {
+  padding: 0;
   font-size: 10px;
   color: grey;
+  vertical-align: text-top;
+  width: 100%;
 }
 
-.property-view-hidden {
+.property-view-hidden,
+.property-content-hidden {
   display: none;
 }
 
 .rule-link {
   text-align: end;
   -moz-padding-start: 10px;
 }
 
 /* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
 .rule-text {
   direction: ltr;
-  -moz-padding-start: 15px;
+  padding: 0;
+  -moz-padding-start: 20px;
 }
 
 .bestmatch {
   color: black;
 }
 .matched {
   text-decoration: line-through;
 }
 .parentmatch {
   color: #666;
 }
-.unmatched {
-  color: brown;
-}
 
 #propertyContainer {
   display: -moz-box;
   -moz-box-orient: vertical;
   -moz-box-flex: 1;
   overflow-y: auto;
+  border-collapse: collapse;
 }
 
 .darkrow {
   background-color: rgba(0,0,0,.022);
 }
 
 #noResults {
   font-size: 18px;
   margin-top: 5px;
   text-align: center;
 }
 
 .headerControls {
   color: -moz-dialogtext;
   background-color: -moz-dialog;
-  padding-top: 5px;
 }
 
 .onlyuserstyles {
   cursor: pointer;
   font-size: 11px;
 }
 
-.searchfield {
-  -moz-margin-start: 10px;
-}
-
-.styleinspector-legend {
-  -moz-margin-start: 12px;
-}
-
 #footer {
   border-top: 1px solid -moz-dialog;
 }
 
 .legendKey {
   margin: 0 5px;
 }
 
--- a/browser/themes/winstripe/browser.css
+++ b/browser/themes/winstripe/browser.css
@@ -2797,16 +2797,17 @@ panel[dimmed="true"] {
      This negative margin compensate the extra row of pixels created
      by the shadow.*/
   margin: -1px 0;
 }
 
 .inspector-breadcrumbs-button {
   -moz-appearance: none;
   background-color: transparent;
+  border-style: solid;
   border-width: 2px 13px;
   outline: none;
   color: hsl(210,30%,85%);
   max-width: 85px;
   /* The content of the button can be larger than the button */
   overflow: hidden;
   min-height: 25px;
   margin: 0 -11px 0 0;
@@ -2828,120 +2829,120 @@ panel[dimmed="true"] {
 
 /* Highlighter toolbar - breadcrumbs - LTR */
 
 .inspector-breadcrumbs-button:-moz-locale-dir(ltr):first-of-type {
   margin-left: 0;
 }
 
 .inspector-breadcrumbs-button {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle.png") 2 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle.png") 2 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:not([checked]),
 .inspector-breadcrumbs-button:not([checked]):hover:active {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-pressed.png") 2 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-pressed.png") 2 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[checked] {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-selected.png") 2 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-selected.png") 2 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[checked][siblings-menu-open],
 .inspector-breadcrumbs-button[checked]:hover:active {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-selected-pressed.png") 2 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-selected-pressed.png") 2 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:first-of-type {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start.png") 2 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start.png") 2 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:first-of-type:not([checked]),
 .inspector-breadcrumbs-button:first-of-type:not([checked]):hover:active {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-pressed.png") 2 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-pressed.png") 2 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:first-of-type[checked] {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-selected.png") 2 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-selected.png") 2 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:first-of-type[checked],
 .inspector-breadcrumbs-button:first-of-type[checked]:hover:active {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-selected-pressed.png") 2 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-selected-pressed.png") 2 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:last-of-type {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end.png") 2 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end.png") 2 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:last-of-type:not([checked]),
 .inspector-breadcrumbs-button:last-of-type:not([checked]):hover:active {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-pressed.png") 2 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-pressed.png") 2 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:last-of-type[checked] {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-selected.png") 2 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-selected.png") 2 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:last-of-type[checked],
 .inspector-breadcrumbs-button:last-of-type[checked]:hover:active {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-selected-pressed.png") 2 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-selected-pressed.png") 2 13 2 13 fill stretch;
 }
 
 /* Highlighter toolbar - breadcrumbs - RTL */
 
 .inspector-breadcrumbs-button:-moz-locale-dir(rtl):first-of-type {
   margin-right: 0;
 }
 
 .inspector-breadcrumbs-button:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle.png") 2 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle.png") 2 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:not([checked]):-moz-locale-dir(rtl),
 .inspector-breadcrumbs-button:not([checked]):hover:active:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-pressed.png") 2 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-pressed.png") 2 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[checked]:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-selected.png") 2 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-selected.png") 2 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[checked][siblings-menu-open]:-moz-locale-dir(rtl),
 .inspector-breadcrumbs-button[checked]:hover:active:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-selected-pressed.png") 2 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-selected-pressed.png") 2 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:first-of-type:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start.png") 2 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start.png") 2 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:first-of-type:not([checked]):-moz-locale-dir(rtl),
 .inspector-breadcrumbs-button:first-of-type:not([checked]):hover:active:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-pressed.png") 2 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-pressed.png") 2 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:first-of-type[checked]:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-selected.png") 2 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-selected.png") 2 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:first-of-type[checked]:-moz-locale-dir(rtl),
 .inspector-breadcrumbs-button:first-of-type[checked]:hover:active:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-selected-pressed.png") 2 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-selected-pressed.png") 2 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:last-of-type:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end.png") 2 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end.png") 2 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:last-of-type:not([checked]):-moz-locale-dir(rtl),
 .inspector-breadcrumbs-button:last-of-type:not([checked]):hover:active:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-pressed.png") 2 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-pressed.png") 2 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button:last-of-type[checked]:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-selected.png") 2 13 2 13 stretch;
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-selected.png") 2 13 2 13 fill stretch;
 }
 
 .inspector-breadcrumbs-button[siblings-menu-open]:last-of-type[checked]:-moz-locale-dir(rtl),
 .inspector-breadcrumbs-button:last-of-type[checked]:hover:active:-moz-locale-dir(rtl) {
-  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-selected-pressed.png") 2 13 2 13 stretch;
-}
+  -moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-selected-pressed.png") 2 13 2 13 fill stretch;
+}
--- a/browser/themes/winstripe/devtools/csshtmltree.css
+++ b/browser/themes/winstripe/devtools/csshtmltree.css
@@ -45,172 +45,148 @@
   color: -moz-FieldText;
 }
 
 #root {
   display: -moz-box;
 }
 
 .property-header {
-  padding: 4px;
-  -moz-padding-start: 0;
-  -moz-padding-end: 5px;
-}
-
-.rule-unmatched {
-  cursor: pointer;
-  padding: 2px;
-  -moz-padding-start: 4px;
-  -moz-padding-end: 0;
+  padding: 5px 0;
   white-space: nowrap;
+  vertical-align: text-top;
 }
 
 /* Take away these two :visited rules to get a core dumper     */
 /* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
 .link,
 .link:visited {
   color: #0091ff;
 }
 .link,
 .helplink,
 .link:visited,
 .helplink:visited {
   text-decoration: none;
 }
 
-.helplink-container {
-  position: relative;
-  top: 2px;
-}
-
 .helplink {
   display: block;
   height: 14px;
   width: 0;
   overflow: hidden;
   -moz-padding-start: 14px;
   background-image: url("chrome://browser/skin/devtools/goto-mdn.png");
   -moz-margin-end: 2px;
+  cursor: pointer;
 }
 
-.property-header:not(:hover) > .helplink-container {
+.property-view:not(:hover) > .helplink-container {
   visibility: hidden;
 }
 
-.unmatchedSelectorTable {
-  -moz-margin-start: 15px;
-}
-
 .rulelink {
   color: -moz-dialogtext;
-  -moz-margin-start: 12px;
+  padding: 0;
 }
 
 .expander {
   width: 9px;
   height: 9px;
   -moz-margin-start: 5px;
   -moz-margin-end: 5px;
   background: url("chrome://global/skin/tree/twisty-clsd.png") center center no-repeat;
+  display: inline-block;
+  vertical-align: middle;
 }
 
 .expander[open] {
   background-image: url("chrome://global/skin/tree/twisty-open.png");
 }
 
 .expandable {
   cursor: pointer;
 }
 
 .match {
   visibility: hidden;
 }
 
-.expandable > .match {
+.expandable > .property-header > .match {
   visibility: visible;
 }
 
-.only-unmatched {
-  -moz-margin-start: 0;
-}
-
 .property-name {
   font-size: 12px;
   color: -moz-FieldText;
-  width: 220px;
+  display: inline-block;
 }
 .property-value {
+  padding: 0;
   font-size: 10px;
   color: grey;
+  vertical-align: text-top;
+  width: 100%;
 }
 
-.property-view-hidden {
+.property-view-hidden,
+.property-content-hidden {
   display: none;
 }
 
 .rule-link {
   text-align: end;
   -moz-padding-start: 10px;
 }
 
 /* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
 .rule-text {
   direction: ltr;
-  -moz-padding-start: 15px;
+  padding: 0;
+  -moz-padding-start: 20px;
 }
 
 .bestmatch {
   color: black;
 }
 .matched {
   text-decoration: line-through;
 }
 .parentmatch {
   color: #666;
 }
-.unmatched {
-  color: brown;
-}
 
 #propertyContainer {
   display: -moz-box;
   -moz-box-orient: vertical;
   -moz-box-flex: 1;
   overflow-y: auto;
+  border-collapse: collapse;
 }
 
 .darkrow {
   background-color: rgba(0,0,0,.022);
 }
 
 #noResults {
   font-size: 18px;
   margin-top: 5px;
   text-align: center;
 }
 
 .headerControls {
   color: -moz-dialogtext;
   background-color: -moz-dialog;
-  padding-top: 5px;
 }
 
 .onlyuserstyles {
   cursor: pointer;
   font-size: 11px;
 }
 
-.searchfield {
-  -moz-margin-start: 10px;
-}
-
-.styleinspector-legend {
-  -moz-margin-start: 12px;
-}
-
 #footer {
   border-top: 1px solid -moz-dialog;
 }
 
 .legendKey {
   margin: 0 5px;
 }
 
--- a/dom/system/NetworkGeolocationProvider.js
+++ b/dom/system/NetworkGeolocationProvider.js
@@ -213,27 +213,29 @@ WifiGeoPositionProvider.prototype = {
       // make sure that the ssid doesn't contain any | chars.
       ap.ssid = ap.ssid.replace("|", "\\|");
       // gls service parses the | as fields
       return "&wifi=mac:"+ap.mac+"|ssid:"+ap.ssid+"|ss:"+ap.signal;
     };
 
     if (accessPoints) {
         providerUrl = providerUrl + accessPoints.sort(sort).map(encode).join("");
-        // max length is 2k.  make sure we are under that
-        let x = providerUrl.length - 2000;
-        if (x >= 0) {
-            // we need to trim
-            let doomed = providerUrl.lastIndexOf("&", 2000);
-            LOG("Doomed:"+doomed);
-            providerUrl = providerUrl.substring(0, doomed);
-        }
     }
 
     providerUrl = encodeURI(providerUrl);
+
+    // max length is 2k.  make sure we are under that
+    let x = providerUrl.length - 2000;
+    if (x >= 0) {
+	// we need to trim
+	let doomed = providerUrl.lastIndexOf("&", 2000);
+	LOG("Doomed:"+doomed);
+	providerUrl = providerUrl.substring(0, doomed);
+    }
+    
     LOG("************************************* Sending request:\n" + providerUrl + "\n");
 
     // send our request to a wifi geolocation network provider:
     let xhr = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
                         .createInstance(Ci.nsIXMLHttpRequest);
 
     // This is a background load
     xhr.mozBackgroundRequest = true;