Merge the last green changeset of mozilla-inbound to mozilla-central
authorEhsan Akhgari <ehsan@mozilla.com>
Wed, 21 Sep 2011 13:12:26 -0400
changeset 78562 4ea7e20806667913ab2fc941b4d0605c53c263c2
parent 78561 a3d4a447c8fc8512b169b9d5679f6ab198d5fab6 (current diff)
parent 78559 3d181775477ffbca5fe73d5b0d2d99a45ff1a94a (diff)
child 78575 50b36274e6896899e9b3e1de6b4e0ad75ed60a37
child 78587 f4ec1c8b2567a50a043798feeb5e3af2ddeee4e2
push id78
push userclegnitto@mozilla.com
push dateFri, 16 Dec 2011 17:32:24 +0000
treeherdermozilla-release@79d24e644fdd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone9.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 the last green changeset of mozilla-inbound to mozilla-central
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -522,14 +522,18 @@ statuspanel[label=""] {
 }
 
 .statuspanel-inner {
   height: 3em;
   width: 100%;
   -moz-box-align: end;
 }
 
+.styleInspector {
+  min-width: 350px;
+}
+
 .panel-inner-arrowcontentfooter[footertype="promobox"] {
   -moz-binding: url("chrome://browser/content/urlbarBindings.xml#promobox");
 }
 
 /* highlighter */
 %include highlighter.css
--- a/browser/base/content/inspector.js
+++ b/browser/base/content/inspector.js
@@ -248,60 +248,78 @@ Highlighter.prototype = {
    */
   highlight: function Highlighter_highlight(aScroll)
   {
     // node is not set or node is not highlightable, bail
     if (!this.node || !this.isNodeHighlightable()) {
       return;
     }
 
+    if (aScroll) {
+      this.node.scrollIntoView();
+    }
+
     let clientRect = this.node.getBoundingClientRect();
 
+    // Go up in the tree of frames to determine the correct rectangle.
     // clientRect is read-only, we need to be able to change properties.
     let rect = {top: clientRect.top,
                 left: clientRect.left,
                 width: clientRect.width,
                 height: clientRect.height};
 
-    if (aScroll) {
-      this.node.scrollIntoView();
-    }
+    let frameWin = this.node.ownerDocument.defaultView;
+
+    // We iterate through all the parent windows.
+    while (true) {
+
+      // Does the selection overflow on the right of its window?
+      let diffx = frameWin.innerWidth - (rect.left + rect.width);
+      if (diffx < 0) {
+        rect.width += diffx;
+      }
 
-    // Go up in the tree of frames to determine the correct rectangle
-    // coordinates and size.
-    let frameWin = this.node.ownerDocument.defaultView;
-    do {
-      let frameRect = frameWin.frameElement ?
-                      frameWin.frameElement.getBoundingClientRect() :
-                      {top: 0, left: 0};
+      // Does the selection overflow on the bottom of its window?
+      let diffy = frameWin.innerHeight - (rect.top + rect.height);
+      if (diffy < 0) {
+        rect.height += diffy;
+      }
 
+      // Does the selection overflow on the left of its window?
+      if (rect.left < 0) {
+        rect.width += rect.left;
+        rect.left = 0;
+      }
+
+      // Does the selection overflow on the top of its window?
       if (rect.top < 0) {
         rect.height += rect.top;
         rect.top = 0;
       }
 
-      if (rect.left < 0) {
-        rect.width += rect.left;
-        rect.left = 0;
+      // Selection has been clipped to fit in its own window.
+
+      // Are we in the top-level window?
+      if (frameWin.parent === frameWin || !frameWin.frameElement) {
+        break;
       }
 
-      let diffx = frameWin.innerWidth - rect.left - rect.width;
-      if (diffx < 0) {
-        rect.width += diffx;
-      }
-      let diffy = frameWin.innerHeight - rect.top - rect.height;
-      if (diffy < 0) {
-        rect.height += diffy;
-      }
+      // We are in an iframe.
+      // We take into account the parent iframe position and its
+      // offset (borders and padding).
+      let frameRect = frameWin.frameElement.getBoundingClientRect();
 
-      rect.left += frameRect.left;
-      rect.top += frameRect.top;
+      let [offsetTop, offsetLeft] =
+        InspectorUI.getIframeContentOffset(frameWin.frameElement);
+
+      rect.top += frameRect.top + offsetTop;
+      rect.left += frameRect.left + offsetLeft;
 
       frameWin = frameWin.parent;
-    } while (frameWin != this.win);
+    }
 
     this.highlightRectangle(rect);
 
     if (this._highlighting) {
       Services.obs.notifyObservers(null,
         INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, null);
     }
   },
@@ -1373,36 +1391,72 @@ var InspectorUI = {
    * @param integer aX
    * @param integer aY
    * @returns Node|null the element node found at the given coordinates.
    */
   elementFromPoint: function IUI_elementFromPoint(aDocument, aX, aY)
   {
     let node = aDocument.elementFromPoint(aX, aY);
     if (node && node.contentDocument) {
-      switch (node.nodeName.toLowerCase()) {
-        case "iframe":
-          let rect = node.getBoundingClientRect();
-          aX -= rect.left;
-          aY -= rect.top;
+      if (node instanceof HTMLIFrameElement) {
+        let rect = node.getBoundingClientRect();
+
+        // Gap between the iframe and its content window.
+        let [offsetTop, offsetLeft] = this.getIframeContentOffset(node);
+
+        aX -= rect.left + offsetLeft;
+        aY -= rect.top + offsetTop;
 
-        case "frame":
-          let subnode = this.elementFromPoint(node.contentDocument, aX, aY);
-          if (subnode) {
-            node = subnode;
-          }
+        if (aX < 0 || aY < 0) {
+          // Didn't reach the content document, still over the iframe.
+          return node;
+        }
+      }
+      if (node instanceof HTMLIFrameElement ||
+          node instanceof HTMLFrameElement) {
+        let subnode = this.elementFromPoint(node.contentDocument, aX, aY);
+        if (subnode) {
+          node = subnode;
+        }
       }
     }
     return node;
   },
 
   ///////////////////////////////////////////////////////////////////////////
   //// Utility functions
 
   /**
+   * Returns iframe content offset (iframe border + padding).
+   * Note: this function shouldn't need to exist, had the platform provided a
+   * suitable API for determining the offset between the iframe's content and
+   * its bounding client rect. Bug 626359 should provide us with such an API.
+   *
+   * @param aIframe
+   *        The iframe.
+   * @returns array [offsetTop, offsetLeft]
+   *          offsetTop is the distance from the top of the iframe and the
+   *            top of the content document.
+   *          offsetLeft is the distance from the left of the iframe and the
+   *            left of the content document.
+   */
+  getIframeContentOffset: function IUI_getIframeContentOffset(aIframe)
+  {
+    let style = aIframe.contentWindow.getComputedStyle(aIframe, null);
+
+    let paddingTop = parseInt(style.getPropertyValue("padding-top"));
+    let paddingLeft = parseInt(style.getPropertyValue("padding-left"));
+
+    let borderTop = parseInt(style.getPropertyValue("border-top-width"));
+    let borderLeft = parseInt(style.getPropertyValue("border-left-width"));
+
+    return [borderTop + paddingTop, borderLeft + paddingLeft];
+  },
+
+  /**
    * Does the given object have a class attribute?
    * @param aNode
    *        the DOM node.
    * @param aClass
    *        The class string.
    * @returns boolean
    */
   hasClass: function IUI_hasClass(aNode, aClass)
--- a/browser/base/content/test/inspector/Makefile.in
+++ b/browser/base/content/test/inspector/Makefile.in
@@ -51,14 +51,15 @@ include $(topsrcdir)/config/rules.mk
 		browser_inspector_scrolling.js \
 		browser_inspector_store.js \
 		browser_inspector_tab_switch.js \
 		browser_inspector_treePanel_output.js \
 		browser_inspector_treePanel_input.html \
 		browser_inspector_treePanel_result.html \
 		browser_inspector_registertools.js \
 		browser_inspector_bug_665880.js \
+		browser_inspector_bug_674871.js \
 		browser_inspector_editor.js \
 		browser_inspector_bug_566084_location_changed.js \
 		$(NULL)
 
 libs::	$(_BROWSER_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/inspector/browser_inspector_bug_674871.js
@@ -0,0 +1,114 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+
+function test()
+{
+  waitForExplicitFinish();
+
+  let doc;
+  let iframeNode, iframeBodyNode;
+
+  let iframeSrc = "<style>" +
+                  "body {" +
+                  "margin:0;" +
+                  "height:100%;" +
+                  "background-color:red" +
+                  "}" +
+                  "</style>" +
+                  "<body></body>";
+  let docSrc = "<style>" +
+               "iframe {" +
+               "height:200px;" +
+               "border: 11px solid black;" +
+               "padding: 13px;" +
+               "}" +
+               "body,iframe {" +
+               "margin:0" +
+               "}" +
+               "</style>" +
+               "<body>" +
+               "<iframe src='data:text/html," + iframeSrc + "'></iframe>" +
+               "</body>";
+
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", function onload() {
+    gBrowser.selectedBrowser.removeEventListener("load", onload, true);
+    doc = content.document;
+    waitForFocus(setupTest, content);
+  }, true);
+
+  content.location = "data:text/html," + docSrc;
+
+  function setupTest()
+  {
+    iframeNode = doc.querySelector("iframe");
+    iframeBodyNode = iframeNode.contentDocument.querySelector("body");
+    ok(iframeNode, "we have the iframe node");
+    ok(iframeBodyNode, "we have the body node");
+    Services.obs.addObserver(runTests,
+      INSPECTOR_NOTIFICATIONS.OPENED, false);
+    InspectorUI.toggleInspectorUI();
+  }
+
+  function runTests()
+  {
+    Services.obs.removeObserver(runTests,
+      INSPECTOR_NOTIFICATIONS.OPENED);
+
+    executeSoon(function() {
+      Services.obs.addObserver(isTheIframeSelected,
+        INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
+
+      moveMouseOver(iframeNode, 1, 1);
+    });
+  }
+
+  function isTheIframeSelected()
+  {
+    Services.obs.removeObserver(isTheIframeSelected,
+      INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
+
+    is(InspectorUI.selection, iframeNode, "selection matches node");
+    iframeNode.style.marginBottom = doc.defaultView.innerHeight + "px";
+    doc.defaultView.scrollBy(0, 40);
+
+    executeSoon(function() {
+      Services.obs.addObserver(isTheIframeContentSelected,
+        INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
+
+      moveMouseOver(iframeNode, 40, 40);
+    });
+  }
+
+  function isTheIframeContentSelected()
+  {
+    Services.obs.removeObserver(isTheIframeContentSelected,
+      INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
+
+    is(InspectorUI.selection, iframeBodyNode, "selection matches node");
+    // 184 == 200 + 11(border) + 13(padding) - 40(scroll)
+    is(InspectorUI.highlighter._highlightRect.height, 184,
+      "highlighter height");
+
+    Services.obs.addObserver(finishUp,
+      INSPECTOR_NOTIFICATIONS.CLOSED, false);
+    InspectorUI.closeInspectorUI();
+  }
+
+  function finishUp() {
+    Services.obs.removeObserver(finishUp, INSPECTOR_NOTIFICATIONS.CLOSED);
+    doc = iframeNode = iframeBodyNode = null;
+    gBrowser.removeCurrentTab();
+    finish();
+  }
+
+
+  function moveMouseOver(aElement, x, y)
+  {
+    EventUtils.synthesizeMouse(aElement, x, y, {type: "mousemove"},
+                               aElement.ownerDocument.defaultView);
+  }
+
+}
+
--- a/browser/devtools/sourceeditor/source-editor-textarea.jsm
+++ b/browser/devtools/sourceeditor/source-editor-textarea.jsm
@@ -1,9 +1,9 @@
-/* vim:set ts=2 sw=2 sts=2 et tw=80:
+/* vim:set ft=javascript ts=2 sw=2 sts=2 et tw=80:
  * ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
@@ -124,17 +124,17 @@ SourceEditor.prototype = {
     this._editor = this._textbox.editor;
 
     this._expandTab = aConfig.expandTab !== undefined ?
                       aConfig.expandTab : SourceEditor.DEFAULTS.EXPAND_TAB;
     this._tabSize = aConfig.tabSize || SourceEditor.DEFAULTS.TAB_SIZE;
 
     this._textbox.style.MozTabSize = this._tabSize;
 
-    this._textbox.setAttribute("value", aConfig.placeholderText);
+    this._textbox.setAttribute("value", aConfig.placeholderText || "");
     this._textbox.setAttribute("class", "monospace");
     this._textbox.style.direction = "ltr";
     this._textbox.readOnly = aConfig.readOnly;
 
     // Make sure that the SourceEditor Selection events are fired properly.
     // Also make sure that the Tab key inserts spaces when expandTab is true.
     this._textbox.addEventListener("select", this._onSelect.bind(this), false);
     this._textbox.addEventListener("keypress", this._onKeyPress.bind(this), false);
--- a/browser/devtools/styleinspector/CssHtmlTree.jsm
+++ b/browser/devtools/styleinspector/CssHtmlTree.jsm
@@ -35,16 +35,17 @@
  * 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 Cu = Components.utils;
+const FILTER_CHANGED_TIMEOUT = 300;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/PluralForm.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource:///modules/devtools/CssLogic.jsm");
 Cu.import("resource:///modules/devtools/Templater.jsm");
 
 var EXPORTED_SYMBOLS = ["CssHtmlTree", "PropertyView"];
@@ -60,31 +61,32 @@ var EXPORTED_SYMBOLS = ["CssHtmlTree", "
  */
 function CssHtmlTree(aStyleWin, aCssLogic, aPanel)
 {
   this.styleWin = aStyleWin;
   this.cssLogic = aCssLogic;
   this.doc = aPanel.ownerDocument;
   this.win = this.doc.defaultView;
   this.getRTLAttr = CssHtmlTree.getRTLAttr;
+  this.propertyViews = {};
 
   // The document in which we display the results (csshtmltree.xhtml).
   this.styleDocument = this.styleWin.contentWindow.document;
 
   // Nodes used in templating
   this.root = this.styleDocument.getElementById("root");
+  this.path = this.styleDocument.getElementById("path");
   this.templateRoot = this.styleDocument.getElementById("templateRoot");
+  this.templatePath = this.styleDocument.getElementById("templatePath");
   this.propertyContainer = this.styleDocument.getElementById("propertyContainer");
   this.templateProperty = this.styleDocument.getElementById("templateProperty");
   this.panel = aPanel;
 
   // The element that we're inspecting, and the document that it comes from.
   this.viewedElement = null;
-  this.viewedDocument = null;
-
   this.createStyleViews();
 }
 
 /**
  * Memonized lookup of a l10n string from a string bundle.
  * @param {string} aName The key to lookup.
  * @returns A localized version of the given key.
  */
@@ -143,86 +145,154 @@ XPCOMUtils.defineLazyGetter(CssHtmlTree,
   let mainWindow = Services.wm.getMostRecentWindow("navigator:browser");
   return mainWindow.getComputedStyle(mainWindow.gBrowser).direction;
 });
 
 XPCOMUtils.defineLazyGetter(CssHtmlTree, "_strings", function() Services.strings
     .createBundle("chrome://browser/locale/styleinspector.properties"));
 
 CssHtmlTree.prototype = {
+  htmlComplete: false,
+
+  // Used for cancelling timeouts in the style filter.
+  filterChangedTimeout: null,
+
+  // The search filter
+  searchField: null,
+  
+  // Reference to the "Only user Styles" checkbox.
+  onlyUserStylesCheckbox: null,
+
+  get showOnlyUserStyles()
+  {
+    return this.onlyUserStylesCheckbox.checked;
+  },
+
   /**
-   * Focus the output display on a specific element.
+   * Update the highlighted element. The CssHtmlTree panel will show the style
+   * information for the given element.
    * @param {nsIDOMElement} aElement The highlighted node to get styles for.
    */
   highlight: function CssHtmlTree_highlight(aElement)
   {
     if (this.viewedElement == aElement) {
       return;
     }
 
     this.viewedElement = aElement;
 
-    if (this.viewedElement) {
-      this.viewedDocument = this.viewedElement.ownerDocument;
-      CssHtmlTree.processTemplate(this.templateRoot, this.root, this);
+    CssHtmlTree.processTemplate(this.templatePath, this.path, this);
+
+    if (this.htmlComplete) {
+      this.refreshPanel();
     } else {
-      this.viewedDocument = null;
-      this.root.innerHTML = "";
-    }
-
-    this.propertyContainer.innerHTML = "";
+      CssHtmlTree.processTemplate(this.templateRoot, this.root, this);
 
-    // We use a setTimeout loop to display the properties in batches of 25 at a
-    // time. This gives a perceptibly more responsive UI and allows us to cancel
-    // the displaying of properties in the case that a new element is selected.
-    let i = 0;
-    let batchSize = 25;
-    let max = CssHtmlTree.propertyNames.length - 1;
-    function displayProperties() {
-      if (this.viewedElement == aElement && this.panel.isOpen()) {
-        // Display the next 25 properties
-        for (let step = i + batchSize; i < step && i <= max; i++) {
-          let propView = new PropertyView(this, CssHtmlTree.propertyNames[i]);
-          CssHtmlTree.processTemplate(
-              this.templateProperty, this.propertyContainer, propView, true);
-        }
-        if (i < max) {
-          // There are still some properties to display. We loop here to display
-          // the next batch of 25.
-          this.win.setTimeout(displayProperties.bind(this), 0);
+      // We use a setTimeout loop to display the properties in batches of 15 at a
+      // time. This results in a perceptibly more responsive UI.
+      let i = 0;
+      let batchSize = 15;
+      let max = CssHtmlTree.propertyNames.length - 1;
+      function displayProperties() {
+        if (this.viewedElement == aElement && this.panel.isOpen()) {
+          // Display the next 15 properties
+          for (let step = i + batchSize; i < step && i <= max; i++) {
+            let name = CssHtmlTree.propertyNames[i];
+            let propView = new PropertyView(this, name);
+            CssHtmlTree.processTemplate(this.templateProperty,
+              this.propertyContainer, propView, true);
+            propView.refreshMatchedSelectors();
+            propView.refreshUnmatchedSelectors();
+            this.propertyViews[name] = propView;
+          }
+          if (i < max) {
+            // There are still some properties to display. We loop here to display
+            // the next batch of 15.
+            this.win.setTimeout(displayProperties.bind(this), 50);
+          } else {
+            this.htmlComplete = true;
+            Services.obs.notifyObservers(null, "StyleInspector-populated", null);
+          }
         }
       }
+      this.win.setTimeout(displayProperties.bind(this), 50);
     }
-    this.win.setTimeout(displayProperties.bind(this), 0);
+  },
+
+  /**
+   * Refresh the panel content.
+   */
+  refreshPanel: function CssHtmlTree_refreshPanel()
+  {
+    for each(let propView in this.propertyViews) {
+      propView.refresh();
+    }
+    Services.obs.notifyObservers(null, "StyleInspector-populated", null);
   },
 
   /**
    * Called when the user clicks on a parent element in the "current element"
    * path.
    *
    * @param {Event} aEvent the DOM Event object.
    */
   pathClick: function CssHtmlTree_pathClick(aEvent)
   {
     aEvent.preventDefault();
     if (aEvent.target && this.viewedElement != aEvent.target.pathElement) {
-      this.propertyContainer.innerHTML = "";
       if (this.win.InspectorUI.selection) {
         if (aEvent.target.pathElement != this.win.InspectorUI.selection) {
           let elt = aEvent.target.pathElement;
           this.win.InspectorUI.inspectNode(elt);
           this.panel.selectNode(elt);
         }
       } else {
         this.panel.selectNode(aEvent.target.pathElement);
       }
     }
   },
 
   /**
+   * Called when the user enters a search term.
+   *
+   * @param {Event} aEvent the DOM Event object.
+   */
+  filterChanged: function CssHtmlTree_filterChanged(aEvent)
+  {
+    let win = this.styleWin.contentWindow;
+
+    if (this.filterChangedTimeout) {
+      win.clearTimeout(this.filterChangedTimeout);
+      this.filterChangeTimeout = null;
+    }
+
+    this.filterChangedTimeout = win.setTimeout(function() {
+      this.refreshPanel();
+    }.bind(this), FILTER_CHANGED_TIMEOUT);
+  },
+
+  /**
+   * The change event handler for the onlyUserStyles checkbox. When
+   * onlyUserStyles.checked is true we do not display properties that have no
+   * matched selectors, and we do not display UA styles. If .checked is false we
+   * do display even properties with no matched selectors, and we include the UA
+   * styles.
+   *
+   * @param {Event} aEvent the DOM Event object.
+   */
+  onlyUserStylesChanged: function CssHtmltree_onlyUserStylesChanged(aEvent)
+  {
+    this.cssLogic.sourceFilter = this.showOnlyUserStyles ?
+                                 CssLogic.FILTER.ALL :
+                                 CssLogic.FILTER.UA;
+    
+    this.refreshPanel();
+  },
+
+  /**
    * Provide access to the path to get from document.body to the selected
    * element.
    *
    * @return {array} the array holding the path from document.body to the
    * selected element.
    */
   get pathElements()
   {
@@ -268,184 +338,281 @@ CssHtmlTree.prototype = {
  * instance will render the rules.
  */
 function PropertyView(aTree, aName)
 {
   this.tree = aTree;
   this.name = aName;
   this.getRTLAttr = CssHtmlTree.getRTLAttr;
 
-  this.populated = false;
-  this.showUnmatched = false;
-
   this.link = "https://developer.mozilla.org/en/CSS/" + aName;
 
-  this.templateRules = aTree.styleDocument.getElementById("templateRules");
-
-  // The parent element which contains the open attribute
-  this.element = null;
-  // Destination for templateRules.
-  this.rules = null;
-
-  this.str = {};
+  this.templateMatchedSelectors = aTree.styleDocument.getElementById("templateMatchedSelectors");
+  this.templateUnmatchedSelectors = aTree.styleDocument.getElementById("templateUnmatchedSelectors");
 }
 
 PropertyView.prototype = {
-  /**
-   * The click event handler for the property name of the property view. If
-   * there are >0 rules then the rules are expanded. If there are 0 rules and
-   * >0 unmatched rules then the unmatched rules are expanded instead.
-   *
-   * @param {Event} aEvent the DOM event
-   */
-  click: function PropertyView_click(aEvent)
-  {
-    // Clicking on the property link itself is already handled
-    if (aEvent.target.tagName.toLowerCase() == "a") {
-      return;
-    }
+  // The parent element which contains the open attribute
+  element: null,
+
+  // Destination for property values
+  valueNode: null,
+
+  // Are matched rules expanded?
+  matchedExpanded: false,
+
+  // Are unmatched rules expanded?
+  unmatchedExpanded: false,
+
+  // Matched selector container
+  matchedSelectorsContainer: null,
+
+  // Unmatched selector container
+  unmatchedSelectorsContainer: null,
+
+  // Matched selector expando
+  matchedExpander: null,
 
-    if (this.element.hasAttribute("open")) {
-      this.element.removeAttribute("open");
-      return;
-    }
+  // Unmatched selector expando
+  unmatchedExpander: null,
+
+  // Container for X matched selectors
+  matchedSelectorsTitleNode: null,
 
-    if (!this.populated) {
-      let matchedRuleCount = this.propertyInfo.matchedRuleCount;
+  // Container for X unmatched selectors
+  unmatchedSelectorsTitleNode: null,
+
+  // Matched selectors table
+  matchedSelectorTable: null,
 
-      if (matchedRuleCount == 0 && this.showUnmatchedLink) {
-        this.showUnmatchedLinkClick(aEvent);
-      } else {
-        CssHtmlTree.processTemplate(this.templateRules, this.rules, this);
-      }
-      this.populated = true;
-    }
-    this.element.setAttribute("open", "");
-  },
+  // Unmatched selectors table
+  unmatchedSelectorTable: null,
+
+  // Cache for matched selector views
+  _matchedSelectorViews: null,
+
+  // Cache for unmatched selector views
+  _unmatchedSelectorViews: null,
+
+  // The previously selected element used for the selector view caches
+  prevViewedElement: null,
 
   /**
    * Get the computed style for the current property.
    *
    * @return {string} the computed style for the current property of the
    * currently highlighted element.
    */
   get value()
   {
     return this.propertyInfo.value;
   },
 
   /**
-   * An easy way to access the CssPropertyInfo behind this PropertyView
+   * An easy way to access the CssPropertyInfo behind this PropertyView.
    */
   get propertyInfo()
   {
     return this.tree.cssLogic.getPropertyInfo(this.name);
   },
 
   /**
-   * Compute the title of the property view. The title includes the number of
-   * selectors that match the currently selected element.
+   * Should this property be visible?
+   */
+  get visible()
+  {
+    if (this.tree.showOnlyUserStyles && this.matchedSelectorCount == 0) {
+      return false;
+    }
+
+    let searchTerm = this.tree.searchField.value.toLowerCase();
+    if (searchTerm && this.name.toLowerCase().indexOf(searchTerm) == -1 &&
+      this.value.toLowerCase().indexOf(searchTerm) == -1) {
+      return false;
+    }
+
+    return true;
+  },
+
+  /**
+   * Returns the className that should be assigned to the propertyView.
+   */
+  get className()
+  {
+    return this.visible ? "property-view" : "property-view-hidden";
+  },
+
+  /**
+   * The number of matched selectors.
+   */
+  get matchedSelectorCount()
+  {
+    return this.propertyInfo.matchedSelectors.length;
+  },
+
+  /**
+   * The number of unmatched selectors.
+   */
+  get unmatchedSelectorCount()
+  {
+    return this.propertyInfo.unmatchedSelectors.length;
+  },
+
+  /**
+   * Refresh the panel's CSS property value.
+   */
+  refresh: function PropertyView_refresh()
+  {
+    this.element.className = this.className;
+
+    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.unmatchedSelectorsContainer.hidden = true;
+      this.matchedSelectorTable.innerHTML = "";
+      this.unmatchedSelectorTable.innerHTML = "";
+      this.matchedExpander.removeAttribute("open");
+      this.unmatchedExpander.removeAttribute("open");
+      return;
+    }
+
+    this.valueNode.innerHTML = this.propertyInfo.value;
+    
+    this.refreshMatchedSelectors();
+    this.refreshUnmatchedSelectors();
+  },
+
+  /**
+   * Refresh the panel matched rules.
+   */
+  refreshMatchedSelectors: function PropertyView_refreshMatchedSelectors()
+  {
+    this.matchedSelectorsTitleNode.innerHTML = this.matchedSelectorTitle();
+    this.matchedSelectorsContainer.hidden = this.matchedSelectorCount == 0;
+
+    if (this.matchedExpanded && this.matchedSelectorCount > 0) {
+      CssHtmlTree.processTemplate(this.templateMatchedSelectors,
+        this.matchedSelectorTable, this);
+      this.matchedExpander.setAttribute("open", "");
+    } else {
+      this.matchedSelectorTable.innerHTML = "";
+      this.matchedExpander.removeAttribute("open");
+    }
+  },
+
+  /**
+   * Refresh the panel unmatched rules.
+   */
+  refreshUnmatchedSelectors: function PropertyView_refreshUnmatchedSelectors() {
+    this.unmatchedSelectorsTitleNode.innerHTML = this.unmatchedSelectorTitle();
+    this.unmatchedSelectorsContainer.hidden = this.unmatchedSelectorCount == 0;
+
+    if (this.unmatchedExpanded && this.unmatchedSelectorCount > 0) {
+      CssHtmlTree.processTemplate(this.templateUnmatchedSelectors,
+          this.unmatchedSelectorTable, this);
+      this.unmatchedExpander.setAttribute("open", "");
+    } else {
+      this.unmatchedSelectorTable.innerHTML = "";
+      this.unmatchedExpander.removeAttribute("open");
+    }
+  },
+
+  /**
+   * Compute the title of the matched selector expander. The title includes the
+   * number of selectors that match the currently selected element.
    *
-   * @param {nsIDOMElement} aElement reference to the DOM element where the rule
-   * title needs to be displayed.
    * @return {string} The rule title.
    */
-  ruleTitle: function PropertyView_ruleTitle(aElement)
+  matchedSelectorTitle: function PropertyView_matchedSelectorTitle()
   {
     let result = "";
-    let matchedSelectorCount = this.propertyInfo.matchedSelectors.length;
 
-    if (matchedSelectorCount > 0) {
-      aElement.classList.add("rule-count");
-      aElement.firstElementChild.className = "expander";
-
-      let str = CssHtmlTree.l10n("property.numberOfSelectors");
-      result = PluralForm.get(matchedSelectorCount, str)
-          .replace("#1", matchedSelectorCount);
-    } else if (this.showUnmatchedLink) {
-      aElement.classList.add("rule-unmatched");
-      aElement.firstElementChild.className = "expander";
-
-      let unmatchedSelectorCount = this.propertyInfo.unmatchedSelectors.length;
-      let str = CssHtmlTree.l10n("property.numberOfUnmatchedSelectors");
-      result = PluralForm.get(unmatchedSelectorCount, str)
-          .replace("#1", unmatchedSelectorCount);
+    if (this.matchedSelectorCount > 0) {
+      let str = CssHtmlTree.l10n("property.numberOfMatchedSelectors");
+      result = PluralForm.get(this.matchedSelectorCount, str)
+                         .replace("#1", this.matchedSelectorCount);
     }
     return result;
   },
 
   /**
-   * Close the property view.
+   * Compute the title of the unmatched selector expander. The title includes
+   * the number of selectors that match the currently selected element.
+   *
+   * @return {string} The rule title.
    */
-  close: function PropertyView_close()
+  unmatchedSelectorTitle: function PropertyView_unmatchedSelectorTitle()
   {
-    if (this.rules && this.element) {
-      this.element.removeAttribute("open");
-    }
-  },
+    let result = "";
 
-  /**
-   * Reset the property view.
-   */
-  reset: function PropertyView_reset()
-  {
-    this.close();
-    this.populated = false;
-    this.showUnmatched = false;
-    this.element = false;
+    if (this.unmatchedSelectorCount > 0) {
+      let str = CssHtmlTree.l10n("property.numberOfUnmatchedSelectors");
+      result = PluralForm.get(this.unmatchedSelectorCount, str)
+                         .replace("#1", this.unmatchedSelectorCount);
+    }
+    return result;
   },
 
   /**
-   * Provide access to the SelectorViews that we are currently displaying
+   * Provide access to the matched SelectorViews that we are currently
+   * displaying.
    */
-  get selectorViews()
+  get matchedSelectorViews()
   {
-    var all = [];
-
-    function convert(aSelectorInfo) {
-      all.push(new SelectorView(aSelectorInfo));
+    if (!this._matchedSelectorViews) {
+      this._matchedSelectorViews = [];
+      this.propertyInfo.matchedSelectors.forEach(
+        function matchedSelectorViews_convert(aSelectorInfo) {
+          this._matchedSelectorViews.push(new SelectorView(aSelectorInfo));
+        }, this);
     }
 
-    this.propertyInfo.matchedSelectors.forEach(convert);
-    if (this.showUnmatched) {
-      this.propertyInfo.unmatchedSelectors.forEach(convert);
+    return this._matchedSelectorViews;
+  },
+
+    /**
+   * Provide access to the unmatched SelectorViews that we are currently
+   * displaying.
+   */
+  get unmatchedSelectorViews()
+  {
+    if (!this._unmatchedSelectorViews) {
+      this._unmatchedSelectorViews = [];
+      this.propertyInfo.unmatchedSelectors.forEach(
+        function unmatchedSelectorViews_convert(aSelectorInfo) {
+          this._unmatchedSelectorViews.push(new SelectorView(aSelectorInfo));
+        }, this);
     }
 
-    return all;
+    return this._unmatchedSelectorViews;
   },
 
   /**
-   * Should we display a 'X unmatched rules' link?
-   * @return {boolean} false if we are already showing the unmatched links or
-   * if there are none to display, true otherwise.
+   * The action when a user expands matched selectors.
    */
-  get showUnmatchedLink()
+  matchedSelectorsClick: function PropertyView_matchedSelectorsClick(aEvent)
   {
-    return !this.showUnmatched && this.propertyInfo.unmatchedRuleCount > 0;
+    this.matchedExpanded = !this.matchedExpanded;
+    this.refreshMatchedSelectors();
+    aEvent.preventDefault();
   },
 
   /**
-   * The UI has a link to allow the user to display unmatched selectors.
-   * This provides localized link text.
+   * The action when a user expands unmatched selectors.
    */
-  get showUnmatchedLinkText()
+  unmatchedSelectorsClick: function PropertyView_unmatchedSelectorsClick(aEvent)
   {
-    let smur = CssHtmlTree.l10n("rule.showUnmatchedLink");
-    let unmatchedSelectorCount = this.propertyInfo.unmatchedSelectors.length;
-    let plural = PluralForm.get(unmatchedSelectorCount, smur);
-    return plural.replace("#1", unmatchedSelectorCount);
-  },
-
-  /**
-   * The action when a user clicks the 'show unmatched' link.
-   */
-  showUnmatchedLinkClick: function PropertyView_showUnmatchedLinkClick(aEvent)
-  {
-    this.showUnmatched = true;
-    CssHtmlTree.processTemplate(this.templateRules, this.rules, this);
+    this.unmatchedExpanded = !this.unmatchedExpanded;
+    this.refreshUnmatchedSelectors();
     aEvent.preventDefault();
   },
 };
 
 /**
  * A container to view us easy access to display data from a CssRule
  */
 function SelectorView(aSelectorInfo)
--- a/browser/devtools/styleinspector/StyleInspector.jsm
+++ b/browser/devtools/styleinspector/StyleInspector.jsm
@@ -63,28 +63,26 @@ var StyleInspector = {
    */
   createPanel: function SI_createPanel(aPreserveOnHide)
   {
     let win = Services.wm.getMostRecentWindow("navigator:browser");
     let popupSet = win.document.getElementById("mainPopupSet");
     let ns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
     let panel = win.document.createElementNS(ns, "panel");
 
+    panel.setAttribute("class", "styleInspector");
     panel.setAttribute("orient", "vertical");
     panel.setAttribute("ignorekeys", "true");
     panel.setAttribute("noautofocus", "true");
     panel.setAttribute("noautohide", "true");
     panel.setAttribute("titlebar", "normal");
     panel.setAttribute("close", "true");
     panel.setAttribute("label", StyleInspector.l10n("panelTitle"));
-
-    // size panel to 200px wide by half browser height - 60.
-    let contentWindow = win.gBrowser.selectedBrowser.contentWindow;
-    panel.setAttribute("width", 200);
-    panel.setAttribute("height", contentWindow.outerHeight / 2 - 60);
+    panel.setAttribute("width", 350);
+    panel.setAttribute("height", win.screen.height / 2);
 
     let vbox = win.document.createElement("vbox");
     vbox.setAttribute("flex", "1");
     panel.appendChild(vbox);
 
     let iframe = win.document.createElementNS(ns, "iframe");
     iframe.setAttribute("flex", "1");
     iframe.setAttribute("tooltip", "aHTMLTooltip");
--- a/browser/devtools/styleinspector/csshtmltree.xhtml
+++ b/browser/devtools/styleinspector/csshtmltree.xhtml
@@ -61,29 +61,49 @@
     href="chrome://browser/skin/devtools/csshtmltree.css" />
 </head>
 <body role="application">
 
 <!-- The output from #templateRoot (below) is inserted here. -->
 <div id="root">
 </div>
 
+<!-- The output from #templatePath (below) is inserted here. -->
+<div id="path">
+</div>
+
 <!-- The output from #templateProperty (below) is appended here. -->
 <div id="propertyContainer">
 </div>
 
 <!--
 To visually debug the templates without running firefox, alter the display:none
 -->
 <div style="display:none;">
   <!--
-  templateRoot sits at the top of the window showing what we're looking at.
-  For data it needs an instance of CssHtmlTree.
+  templateRoot sits at the top of the window and contains the "include default
+  styles" checkbox. For data it needs an instance of CssHtmlTree.
   -->
   <div id="templateRoot">
+    <div class="filters">
+      <label class="userStylesLabel" dir="${getRTLAttr}">
+        &userStylesLabel;
+        <input class="userStyles" save="${onlyUserStylesCheckbox}" type="checkbox"
+               onchange="${onlyUserStylesChanged}" checked=""/>
+      </label>
+      <input save="${searchField}" class="searchfield" type="text"
+             oninput="${filterChanged}"/>
+    </div>
+  </div>
+
+  <!--
+  templatePath sits just below the top of the window showing what we're looking
+  at. For data it needs an instance of CssHtmlTree.
+  -->
+  <div id="templatePath">
     <p class="path">
       <label dir="${getRTLAttr}">&lookingAtLabel;</label>
       <ol>
         <li foreach="item in ${pathElements}" dir="${getRTLAttr}">
           <a href="#" onclick="${pathClick}" __pathElement="${item.element}">
             ${__element.pathElement = item.element; item.display}
           </a>
         </li>
@@ -93,61 +113,92 @@ To visually debug the templates without 
 
   <!--
   TemplateProperty lists the properties themselves. Each needs data like this:
   {
     property: ... // PropertyView from CssHtmlTree.jsm
   }
   -->
   <div id="templateProperty">
-    <div class="property-view" save="${element}" dir="${getRTLAttr}">
-      <div class="property-header" onclick="${click}">
+    <div class="${className}" save="${element}" dir="${getRTLAttr}">
+      <div class="property-header">
         <div class="property-name" dir="${getRTLAttr}">
           <a class="link" target="_blank" title="&helpLinkTitle;"
               href="${link}">${name}</a>
         </div>
-        <div class="property-value" dir="ltr">${value}</div>
-        <div class="link" dir="${getRTLAttr}">
-          <div></div>${ruleTitle(__element)}
+        <div save="${valueNode}" class="property-value" dir="ltr">${value}</div>
+      </div>
+
+      <div save="${matchedSelectorsContainer}" class="rulelink" dir="${getRTLAttr}">
+        <div onclick="${matchedSelectorsClick}" class="rule-matched">
+          <div save="${matchedExpander}" class="expander"></div>
+          <div save="${matchedSelectorsTitleNode}">
+            ${matchedSelectorTitle(__element)}
+          </div>
         </div>
+        <table save="${matchedSelectorTable}" dir="${getRTLAttr}"></table>
       </div>
-      <table class="rules" save="${rules}" dir="${getRTLAttr}"></table>
+
+      <div save="${unmatchedSelectorsContainer}" class="rulelink" dir="${getRTLAttr}">
+        <div onclick="${unmatchedSelectorsClick}" class="rule-unmatched">
+          <div save="${unmatchedExpander}" class="expander"></div>
+          <div save="${unmatchedSelectorsTitleNode}">
+            ${unmatchedSelectorTitle(__element)}
+          </div>
+        </div>
+        <table save="${unmatchedSelectorTable}" dir="${getRTLAttr}"></table>
+      </div>
     </div>
   </div>
 
   <!--
-  A templateRules sits inside each templateProperties showing the list of rules
-  that affect that property. Each needs data like this:
+  A templateMatchedSelectors sits inside each templateProperties showing the
+  list of selectors that affect that property. Each needs data like this:
   {
-    selectors: ..., // from cssLogic.getPropertyInfo(x).[un]matchedSelectors
-    statusText: function(status) {}, // convert rule.status to readable text
-    showUnmatchedRules: true / false, // show a "more unmatched rules" link
-    showUnmatchedRulesClick: function() {}, // click event handler for the
-        "show more unmatched rules"
+    matchedSelectorViews: ..., // from cssHtmlTree.propertyViews[name].matchedSelectorViews
   }
   This is a template so the parent does not need to be a table, except that
   using a div as the parent causes the DOM to muck with the tr elements
   -->
-  <table id="templateRules">
-    <loop foreach="selector in ${selectorViews}" if="${selector.selectorInfo.sheetAllowed}">
-      <tr>
-        <td dir="ltr" class="rule-text ${selector.statusClass}">
-          ${selector.humanReadableText(__element)}
-        </td>
-        <td class="rule-link">
-          <a target="_blank" href="view-source:${selector.selectorInfo.href}" class="link"
-              title="${selector.selectorInfo.href}">${selector.selectorInfo.source}</a>
-        </td>
-      </tr>
-    </loop>
-    <tr if="${showUnmatchedLink}">
-      <td colspan="4">
-        <div class="expander unmatched-rule"></div>
-        <div class="unmatched">
-          <a href="#" onclick="${showUnmatchedLinkClick}" class="unmatchedlink">${showUnmatchedLinkText}</a>
-        </div>
-      </td>
-    </tr>
-  </table>
+  <div id="templateMatchedSelectors">
+    <table>
+      <loop foreach="selector in ${matchedSelectorViews}">
+        <tr>
+          <td dir="ltr" class="rule-text ${selector.statusClass}">
+            ${selector.humanReadableText(__element)}
+          </td>
+          <td class="rule-link">
+            <a target="_blank" href="view-source:${selector.selectorInfo.href}" class="link"
+                title="${selector.selectorInfo.href}">${selector.selectorInfo.source}</a>
+          </td>
+        </tr>
+      </loop>
+    </table>
+  </div>
+
+  <!--
+  A templateUnmatchedSelectors sits inside each templateProperties showing the
+  list of selectors that fail to affect that property. Each needs data like this:
+  {
+    unmatchedSelectorViews: ..., // from cssHtmlTree.propertyViews[name].unmatchedSelectorViews
+  }
+  This is a template so the parent does not need to be a table, except that
+  using a div as the parent causes the DOM to muck with the tr elements
+  -->
+  <div id="templateUnmatchedSelectors">
+    <table>
+      <loop foreach="selector in ${unmatchedSelectorViews}">
+        <tr>
+          <td dir="ltr" class="rule-text unmatched">
+            ${selector.humanReadableText(__element)}
+          </td>
+          <td class="rule-link">
+            <a target="_blank" href="view-source:${selector.selectorInfo.href}" class="link"
+                title="${selector.selectorInfo.href}">${selector.selectorInfo.source}</a>
+          </td>
+        </tr>
+      </loop>
+    </table>
+  </div>
 </div>
 
 </body>
 </html>
--- a/browser/devtools/styleinspector/test/browser/Makefile.in
+++ b/browser/devtools/styleinspector/test/browser/Makefile.in
@@ -44,16 +44,18 @@ relativesrcdir  = browser/devtools/style
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_TEST_FILES = \
   browser_styleinspector.js \
   browser_styleinspector_webconsole.js \
   browser_bug683672.js \
+  browser_styleinspector_bug_672746_default_styles.js \
+  browser_styleinspector_bug_672744_search_filter.js \
   head.js \
   $(NULL)
 
 _BROWSER_TEST_PAGES = \
   browser_styleinspector_webconsole.htm \
   browser_bug683672.html \
   $(NULL)
 
--- a/browser/devtools/styleinspector/test/browser/browser_bug683672.js
+++ b/browser/devtools/styleinspector/test/browser/browser_bug683672.js
@@ -56,26 +56,25 @@ function testMatchedSelectors()
       "style inspector node matches the selected node");
 
   let propertyView = new PropertyView(htmlTree, "color");
   let numMatchedSelectors = propertyView.propertyInfo.matchedSelectors.length;
 
   is(numMatchedSelectors, 6,
       "CssLogic returns the correct number of matched selectors for div");
 
-  let dummy = content.document.getElementById("dummy");
-  let returnedRuleTitle = propertyView.ruleTitle(dummy);
-  let str = CssHtmlTree.l10n("property.numberOfSelectors");
-  let calculatedRuleTitle = PluralForm.get(numMatchedSelectors, str)
+  let returnedSelectorTitle = propertyView.matchedSelectorTitle();
+  let str = CssHtmlTree.l10n("property.numberOfMatchedSelectors");
+  let calculatedSelectorTitle = PluralForm.get(numMatchedSelectors, str)
                                       .replace("#1", numMatchedSelectors);
 
-  info("returnedRuleTitle: '" + returnedRuleTitle + "'");
+  info("returnedSelectorTitle: '" + returnedSelectorTitle + "'");
 
-  is(returnedRuleTitle, calculatedRuleTitle,
-      "returned title for matched rules is correct");
+  is(returnedSelectorTitle, calculatedSelectorTitle,
+      "returned title for matched selectors is correct");
 }
 
 function testUnmatchedSelectors()
 {
   info("checking selector counts, unmatched rules and titles");
   let body = content.document.body;
   ok(body, "captain, we have a body");
 
@@ -88,26 +87,25 @@ function testUnmatchedSelectors()
       "style inspector node matches the selected node");
 
   let propertyView = new PropertyView(htmlTree, "color");
   let numUnmatchedSelectors = propertyView.propertyInfo.unmatchedSelectors.length;
 
   is(numUnmatchedSelectors, 13,
       "CssLogic returns the correct number of unmatched selectors for body");
 
-  let dummy = content.document.getElementById("dummy");
-  let returnedRuleTitle = propertyView.ruleTitle(dummy);
+  let returnedSelectorTitle = propertyView.unmatchedSelectorTitle();
   let str = CssHtmlTree.l10n("property.numberOfUnmatchedSelectors");
-  let calculatedRuleTitle = PluralForm.get(numUnmatchedSelectors, str)
+  let calculatedSelectorTitle = PluralForm.get(numUnmatchedSelectors, str)
                                       .replace("#1", numUnmatchedSelectors);
 
-  info("returnedRuleTitle: '" + returnedRuleTitle + "'");
+  info("returnedSelectorTitle: '" + returnedSelectorTitle + "'");
 
-  is(returnedRuleTitle, calculatedRuleTitle,
-      "returned title for unmatched rules is correct");
+  is(returnedSelectorTitle, calculatedSelectorTitle,
+      "returned title for unmatched selectors is correct");
 }
 
 function finishUp()
 {
   Services.obs.removeObserver(finishUp, "StyleInspector-closed", false);
   ok(!stylePanel.isOpen(), "style inspector is closed");
   doc = stylePanel = null;
   gBrowser.removeCurrentTab();
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser/browser_styleinspector_bug_672744_search_filter.js
@@ -0,0 +1,112 @@
+/* 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 search filter works properly.
+
+let doc;
+let stylePanel;
+
+function createDocument()
+{
+  doc.body.innerHTML = '<style type="text/css"> ' +
+    '.matches {color: #F00;}</style>' +
+    '<span id="matches" class="matches">Some styled text</span>' +
+    '</div>';
+  doc.title = "Style Inspector Search Filter Test";
+  ok(window.StyleInspector, "StyleInspector exists");
+  ok(StyleInspector.isEnabled, "style inspector preference is enabled");
+  stylePanel = StyleInspector.createPanel();
+  Services.obs.addObserver(runStyleInspectorTests, "StyleInspector-opened", false);
+  stylePanel.openPopup(gBrowser.selectedBrowser, "end_before", 0, 0, false, false);
+}
+
+function runStyleInspectorTests()
+{
+  Services.obs.removeObserver(runStyleInspectorTests, "StyleInspector-opened", false);
+
+  ok(stylePanel.isOpen(), "style inspector is open");
+
+  Services.obs.addObserver(SI_toggleDefaultStyles, "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_toggleDefaultStyles()
+{
+  Services.obs.removeObserver(SI_toggleDefaultStyles, "StyleInspector-populated", false);
+
+  info("clearing \"only user styles\" checkbox");
+  let iframe = stylePanel.querySelector("iframe");
+  let checkbox = iframe.contentDocument.querySelector(".userStyles");
+  Services.obs.addObserver(SI_AddFilterText, "StyleInspector-populated", false);
+  EventUtils.synthesizeMouse(checkbox, 5, 5, {}, iframe.contentWindow);
+}
+
+function SI_AddFilterText()
+{
+  Services.obs.removeObserver(SI_AddFilterText, "StyleInspector-populated", false);
+
+  let iframe = stylePanel.querySelector("iframe");
+  let searchbar = iframe.contentDocument.querySelector(".searchfield");
+
+  Services.obs.addObserver(SI_checkFilter, "StyleInspector-populated", false);
+  info("setting filter text to \"color\"");
+  searchbar.focus();
+  EventUtils.synthesizeKey("c", {}, iframe.contentWindow);
+  EventUtils.synthesizeKey("o", {}, iframe.contentWindow);
+  EventUtils.synthesizeKey("l", {}, iframe.contentWindow);
+  EventUtils.synthesizeKey("o", {}, iframe.contentWindow);
+  EventUtils.synthesizeKey("r", {}, iframe.contentWindow);
+}
+
+function SI_checkFilter()
+{
+  Services.obs.removeObserver(SI_checkFilter, "StyleInspector-populated", false);
+  let propertyViews = stylePanel.cssHtmlTree.propertyViews;
+
+  info("check that the correct properties are visible");
+  for each(let propView in propertyViews) {
+    let name = propView.name;
+    is(propView.visible, name.indexOf("color") > -1,
+      "span " + name + " property visibility check");
+  }
+
+  Services.obs.addObserver(finishUp, "StyleInspector-closed", false);
+  stylePanel.hidePopup();
+}
+
+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";
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser/browser_styleinspector_bug_672746_default_styles.js
@@ -0,0 +1,107 @@
+/* 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 checkbox to show only user styles works properly.
+
+let doc;
+let stylePanel;
+
+function createDocument()
+{
+  doc.body.innerHTML = '<style type="text/css"> ' +
+    '.matches {color: #F00;}</style>' +
+    '<span id="matches" class="matches">Some styled text</span>' +
+    '</div>';
+  doc.title = "Style Inspector Default Styles Test";
+  ok(window.StyleInspector, "StyleInspector exists");
+  ok(StyleInspector.isEnabled, "style inspector preference is enabled");
+  stylePanel = StyleInspector.createPanel();
+  Services.obs.addObserver(runStyleInspectorTests, "StyleInspector-opened", false);
+  stylePanel.openPopup(gBrowser.selectedBrowser, "end_before", 0, 0, false, false);
+}
+
+function runStyleInspectorTests()
+{
+  Services.obs.removeObserver(runStyleInspectorTests, "StyleInspector-opened", false);
+
+  ok(stylePanel.isOpen(), "style inspector is open");
+
+  Services.obs.addObserver(SI_check, "StyleInspector-populated", false);
+  SI_inspectNode();
+}
+
+function SI_inspectNode()
+{
+  let 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_check()
+{
+  Services.obs.removeObserver(SI_check, "StyleInspector-populated", false);
+  is(propertyVisible("color"), true,
+    "span #matches color property is visible");
+  is(propertyVisible("background-color"), false,
+    "span #matches background-color property is hidden");
+
+  SI_toggleDefaultStyles();
+}
+
+function SI_toggleDefaultStyles()
+{
+  // Click on the checkbox.
+  let iframe = stylePanel.querySelector("iframe");
+  let checkbox = iframe.contentDocument.querySelector(".userStyles");
+  Services.obs.addObserver(SI_checkDefaultStyles, "StyleInspector-populated", false);
+  EventUtils.synthesizeMouse(checkbox, 5, 5, {}, iframe.contentWindow);
+}
+
+function SI_checkDefaultStyles()
+{
+  Services.obs.removeObserver(SI_checkDefaultStyles, "StyleInspector-populated", false);
+  // Check that the default styles are now applied.
+  is(propertyVisible("color"), true,
+      "span color property is visible");
+  is(propertyVisible("background-color"), true,
+      "span background-color property is visible");
+
+  Services.obs.addObserver(finishUp, "StyleInspector-closed", false);
+  stylePanel.hidePopup();
+}
+
+function propertyVisible(aName)
+{
+  let propertyViews = stylePanel.cssHtmlTree.propertyViews;
+  return propertyViews[aName].className == "property-view";
+}
+
+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/webconsole/HUDService.jsm
+++ b/browser/devtools/webconsole/HUDService.jsm
@@ -3610,33 +3610,33 @@ HeadsUpDisplay.prototype = {
         ]
       }
     ];
 
     let toolbar = this.makeXULNode("toolbar");
     toolbar.setAttribute("class", "hud-console-filter-toolbar");
     toolbar.setAttribute("mode", "full");
 
-#ifdef XP_MAC
+#ifdef XP_MACOSX
     this.makeCloseButton(toolbar);
 #endif
 
     for (let i = 0; i < BUTTONS.length; i++) {
       this.makeFilterButton(toolbar, BUTTONS[i]);
     }
 
     toolbar.appendChild(this.filterSpacer);
 
     let positionUI = this.createPositionUI();
     toolbar.appendChild(positionUI);
 
     toolbar.appendChild(this.filterBox);
     this.makeClearConsoleButton(toolbar);
 
-#ifndef XP_MAC
+#ifndef XP_MACOSX
     this.makeCloseButton(toolbar);
 #endif
 
     return toolbar;
   },
 
   /**
    * Creates the UI for re-positioning the console
@@ -4433,17 +4433,17 @@ function JSTermHelper(aJSTerm)
       errstr = HUDService.getStr("inspectStyle.mustBeDomNode");
     } else if (!(aNode.style instanceof Ci.nsIDOMCSSStyleDeclaration)) {
       errstr = HUDService.getStr("inspectStyle.nodeHasNoStyleProps");
     }
 
     if (!errstr) {
       let stylePanel = StyleInspector.createPanel();
       stylePanel.setAttribute("hudToolId", aJSTerm.hudId);
-      stylePanel.selectNode(aNode, true);
+      stylePanel.selectNode(aNode);
     } else {
       aJSTerm.writeOutput(errstr + "\n", CATEGORY_OUTPUT, SEVERITY_ERROR);
     }
   };
 
   /**
    * Prints aObject to the output.
    *
--- a/browser/locales/en-US/chrome/browser/styleinspector.dtd
+++ b/browser/locales/en-US/chrome/browser/styleinspector.dtd
@@ -1,8 +1,13 @@
+<!-- LOCALIZATION NOTE (userStylesLabel): This is the label for the checkbox
+  -  that specifies whether the styles that are not from the user's stylesheet
+  -  should be displayed or not. -->
+<!ENTITY userStylesLabel    "Only user styles">
+
 <!-- LOCALIZATION NOTE (lookingAtLabel): This is the label for the path of
   -  the highlighted element in the web page. This path is based on the document
   -  tree. -->
 <!ENTITY lookingAtLabel        "Looking at:">
 
 <!-- LOCALIZATION NOTE (helpLinkTitle): For each style property
   -  the user can hover it and get a help link button which allows one to
   -  quickly jump to the documentation from the Mozilla Developer Network site.
--- a/browser/locales/en-US/chrome/browser/styleinspector.properties
+++ b/browser/locales/en-US/chrome/browser/styleinspector.properties
@@ -1,18 +1,18 @@
 # LOCALIZATION NOTE These strings are used inside the Style Inspector.
 
 # LOCALIZATION NOTE (panelTitle): This is the panel title
 panelTitle=Style Inspector
 
-# LOCALIZATION NOTE (property.numberOfSelectors): For each style property the
+# LOCALIZATION NOTE (property.numberOfMatchedSelectors): For each style property the
 # panel shows the number of selectors which match the currently selected
 # element, counted from all stylesheets in the web page inspected.
 # See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
-property.numberOfSelectors=1 selector;#1 selectors
+property.numberOfMatchedSelectors=1 matched selector;#1 matched selectors
 
 # LOCALIZATION NOTE (property.numberOfUnmatchedSelectors): For each style
 # property the panel shows the number of selectors which do not match the
 # currently selected element, counted from all stylesheets in the web page
 # inspected.
 # See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
 property.numberOfUnmatchedSelectors=1 unmatched selector;#1 unmatched selectors
 
@@ -27,23 +27,16 @@ rule.status.UNMATCHED=Unmatched
 
 # LOCALIZATION NOTE (rule.sourceElement, rule.sourceInline): For each
 # style property the panel shows the rules which hold that specific property.
 # For every rule, the rule source is also displayed: a rule can come from a
 # file, from the same page (inline), or from the element itself (element).
 rule.sourceInline=inline
 rule.sourceElement=element
 
-# LOCALIZATION NOTE (rule.showUnmatchedLink): For each style
-# property the panel shows the number of selectors which do not match the
-# currently selected element, counted from all stylesheets in the web page
-# inspected.
-# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
-rule.showUnmatchedLink=1 unmatched selector…;#1 unmatched selectors…
-
 # LOCALIZATION NOTE (group): Style properties are displayed in categories and
 # these are the category names.
 group.Text_Fonts_and_Color=Text, Fonts & Color
 group.Background=Background
 group.Dimensions=Dimensions
 group.Positioning_and_Page_Flow=Positioning and Page Flow
 group.Borders=Borders
 group.Lists=Lists
--- a/browser/themes/gnomestripe/browser/devtools/csshtmltree.css
+++ b/browser/themes/gnomestripe/browser/devtools/csshtmltree.css
@@ -37,17 +37,18 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 body {
   font-family: sans-serif;
   font-size: 11px;
   background: #EEE;
 }
-.path {
+.path,
+.filters {
   font-size: 11px;
   word-spacing: -1px;
 }
 .path ol {
   list-style: none outside none;
   margin: 0;
   padding: 0;
 }
@@ -66,117 +67,95 @@ body {
 .path li:last-child {
   background: -moz-linear-gradient(top, #FFC, #DD8);
 }
 .path li:last-child:after {
   color: red;
   content: "";
 }
 
-#header,
-#footer {
-  padding: 5px;
-}
-
-#header label {
-  font-weight: bold;
-}
-
 .property-header {
   padding: 2px 5px;
   background: -moz-linear-gradient(top, #F8F8F8, #E8E8E8);
   color: #666;
 }
 
 .property-name,
-.property-value,
-.rule-count,
+.rule-matched,
 .rule-unmatched {
   cursor: pointer;
 }
 
 /* Take away these two :visited rules to get a core dumper     */
 /* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
-.link,
-.unmatchedlink {
+.link {
   color: #55A;
 }
-.link:visited,
-.unmatchedlink:visited {
+.link:visited {
   color: #55A;
 }
-a.link,
-a.unmatchedlink {
+a.link {
   text-decoration: none;
   cursor: pointer;
 }
-a.link:visited,
-a.unmatchedlink:visited {
+a.link:visited {
   text-decoration: none;
 }
 
-.rule-count,
+.rule-matched,
 .rule-unmatched {
-  padding: 5px 0 0 15px;
+  padding: 2px 0;
+  white-space: nowrap;
 }
-.unmatched {
-  display: inline-block;
+
+.rulelink {
+  color: #55A;
 }
+
 .expander {
   width: 8px;
   height: 8px;
-  display: inline-block;
+  float: left;
+  -moz-margin-start: 15px;
   -moz-margin-end: 5px;
-  margin-bottom: 1px;
+  margin-top: 3px;
   background: url("chrome://browser/skin/devtools/arrows.png");
-}
-
-.unmatched-rule {
-  -moz-margin-start: 25px;
   background-position: 24px 0;
 }
 
-.property-view .rule-count .expander,
-.property-view .rule-unmatched .expander {
-  background-position: 24px 0;
+.searchfield {
+  background: url("chrome://browser/skin/devtools/search.png") no-repeat #FFF;
+  border-radius: 5px;
+  -moz-padding-start: 20px;
+  width: 135px;
+  float: right;
 }
-.property-view[dir="rtl"] .rule-count .expander,
-.property-view[dir="rtl"] .rule-unmatched .expander {
+
+.expander[dir="rtl"] {
   background-position: 16px 0;
 }
-.property-view[open] .rule-count .expander,
-.property-view[open] .rule-unmatched .expander {
+.expander[open] {
   background-position: 8px 0;
 }
 
 .property-name {
   display: inline-block;
   font-size: 12px;
   font-weight: bold;
   color: #000;
 }
 .property-value {
   display: inline-block;
   font-size: 10px;
 }
 
-.property-view > .rules {
+.property-view-hidden {
   display: none;
 }
-.property-view[open] > .rules {
-  display: table;
-}
-.rules {
-  -moz-margin-start: 32px;
-  max-height: 350px;
-  overflow-y: auto;
-}
-.rule-status {
-  white-space: nowrap;
-}
+
 .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;
@@ -194,8 +173,18 @@ a.unmatchedlink:visited {
   text-decoration: line-through;
 }
 .parentmatch {
   color: #666;
 }
 .unmatched {
   color: brown;
 }
+
+.userStyles {
+  position: relative;
+  top: 3px;
+}
+
+.userStyles,
+.userStylesLabel {
+  cursor: pointer;
+}
\ No newline at end of file
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..df7212d78c8f86e7abe5073d85bf419786993550
GIT binary patch
literal 1445
zc%17D@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE;=WQl7;NpOBzNqJ&XDuZK6ep0G}
zXKrG8YEWuoN@d~6R2v2cW~I!Kh>{3jAFJg2T)jk)8oi3#0tOJUv9BmdOwLX%QAkQn
z&&;z`dcS+Wl0s&Rtx~wDuYqrYb81GWM^#a3aFt(3a#eP+Wr~u$oq|n;70`g()RIJn
zirk#MVyg;UC9t_xKsHENUr7P1q$Jx`3F4>--v9;Y{GwC^Q#}LSWCJq;1v5iELt_(j
zb8{U9BLhPNeFGzXLnB>7b1P#bD+2=sC{P00R+N%v73AUuwF}6zRmvzSDX`MlFE20G
zD>v55FG|-pw6wGYnPFt43sj+7T$xvrSfQI&tPC^3CAB!YD6^m>Ge1uO#7|7hFD<cE
zQi6FQw*YQzUNJP7fB~jokyxN_sAr&$q|nzFztY@Xxa#7Ppwu+{s*6J^3sUuiQj7CT
zi;{s6m!=HTTwvu~l$uzQUlfv`p92fUfQ<Z-{NjxK0tM$_Qw86|<jgz}AFSTj*UB@m
zxFj(zIn~p}RtYGgmzkMj<?8HW<YHiH=45K*WN7H(W@%|*=4@<YVCL%N=458z2-EA5
zpIn-onpXnTn}X15j#DovDL{0m7G;*DrnnX5=PH1`Y?X=IEhf0#0@0g-+byOz_38s1
zqmLHRFd<;-0Wsmp7RZ4o{M0;PYA*sN>rTV&CkzZslAbP(Ar-gIOxf=(ohWhqzW0|&
z%5$EucNmJziJ9UcY}`?-!m3zuX2F9?x{8aG4(>moX>nv>w|9Gzh2oBmj%RINv%&-y
zpVk#z=i6j)gwJ;IvDe>Qzh`+QC3QFR*HpyK+x@)y{pUUBtLLnH{Y3SwOWchrE88a)
zc|v(2D?~zyzr{BRL^aK3Wm<7rz(Bc<b3enw!|LW2?>MWhJ-C;7dz-+8nFfjSk&gGC
zud{8r!LAmz`Sx4$iy0w$V%@KA=9DSR@Xg=wy?(aOGSNN1m%SBx$;Z1U?6rA|pRU;H
zm5VfrJ9-)9Iu6Kp9}TMTYdz26=wbRy%0`bvl9@}xMQLKc&kD=LBX7&zKc2gO#e)TN
zAKaf*Yj<DZ_2hG(_nfJ^k<)ekwQc+LRaaN7eyrKO=mz(9ht^L&_k6gbDaOUB{dV!;
zhYEMAEIRI8{8!U>zx93gOMb=23DO>o4iAElPfA>xVBo>}dTUhg1C?NllMaVjd}g10
zR;g3pwA)2#<JUQsU#e~9T@6~f<f5JFnTN6~nz9S{*%GXu7FBM(9cwo!wNhDxD>m`0
zaijbLrazl*=Im|w7QQ+}%lO9E-|Ng<Ie!-KyyK!a`DJ+M)uvCcXEeR8uvw?{>_Eic
zt0ui_d`-z2I@@L6sJWQks5@rRy<5dI>Og|G$MV`ge)S5v&42rMTzdIs(dCzS4lg);
zGUd{bh})CqXP0bPeuMRfnI6;kSO0I+vq&&pJYHef^w)U`sNnQ;^>bP0l+XkKR`nx-
--- a/browser/themes/gnomestripe/browser/jar.mn
+++ b/browser/themes/gnomestripe/browser/jar.mn
@@ -80,16 +80,17 @@ browser.jar:
   skin/classic/browser/tabbrowser/tab-overflow-border.png (tabbrowser/tab-overflow-border.png)
   skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png)
   skin/classic/browser/tabview/edit-light.png         (tabview/edit-light.png)
   skin/classic/browser/tabview/search.png             (tabview/search.png)  
   skin/classic/browser/tabview/stack-expander.png     (tabview/stack-expander.png)
   skin/classic/browser/tabview/tabview.png            (tabview/tabview.png)
   skin/classic/browser/tabview/tabview.css            (tabview/tabview.css)
   skin/classic/browser/devtools/arrows.png            (devtools/arrows.png)
+  skin/classic/browser/devtools/search.png            (devtools/search.png)
   skin/classic/browser/devtools/csshtmltree.css       (devtools/csshtmltree.css)
 #ifdef MOZ_SERVICES_SYNC
   skin/classic/browser/sync-16-throbber.png
   skin/classic/browser/sync-16.png
   skin/classic/browser/sync-24-throbber.png
   skin/classic/browser/sync-32.png
   skin/classic/browser/sync-bg.png
   skin/classic/browser/sync-desktopIcon.png
--- a/browser/themes/pinstripe/browser/devtools/csshtmltree.css
+++ b/browser/themes/pinstripe/browser/devtools/csshtmltree.css
@@ -37,17 +37,18 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 body {
   font-family: sans-serif;
   font-size: 11px;
   background: #EEE;
 }
-.path {
+.path,
+.filters {
   font-size: 11px;
   word-spacing: -1px;
 }
 .path ol {
   list-style: none outside none;
   margin: 0;
   padding: 0;
 }
@@ -66,117 +67,95 @@ body {
 .path li:last-child {
   background: -moz-linear-gradient(top, #FFC, #DD8);
 }
 .path li:last-child:after {
   color: red;
   content: "";
 }
 
-#header,
-#footer {
-  padding: 5px;
-}
-
-#header label {
-  font-weight: bold;
-}
-
 .property-header {
   padding: 2px 5px;
   background: -moz-linear-gradient(top, #F8F8F8, #E8E8E8);
   color: #666;
 }
 
 .property-name,
-.property-value,
-.rule-count,
+.rule-matched,
 .rule-unmatched {
   cursor: pointer;
 }
 
 /* Take away these two :visited rules to get a core dumper     */
 /* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
-.link,
-.unmatchedlink {
+.link {
   color: #55A;
 }
-.link:visited,
-.unmatchedlink:visited {
+.link:visited {
   color: #55A;
 }
-a.link,
-a.unmatchedlink {
+a.link {
   text-decoration: none;
   cursor: pointer;
 }
-a.link:visited,
-a.unmatchedlink:visited {
+a.link:visited {
   text-decoration: none;
 }
 
-.rule-count,
+.rule-matched,
 .rule-unmatched {
-  padding: 5px 0 0 15px;
+  padding: 2px 0;
+  white-space: nowrap;
 }
-.unmatched {
-  display: inline-block;
+
+.rulelink {
+  color: #55A;
 }
+
 .expander {
   width: 8px;
   height: 8px;
-  display: inline-block;
+  float: left;
+  -moz-margin-start: 15px;
   -moz-margin-end: 5px;
-  margin-bottom: 1px;
+  margin-top: 3px;
   background: url("chrome://browser/skin/devtools/arrows.png");
-}
-
-.unmatched-rule {
-  -moz-margin-start: 25px;
   background-position: 24px 0;
 }
 
-.property-view .rule-count .expander,
-.property-view .rule-unmatched .expander {
-  background-position: 24px 0;
+.searchfield {
+  background: url("chrome://browser/skin/devtools/search.png") no-repeat #FFF;
+  border-radius: 5px;
+  -moz-padding-start: 20px;
+  width: 135px;
+  float: right;
 }
-.property-view[dir="rtl"] .rule-count .expander,
-.property-view[dir="rtl"] .rule-unmatched .expander {
+
+.expander[dir="rtl"] {
   background-position: 16px 0;
 }
-.property-view[open] .rule-count .expander,
-.property-view[open] .rule-unmatched .expander {
+.expander[open] {
   background-position: 8px 0;
 }
 
 .property-name {
   display: inline-block;
   font-size: 12px;
   font-weight: bold;
   color: #000;
 }
 .property-value {
   display: inline-block;
   font-size: 10px;
 }
 
-.property-view > .rules {
+.property-view-hidden {
   display: none;
 }
-.property-view[open] > .rules {
-  display: table;
-}
-.rules {
-  -moz-margin-start: 32px;
-  max-height: 350px;
-  overflow-y: auto;
-}
-.rule-status {
-  white-space: nowrap;
-}
+
 .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;
@@ -194,8 +173,18 @@ a.unmatchedlink:visited {
   text-decoration: line-through;
 }
 .parentmatch {
   color: #666;
 }
 .unmatched {
   color: brown;
 }
+
+.userStyles {
+  position: relative;
+  top: 3px;
+}
+
+.userStyles,
+.userStylesLabel {
+  cursor: pointer;
+}
\ No newline at end of file
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..df7212d78c8f86e7abe5073d85bf419786993550
GIT binary patch
literal 1445
zc%17D@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE;=WQl7;NpOBzNqJ&XDuZK6ep0G}
zXKrG8YEWuoN@d~6R2v2cW~I!Kh>{3jAFJg2T)jk)8oi3#0tOJUv9BmdOwLX%QAkQn
z&&;z`dcS+Wl0s&Rtx~wDuYqrYb81GWM^#a3aFt(3a#eP+Wr~u$oq|n;70`g()RIJn
zirk#MVyg;UC9t_xKsHENUr7P1q$Jx`3F4>--v9;Y{GwC^Q#}LSWCJq;1v5iELt_(j
zb8{U9BLhPNeFGzXLnB>7b1P#bD+2=sC{P00R+N%v73AUuwF}6zRmvzSDX`MlFE20G
zD>v55FG|-pw6wGYnPFt43sj+7T$xvrSfQI&tPC^3CAB!YD6^m>Ge1uO#7|7hFD<cE
zQi6FQw*YQzUNJP7fB~jokyxN_sAr&$q|nzFztY@Xxa#7Ppwu+{s*6J^3sUuiQj7CT
zi;{s6m!=HTTwvu~l$uzQUlfv`p92fUfQ<Z-{NjxK0tM$_Qw86|<jgz}AFSTj*UB@m
zxFj(zIn~p}RtYGgmzkMj<?8HW<YHiH=45K*WN7H(W@%|*=4@<YVCL%N=458z2-EA5
zpIn-onpXnTn}X15j#DovDL{0m7G;*DrnnX5=PH1`Y?X=IEhf0#0@0g-+byOz_38s1
zqmLHRFd<;-0Wsmp7RZ4o{M0;PYA*sN>rTV&CkzZslAbP(Ar-gIOxf=(ohWhqzW0|&
z%5$EucNmJziJ9UcY}`?-!m3zuX2F9?x{8aG4(>moX>nv>w|9Gzh2oBmj%RINv%&-y
zpVk#z=i6j)gwJ;IvDe>Qzh`+QC3QFR*HpyK+x@)y{pUUBtLLnH{Y3SwOWchrE88a)
zc|v(2D?~zyzr{BRL^aK3Wm<7rz(Bc<b3enw!|LW2?>MWhJ-C;7dz-+8nFfjSk&gGC
zud{8r!LAmz`Sx4$iy0w$V%@KA=9DSR@Xg=wy?(aOGSNN1m%SBx$;Z1U?6rA|pRU;H
zm5VfrJ9-)9Iu6Kp9}TMTYdz26=wbRy%0`bvl9@}xMQLKc&kD=LBX7&zKc2gO#e)TN
zAKaf*Yj<DZ_2hG(_nfJ^k<)ekwQc+LRaaN7eyrKO=mz(9ht^L&_k6gbDaOUB{dV!;
zhYEMAEIRI8{8!U>zx93gOMb=23DO>o4iAElPfA>xVBo>}dTUhg1C?NllMaVjd}g10
zR;g3pwA)2#<JUQsU#e~9T@6~f<f5JFnTN6~nz9S{*%GXu7FBM(9cwo!wNhDxD>m`0
zaijbLrazl*=Im|w7QQ+}%lO9E-|Ng<Ie!-KyyK!a`DJ+M)uvCcXEeR8uvw?{>_Eic
zt0ui_d`-z2I@@L6sJWQks5@rRy<5dI>Og|G$MV`ge)S5v&42rMTzdIs(dCzS4lg);
zGUd{bh})CqXP0bPeuMRfnI6;kSO0I+vq&&pJYHef^w)U`sNnQ;^>bP0l+XkKR`nx-
--- a/browser/themes/pinstripe/browser/jar.mn
+++ b/browser/themes/pinstripe/browser/jar.mn
@@ -119,16 +119,17 @@ browser.jar:
   skin/classic/browser/tabbrowser/tabDragIndicator.png                   (tabbrowser/tabDragIndicator.png)
   skin/classic/browser/tabview/close.png                    (tabview/close.png)
   skin/classic/browser/tabview/edit-light.png               (tabview/edit-light.png)
   skin/classic/browser/tabview/search.png                   (tabview/search.png)
   skin/classic/browser/tabview/stack-expander.png           (tabview/stack-expander.png)
   skin/classic/browser/tabview/tabview.png                  (tabview/tabview.png)
   skin/classic/browser/tabview/tabview.css                  (tabview/tabview.css)
   skin/classic/browser/devtools/arrows.png                  (devtools/arrows.png)
+  skin/classic/browser/devtools/search.png                  (devtools/search.png)
   skin/classic/browser/devtools/csshtmltree.css             (devtools/csshtmltree.css)
 #ifdef MOZ_SERVICES_SYNC
   skin/classic/browser/sync-throbber.png
   skin/classic/browser/sync-16.png
   skin/classic/browser/sync-32.png
   skin/classic/browser/sync-bg.png
   skin/classic/browser/sync-desktopIcon.png
   skin/classic/browser/sync-mobileIcon.png
--- a/browser/themes/winstripe/browser/devtools/csshtmltree.css
+++ b/browser/themes/winstripe/browser/devtools/csshtmltree.css
@@ -37,17 +37,18 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 body {
   font-family: sans-serif;
   font-size: 11px;
   background: #EEE;
 }
-.path {
+.path,
+.filters {
   font-size: 11px;
   word-spacing: -1px;
 }
 .path ol {
   list-style: none outside none;
   margin: 0;
   padding: 0;
 }
@@ -66,117 +67,95 @@ body {
 .path li:last-child {
   background: -moz-linear-gradient(top, #FFC, #DD8);
 }
 .path li:last-child:after {
   color: red;
   content: "";
 }
 
-#header,
-#footer {
-  padding: 5px;
-}
-
-#header label {
-  font-weight: bold;
-}
-
 .property-header {
   padding: 2px 5px;
   background: -moz-linear-gradient(top, #F8F8F8, #E8E8E8);
   color: #666;
 }
 
 .property-name,
-.property-value,
-.rule-count,
+.rule-matched,
 .rule-unmatched {
   cursor: pointer;
 }
 
 /* Take away these two :visited rules to get a core dumper     */
 /* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
-.link,
-.unmatchedlink {
+.link {
   color: #55A;
 }
-.link:visited,
-.unmatchedlink:visited {
+.link:visited {
   color: #55A;
 }
-a.link,
-a.unmatchedlink {
+a.link {
   text-decoration: none;
   cursor: pointer;
 }
-a.link:visited,
-a.unmatchedlink:visited {
+a.link:visited {
   text-decoration: none;
 }
 
-.rule-count,
+.rule-matched,
 .rule-unmatched {
-  padding: 5px 0 0 15px;
+  padding: 2px 0;
+  white-space: nowrap;
 }
-.unmatched {
-  display: inline-block;
+
+.rulelink {
+  color: #55A;
 }
+
 .expander {
   width: 8px;
   height: 8px;
-  display: inline-block;
+  float: left;
+  -moz-margin-start: 15px;
   -moz-margin-end: 5px;
-  margin-bottom: 1px;
+  margin-top: 3px;
   background: url("chrome://browser/skin/devtools/arrows.png");
-}
-
-.unmatched-rule {
-  -moz-margin-start: 25px;
   background-position: 24px 0;
 }
 
-.property-view .rule-count .expander,
-.property-view .rule-unmatched .expander {
-  background-position: 24px 0;
+.searchfield {
+  background: url("chrome://browser/skin/devtools/search.png") no-repeat #FFF;
+  border-radius: 5px;
+  -moz-padding-start: 20px;
+  width: 135px;
+  float: right;
 }
-.property-view[dir="rtl"] .rule-count .expander,
-.property-view[dir="rtl"] .rule-unmatched .expander {
+
+.expander[dir="rtl"] {
   background-position: 16px 0;
 }
-.property-view[open] .rule-count .expander,
-.property-view[open] .rule-unmatched .expander {
+.expander[open] {
   background-position: 8px 0;
 }
 
 .property-name {
   display: inline-block;
   font-size: 12px;
   font-weight: bold;
   color: #000;
 }
 .property-value {
   display: inline-block;
   font-size: 10px;
 }
 
-.property-view > .rules {
+.property-view-hidden {
   display: none;
 }
-.property-view[open] > .rules {
-  display: table;
-}
-.rules {
-  -moz-margin-start: 32px;
-  max-height: 350px;
-  overflow-y: auto;
-}
-.rule-status {
-  white-space: nowrap;
-}
+
 .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;
@@ -194,8 +173,18 @@ a.unmatchedlink:visited {
   text-decoration: line-through;
 }
 .parentmatch {
   color: #666;
 }
 .unmatched {
   color: brown;
 }
+
+.userStyles {
+  position: relative;
+  top: 3px;
+}
+
+.userStyles,
+.userStylesLabel {
+  cursor: pointer;
+}
\ No newline at end of file
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..df7212d78c8f86e7abe5073d85bf419786993550
GIT binary patch
literal 1445
zc%17D@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE;=WQl7;NpOBzNqJ&XDuZK6ep0G}
zXKrG8YEWuoN@d~6R2v2cW~I!Kh>{3jAFJg2T)jk)8oi3#0tOJUv9BmdOwLX%QAkQn
z&&;z`dcS+Wl0s&Rtx~wDuYqrYb81GWM^#a3aFt(3a#eP+Wr~u$oq|n;70`g()RIJn
zirk#MVyg;UC9t_xKsHENUr7P1q$Jx`3F4>--v9;Y{GwC^Q#}LSWCJq;1v5iELt_(j
zb8{U9BLhPNeFGzXLnB>7b1P#bD+2=sC{P00R+N%v73AUuwF}6zRmvzSDX`MlFE20G
zD>v55FG|-pw6wGYnPFt43sj+7T$xvrSfQI&tPC^3CAB!YD6^m>Ge1uO#7|7hFD<cE
zQi6FQw*YQzUNJP7fB~jokyxN_sAr&$q|nzFztY@Xxa#7Ppwu+{s*6J^3sUuiQj7CT
zi;{s6m!=HTTwvu~l$uzQUlfv`p92fUfQ<Z-{NjxK0tM$_Qw86|<jgz}AFSTj*UB@m
zxFj(zIn~p}RtYGgmzkMj<?8HW<YHiH=45K*WN7H(W@%|*=4@<YVCL%N=458z2-EA5
zpIn-onpXnTn}X15j#DovDL{0m7G;*DrnnX5=PH1`Y?X=IEhf0#0@0g-+byOz_38s1
zqmLHRFd<;-0Wsmp7RZ4o{M0;PYA*sN>rTV&CkzZslAbP(Ar-gIOxf=(ohWhqzW0|&
z%5$EucNmJziJ9UcY}`?-!m3zuX2F9?x{8aG4(>moX>nv>w|9Gzh2oBmj%RINv%&-y
zpVk#z=i6j)gwJ;IvDe>Qzh`+QC3QFR*HpyK+x@)y{pUUBtLLnH{Y3SwOWchrE88a)
zc|v(2D?~zyzr{BRL^aK3Wm<7rz(Bc<b3enw!|LW2?>MWhJ-C;7dz-+8nFfjSk&gGC
zud{8r!LAmz`Sx4$iy0w$V%@KA=9DSR@Xg=wy?(aOGSNN1m%SBx$;Z1U?6rA|pRU;H
zm5VfrJ9-)9Iu6Kp9}TMTYdz26=wbRy%0`bvl9@}xMQLKc&kD=LBX7&zKc2gO#e)TN
zAKaf*Yj<DZ_2hG(_nfJ^k<)ekwQc+LRaaN7eyrKO=mz(9ht^L&_k6gbDaOUB{dV!;
zhYEMAEIRI8{8!U>zx93gOMb=23DO>o4iAElPfA>xVBo>}dTUhg1C?NllMaVjd}g10
zR;g3pwA)2#<JUQsU#e~9T@6~f<f5JFnTN6~nz9S{*%GXu7FBM(9cwo!wNhDxD>m`0
zaijbLrazl*=Im|w7QQ+}%lO9E-|Ng<Ie!-KyyK!a`DJ+M)uvCcXEeR8uvw?{>_Eic
zt0ui_d`-z2I@@L6sJWQks5@rRy<5dI>Og|G$MV`ge)S5v&42rMTzdIs(dCzS4lg);
zGUd{bh})CqXP0bPeuMRfnI6;kSO0I+vq&&pJYHef^w)U`sNnQ;^>bP0l+XkKR`nx-
--- a/browser/themes/winstripe/browser/jar.mn
+++ b/browser/themes/winstripe/browser/jar.mn
@@ -102,16 +102,17 @@ browser.jar:
         skin/classic/browser/tabview/edit-light.png                 (tabview/edit-light.png)
         skin/classic/browser/tabview/grain.png                      (tabview/grain.png)
         skin/classic/browser/tabview/search.png                     (tabview/search.png)
         skin/classic/browser/tabview/stack-expander.png             (tabview/stack-expander.png)
         skin/classic/browser/tabview/tabview.png                    (tabview/tabview.png)
         skin/classic/browser/tabview/tabview-inverted.png           (tabview/tabview-inverted.png)
         skin/classic/browser/tabview/tabview.css                    (tabview/tabview.css)
         skin/classic/browser/devtools/arrows.png                    (devtools/arrows.png)
+        skin/classic/browser/devtools/search.png                    (devtools/search.png)
         skin/classic/browser/devtools/csshtmltree.css               (devtools/csshtmltree.css)
 #ifdef MOZ_SERVICES_SYNC
         skin/classic/browser/sync-throbber.png
         skin/classic/browser/sync-16.png
         skin/classic/browser/sync-32.png
         skin/classic/browser/sync-bg.png
         skin/classic/browser/sync-desktopIcon.png
         skin/classic/browser/sync-mobileIcon.png
@@ -223,16 +224,19 @@ browser.jar:
         skin/classic/aero/browser/tabview/close.png                  (tabview/close.png)
         skin/classic/aero/browser/tabview/edit-light.png             (tabview/edit-light.png)
         skin/classic/aero/browser/tabview/grain.png                  (tabview/grain.png)
         skin/classic/aero/browser/tabview/search.png                 (tabview/search.png)
         skin/classic/aero/browser/tabview/stack-expander.png         (tabview/stack-expander.png)
         skin/classic/aero/browser/tabview/tabview.png                (tabview/tabview.png)
         skin/classic/aero/browser/tabview/tabview-inverted.png       (tabview/tabview-inverted.png)
         skin/classic/aero/browser/tabview/tabview.css                (tabview/tabview.css)
+        skin/classic/aero/browser/devtools/arrows.png                (devtools/arrows.png)
+        skin/classic/aero/browser/devtools/search.png                (devtools/search.png)
+        skin/classic/aero/browser/devtools/csshtmltree.css           (devtools/csshtmltree.css)
 #ifdef MOZ_SERVICES_SYNC
         skin/classic/aero/browser/sync-throbber.png
         skin/classic/aero/browser/sync-16.png
         skin/classic/aero/browser/sync-32.png
         skin/classic/aero/browser/sync-bg.png
         skin/classic/aero/browser/sync-desktopIcon.png
         skin/classic/aero/browser/sync-mobileIcon.png
         skin/classic/aero/browser/sync-notification-24.png
--- a/content/html/document/src/VideoDocument.cpp
+++ b/content/html/document/src/VideoDocument.cpp
@@ -128,16 +128,35 @@ VideoDocument::CreateSyntheticVideoDocum
   UpdateTitle(aChannel);
 
   if (nsContentUtils::IsChildOfSameType(this)) {
     // Video documents that aren't toplevel should fill their frames and
     // not have margins
     element->SetAttr(kNameSpaceID_None, nsGkAtoms::style,
         NS_LITERAL_STRING("position:absolute; top:0; left:0; width:100%; height:100%"),
         PR_TRUE);
+  } else {
+    Element* head = GetHeadElement();
+    if (!head) {
+      NS_WARNING("no head on video document!");
+      return NS_ERROR_FAILURE;
+    }
+
+    nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::style, nsnull,
+                                             kNameSpaceID_XHTML,
+                                             nsIDOMNode::ELEMENT_NODE);
+    NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
+    nsRefPtr<nsGenericHTMLElement> styleContent = NS_NewHTMLStyleElement(nodeInfo.forget());
+    NS_ENSURE_TRUE(styleContent, NS_ERROR_OUT_OF_MEMORY);
+
+    styleContent->SetTextContent(
+      NS_LITERAL_STRING("body { background: url(chrome://global/skin/icons/tabprompts-bgtexture.png) #333; height: 100%; width: 100%; margin: 0; padding: 0; } ") +
+      NS_LITERAL_STRING("video { position: absolute; top: 0; right: 0; bottom: 0; left: 0; margin: auto; box-shadow: 0 0 15px #000; } ") +
+      NS_LITERAL_STRING("video:focus { outline-width: 0; } "));
+    head->AppendChildTo(styleContent, PR_FALSE);
   }
 
   return body->AppendChildTo(element, PR_FALSE);
 }
 
 void
 VideoDocument::UpdateTitle(nsIChannel* aChannel)
 {
--- a/dom/base/ConsoleAPI.js
+++ b/dom/base/ConsoleAPI.js
@@ -1,8 +1,10 @@
+/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
@@ -66,29 +68,29 @@ ConsoleAPI.prototype = {
     catch (ex) {
       Cu.reportError(ex);
     }
 
     let self = this;
     let chromeObject = {
       // window.console API
       log: function CA_log() {
-        self.notifyObservers(outerID, innerID, "log", arguments);
+        self.notifyObservers(outerID, innerID, "log", self.processArguments(arguments));
       },
       info: function CA_info() {
-        self.notifyObservers(outerID, innerID, "info", arguments);
+        self.notifyObservers(outerID, innerID, "info", self.processArguments(arguments));
       },
       warn: function CA_warn() {
-        self.notifyObservers(outerID, innerID, "warn", arguments);
+        self.notifyObservers(outerID, innerID, "warn", self.processArguments(arguments));
       },
       error: function CA_error() {
-        self.notifyObservers(outerID, innerID, "error", arguments);
+        self.notifyObservers(outerID, innerID, "error", self.processArguments(arguments));
       },
       debug: function CA_debug() {
-        self.notifyObservers(outerID, innerID, "log", arguments);
+        self.notifyObservers(outerID, innerID, "log", self.processArguments(arguments));
       },
       trace: function CA_trace() {
         self.notifyObservers(outerID, innerID, "trace", self.getStackTrace());
       },
       // Displays an interactive listing of all the properties of an object.
       dir: function CA_dir() {
         self.notifyObservers(outerID, innerID, "dir", arguments);
       },
@@ -164,16 +166,52 @@ ConsoleAPI.prototype = {
 
     ConsoleAPIStorage.recordEvent(aInnerWindowID, consoleEvent);
 
     Services.obs.notifyObservers(consoleEvent,
                                  "console-api-log-event", aOuterWindowID);
   },
 
   /**
+   * Process the console API call arguments in order to perform printf-like
+   * string substitution.
+   * TODO: object substitution should display an interactive property list (bug
+   * 685815) and width and precision qualifiers should be taken into account
+   * (bug 685813).
+   *
+   * @param mixed aArguments
+   *        The arguments given to the console API call.
+   **/
+  processArguments: function CA_processArguments(aArguments) {
+    if (aArguments.length < 2) {
+      return aArguments;
+    }
+    let args = Array.prototype.slice.call(aArguments);
+    let format = args.shift();
+    // Format specification regular expression.
+    let pattern = /%(\d*).?(\d*)[a-zA-Z]/g;
+    let processed = format.replace(pattern, function CA_PA_substitute(spec) {
+      switch (spec[spec.length-1]) {
+        case "o":
+        case "s":
+          return args.shift().toString();
+        case "d":
+        case "i":
+          return parseInt(args.shift());
+        case "f":
+          return parseFloat(args.shift());
+        default:
+          return spec;
+      };
+    });
+    args.unshift(processed);
+    return args;
+  },
+
+  /**
    * Build the stacktrace array for the console.trace() call.
    *
    * @return array
    *         Each element is a stack frame that holds the following properties:
    *         filename, lineNumber, functionName and language.
    **/
   getStackTrace: function CA_getStackTrace() {
     let stack = [];
--- a/dom/tests/browser/browser_ConsoleAPITests.js
+++ b/dom/tests/browser/browser_ConsoleAPITests.js
@@ -156,18 +156,31 @@ function expect(level) {
 function observeConsoleTest() {
   let win = XPCNativeWrapper.unwrap(gWindow);
   expect("log", "arg");
   win.console.log("arg");
 
   expect("info", "arg", "extra arg");
   win.console.info("arg", "extra arg");
 
-  expect("warn", "arg", "extra arg", 1);
-  win.console.warn("arg", "extra arg", 1);
+  // We don't currently support width and precision qualifiers, but we don't
+  // choke on them either.
+  expect("warn", "Lesson 1: PI is approximately equal to 3.14159");
+  win.console.warn("Lesson %d: %s is approximately equal to %1.2f",
+                   1,
+                   "PI",
+                   3.14159);
+  expect("log", "%d, %s, %l");
+  win.console.log("%d, %s, %l");
+  expect("log", "%a %b %c");
+  win.console.log("%a %b %c");
+  expect("log", "%a %b %c", "a", "b");
+  win.console.log("%a %b %c", "a", "b");
+  expect("log", "2, a, %l", 3);
+  win.console.log("%d, %s, %l", 2, "a", 3);
 
   expect("dir", win.toString());
   win.console.dir(win);
 
   expect("error", "arg");
   win.console.error("arg");
 }
 
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -1229,17 +1229,18 @@ class GetPropCompiler : public PICStubCo
 
         NativeStubLinker::FinalJump done;
         if (!NativeStubEpilogue(f, masm, &done, 0, vpOffset, pic.shapeReg, pic.objReg))
             return;
         NativeStubLinker linker(masm, f.jit(), f.regs.pc, done);
         if (!linker.init(f.cx))
             THROW();
 
-        if (!linker.verifyRange(f.jit())) {
+        if (!linker.verifyRange(pic.lastCodeBlock(f.jit())) ||
+            !linker.verifyRange(f.jit())) {
             disable("code memory is out of range");
             return;
         }
 
         linker.patchJump(pic.fastPathRejoin);
 
         linkerEpilogue(linker, start, shapeMismatches);
     }