Bug 697983 - Implement a Font Inspector. r=jwalker
authorPaul Rouget <paul@mozilla.com>
Thu, 07 Mar 2013 05:57:00 +0100
changeset 124187 2d7845ad3cd81a122d39faaabd12d827ab411f79
parent 124186 1156d4f8ec2c037f4299fdf9427d50f80db1cc92
child 124188 af5f267cd6a1a1745b9d4393208b87e6d5892fda
push id24409
push userjwalker@mozilla.com
push dateFri, 08 Mar 2013 16:48:44 +0000
treeherdermozilla-central@af5f267cd6a1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwalker
bugs697983
milestone22.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
Bug 697983 - Implement a Font Inspector. r=jwalker
browser/app/profile/firefox.js
browser/devtools/fontinspector/Makefile.in
browser/devtools/fontinspector/font-inspector.css
browser/devtools/fontinspector/font-inspector.js
browser/devtools/fontinspector/font-inspector.xhtml
browser/devtools/fontinspector/moz.build
browser/devtools/fontinspector/test/Makefile.in
browser/devtools/fontinspector/test/browser_font.woff
browser/devtools/fontinspector/test/browser_fontinspector.html
browser/devtools/fontinspector/test/browser_fontinspector.js
browser/devtools/fontinspector/test/moz.build
browser/devtools/inspector/InspectorPanel.jsm
browser/devtools/jar.mn
browser/devtools/layoutview/view.js
browser/devtools/moz.build
browser/locales/en-US/chrome/browser/devtools/font-inspector.dtd
browser/locales/jar.mn
browser/themes/linux/devtools/font-inspector.css
browser/themes/linux/jar.mn
browser/themes/osx/devtools/font-inspector.css
browser/themes/osx/jar.mn
browser/themes/windows/devtools/font-inspector.css
browser/themes/windows/jar.mn
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1141,16 +1141,19 @@ pref("devtools.editor.expandtab", true);
 // Tells which component you want to use for source editing in developer tools.
 //
 // Available components:
 //   "orion" - this is the Orion source code editor from the Eclipse project. It
 //   provides programmer-specific editor features such as syntax highlighting,
 //   indenting and bracket recognition.
 pref("devtools.editor.component", "orion");
 
+// Enable the Font Inspector
+pref("devtools.fontinspector.enabled", true);
+
 // Whether the character encoding menu is under the main Firefox button. This
 // preference is a string so that localizers can alter it.
 pref("browser.menu.showCharacterEncoding", "chrome://browser/locale/browser.properties");
 
 // Allow using tab-modal prompts when possible.
 pref("prompts.tab_modal.enabled", true);
 // Whether the Panorama should animate going in/out of tabs
 pref("browser.panorama.animate_zoom", true);
new file mode 100644
--- /dev/null
+++ b/browser/devtools/fontinspector/Makefile.in
@@ -0,0 +1,13 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DEPTH		= @DEPTH@
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/browser/devtools/fontinspector/font-inspector.css
@@ -0,0 +1,16 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+.dim > #root,
+.font:not(.has-code) .font-css-code,
+.font-is-local,
+.font-is-remote,
+.font.is-local .font-format-url {
+  display: none;
+}
+
+.font.is-remote .font-is-remote,
+.font.is-local .font-is-local {
+  display: inline;
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/fontinspector/font-inspector.js
@@ -0,0 +1,226 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
+const DOMUtils = Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
+
+function FontInspector(inspector, window)
+{
+  this.inspector = inspector;
+  this.chromeDoc = window.document;
+  this.init();
+}
+
+FontInspector.prototype = {
+  init: function FI_init() {
+    this.update = this.update.bind(this);
+    this.onNewNode = this.onNewNode.bind(this);
+    this.onHighlighterLocked = this.onHighlighterLocked.bind(this);
+    this.inspector.selection.on("new-node", this.onNewNode);
+    this.inspector.sidebar.on("fontinspector-selected", this.onNewNode);
+    if (this.inspector.highlighter) {
+      this.inspector.highlighter.on("locked", this.onHighlighterLocked);
+    }
+    this.update();
+  },
+
+  /**
+   * Is the fontinspector visible in the sidebar?
+   */
+  isActive: function FI_isActive() {
+    return this.inspector.sidebar &&
+           this.inspector.sidebar.getCurrentTabID() == "fontinspector";
+  },
+
+  /**
+   * Remove listeners.
+   */
+  destroy: function FI_destroy() {
+    this.chromeDoc = null;
+    this.inspector.sidebar.off("layoutview-selected", this.onNewNode);
+    this.inspector.selection.off("new-node", this.onNewNode);
+    if (this.inspector.highlighter) {
+      this.inspector.highlighter.off("locked", this.onHighlighterLocked);
+    }
+  },
+
+  /**
+   * Selection 'new-node' event handler.
+   */
+  onNewNode: function FI_onNewNode() {
+    if (this.isActive() &&
+        this.inspector.selection.isConnected() &&
+        this.inspector.selection.isElementNode() &&
+        this.inspector.selection.reason != "highlighter") {
+      this.undim();
+      this.update();
+    } else {
+      this.dim();
+    }
+  },
+
+  /**
+   * Highlighter 'locked' event handler
+   */
+  onHighlighterLocked: function FI_onHighlighterLocked() {
+    this.undim();
+    this.update();
+  },
+
+  /**
+   * Hide the font list. No node are selected.
+   */
+  dim: function FI_dim() {
+    this.chromeDoc.body.classList.add("dim");
+    this.chromeDoc.querySelector("#all-fonts").innerHTML = "";
+  },
+
+  /**
+   * Show the font list. A node is selected.
+   */
+  undim: function FI_undim() {
+    this.chromeDoc.body.classList.remove("dim");
+  },
+
+  /**
+   * Retrieve all the font related info we have for the selected
+   * node and display them.
+   */
+  update: function FI_update() {
+    if (!this.isActive() ||
+        !this.inspector.selection.isConnected() ||
+        !this.inspector.selection.isElementNode() ||
+        this.chromeDoc.body.classList.contains("dim")) {
+      return;
+    }
+
+    let node = this.inspector.selection.node;
+    let contentDocument = node.ownerDocument;
+
+    // We don't get fonts for a node, but for a range
+    let rng = contentDocument.createRange();
+    rng.selectNode(node);
+    let fonts = DOMUtils.getUsedFontFaces(rng);
+    let fontsArray = [];
+    for (let i = 0; i < fonts.length; i++) {
+      fontsArray.push(fonts.item(i));
+    }
+    fontsArray = fontsArray.sort(function(a, b) {
+      return a.srcIndex < b.srcIndex;
+    });
+    this.chromeDoc.querySelector("#all-fonts").innerHTML = "";
+    for (let f of fontsArray) {
+      this.render(f, contentDocument);
+    }
+  },
+
+  /**
+   * Display the information of one font.
+   */
+  render: function FI_render(font, document) {
+    let s = this.chromeDoc.querySelector("#template > section");
+    s = s.cloneNode(true);
+
+    s.querySelector(".font-name").textContent = font.name;
+    s.querySelector(".font-css-name").textContent = font.CSSFamilyName;
+    s.querySelector(".font-format").textContent = font.format;
+
+    if (font.srcIndex == -1) {
+      s.classList.add("is-local");
+    } else {
+      s.classList.add("is-remote");
+    }
+
+    s.querySelector(".font-url").value = font.URI;
+
+    let iframe = s.querySelector(".font-preview");
+    if (font.rule) {
+      // This is the @font-face{…} code.
+      let cssText = font.rule.style.parentRule.cssText;
+
+      s.classList.add("has-code");
+      s.querySelector(".font-css-code").textContent = cssText;
+
+      // We guess the base URL of the stylesheet to make
+      // sure the font will be accessible in the preview.
+      // If the font-face is in an inline <style>, we get
+      // the location of the page.
+      let origin = font.rule.style.parentRule.parentStyleSheet.href;
+      if (!origin) { // Inline stylesheet
+        origin = document.location.href;
+      }
+      // We remove the last part of the URL to get a correct base.
+      let base = origin.replace(/\/[^\/]*$/,"/")
+
+      // From all this information, we build a preview.
+      this.buildPreview(iframe, font.CSSFamilyName, cssText, base);
+    } else {
+      this.buildPreview(iframe, font.CSSFamilyName, "", "");
+    }
+
+    this.chromeDoc.querySelector("#all-fonts").appendChild(s);
+  },
+
+  /**
+   * Show a preview of the font in an iframe.
+   */
+  buildPreview: function FI_buildPreview(iframe, name, cssCode, base) {
+    /* The HTML code of the preview is:
+     *   <!DOCTYPE HTML>
+     *   <head>
+     *    <base href="{base}"></base>
+     *   </head>
+     *   <style>
+     *   p {font-family: {name};}
+     *   * {font-size: 40px;line-height:60px;padding:0 10px;margin:0};
+     *   </style>
+     *   <p contenteditable>Abc</p>
+     */
+    let extraCSS = "* {padding:0;margin:0}";
+    extraCSS += "p {font-family: '" + name + "';}";
+    extraCSS += "p {font-size: 40px;line-height:60px;padding:0 10px;margin:0;}";
+    cssCode += extraCSS;
+    let src = "data:text/html;charset=utf-8,<!DOCTYPE HTML><head><base></base></head><style></style><p contenteditable>Abc</p>";
+    iframe.addEventListener("load", function onload() {
+      iframe.removeEventListener("load", onload, true);
+      let doc = iframe.contentWindow.document;
+      // We could have done that earlier, but we want to avoid any URL-encoding
+      // nightmare.
+      doc.querySelector("base").href = base;
+      doc.querySelector("style").textContent = cssCode;
+    }, true);
+    iframe.src = src;
+  },
+
+  /**
+   * Select the <body> to show all the fonts included in the document.
+   */
+  showAll: function FI_showAll() {
+    if (!this.isActive() ||
+        !this.inspector.selection.isConnected() ||
+        !this.inspector.selection.isElementNode()) {
+      return;
+    }
+    let node = this.inspector.selection.node;
+    let contentDocument = node.ownerDocument;
+    let root = contentDocument.documentElement;
+    if (contentDocument.body) {
+      root = contentDocument.body;
+    }
+    this.inspector.selection.setNode(root, "fontinspector");
+  },
+}
+
+
+window.setPanel = function(panel) {
+  window.fontInspector = new FontInspector(panel, window);
+}
+
+window.onunload = function() {
+  window.fontInspector.destroy();
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/fontinspector/font-inspector.xhtml
@@ -0,0 +1,41 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<!DOCTYPE html [
+<!ENTITY % fontinspectorDTD SYSTEM "chrome://browser/locale/devtools/font-inspector.dtd" >
+ %fontinspectorDTD;
+]>
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>&title;</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+    <link rel="stylesheet" href="font-inspector.css" type="text/css"/>
+    <link rel="stylesheet" href="chrome://browser/skin/devtools/common.css" type="text/css"/>
+    <link rel="stylesheet" href="chrome://browser/skin/devtools/font-inspector.css" type="text/css"/>
+  </head>
+  <body class="devtools-monospace" role="application">
+    <script type="application/javascript;version=1.8" src="font-inspector.js"></script>
+    <div id="root">
+      <ul id="all-fonts"></ul>
+      <button id="showall" onclick="fontInspector.showAll()">&showAllFonts;</button>
+    </div>
+    <div id="template" style="display:none">
+      <section class="font">
+        <iframe sandbox="allow-same-origin" class="font-preview"></iframe>
+        <div class="font-info">
+          <h1 class="font-name"></h1>
+          <span class="font-is-local">&system;</span>
+          <span class="font-is-remote">&remote;</span>
+          <p class="font-format-url">
+            <input readonly="readonly" class="font-url"></input>
+            (<span class="font-format"></span>)
+          </p>
+          <p class="font-css">&usedAs; "<span class="font-css-name"></span>"</p>
+          <pre class="font-css-code"></pre>
+        </div>
+      </section>
+    </div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/browser/devtools/fontinspector/moz.build
@@ -0,0 +1,6 @@
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+TEST_DIRS += ['test']
new file mode 100644
--- /dev/null
+++ b/browser/devtools/fontinspector/test/Makefile.in
@@ -0,0 +1,22 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DEPTH     = @DEPTH@
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir  = @relativesrcdir@
+
+include $(DEPTH)/config/autoconf.mk
+include $(topsrcdir)/config/rules.mk
+
+_BROWSER_FILES = \
+		browser_fontinspector.js \
+		browser_fontinspector.html \
+		browser_font.woff \
+		$(NULL)
+
+
+libs::	$(_BROWSER_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
index 0000000000000000000000000000000000000000..e8440843b48adbc99a20c5e0a1642a36ca7178de
GIT binary patch
literal 4704
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
new file mode 100644
--- /dev/null
+++ b/browser/devtools/fontinspector/test/browser_fontinspector.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+
+<style>
+  @font-face {
+    font-family: bar;
+    src: url(bad/font/name.ttf), url(browser_font.woff) format("woff");
+  }
+  body{
+    font-family:Arial;
+  }
+  div {
+    font-family:Arial;
+    font-family:bar;
+  }
+</style>
+
+<body>
+  BODY
+  <div>DIV</div>
+</body>
new file mode 100644
--- /dev/null
+++ b/browser/devtools/fontinspector/test/browser_fontinspector.js
@@ -0,0 +1,89 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let tempScope = {};
+Cu.import("resource:///modules/devtools/Target.jsm", tempScope);
+let TargetFactory = tempScope.TargetFactory;
+
+function test() {
+  waitForExplicitFinish();
+
+  let doc;
+  let node;
+  let view;
+  let inspector;
+
+  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 = "http://mochi.test:8888/browser/browser/devtools/fontinspector/test/browser_fontinspector.html";
+
+  function setupTest() {
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
+      openFontInspector(toolbox.getCurrentPanel());
+    });
+  }
+
+  function openFontInspector(aInspector) {
+    inspector = aInspector;
+
+    info("Inspector open");
+
+    inspector.selection.setNode(doc.body);
+    inspector.sidebar.select("fontinspector");
+    inspector.sidebar.once("fontinspector-ready", viewReady);
+  }
+
+  function viewReady() {
+    info("Font Inspector ready");
+
+    view = inspector.sidebar.getWindowForTab("fontinspector");
+
+    ok(!!view.fontInspector, "Font inspector document is alive.");
+
+    let d = view.document;
+
+    let s = d.querySelectorAll("#all-fonts > section");
+    is(s.length, 2, "Found 2 fonts");
+
+    is(s[0].querySelector(".font-name").textContent,
+       "DeLarge Bold", "font 0: Right font name");
+    ok(s[0].classList.contains("is-remote"),
+       "font 0: is remote");
+    is(s[0].querySelector(".font-url").value,
+       "http://mochi.test:8888/browser/browser/devtools/fontinspector/test/browser_font.woff",
+       "font 0: right url");
+    is(s[0].querySelector(".font-format").textContent,
+       "woff", "font 0: right font format");
+    is(s[0].querySelector(".font-css-name").textContent,
+       "bar", "font 0: right css name");
+
+
+    let font1Name = s[1].querySelector(".font-name").textContent;
+    let font1CssName = s[1].querySelector(".font-css-name").textContent;
+
+    // On Linux test machines, the Arial font doesn't exist.
+    // The fallback is "Liberation Sans"
+
+    ok((font1Name == "Arial") || (font1Name == "Liberation Sans"),
+       "font 1: Right font name");
+    ok(s[1].classList.contains("is-local"), "font 1: is local");
+    ok((font1CssName == "Arial") || (font1CssName == "Liberation Sans"),
+       "Arial", "font 1: right css name");
+
+    executeSoon(function() {
+      gDevTools.once("toolbox-destroyed", finishUp);
+      inspector._toolbox.destroy();
+    });
+  }
+
+  function finishUp() {
+    gBrowser.removeCurrentTab();
+    finish();
+  }
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/fontinspector/test/moz.build
@@ -0,0 +1,5 @@
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
--- a/browser/devtools/inspector/InspectorPanel.jsm
+++ b/browser/devtools/inspector/InspectorPanel.jsm
@@ -214,16 +214,22 @@ InspectorPanel.prototype = {
     this.sidebar.addTab("ruleview",
                         "chrome://browser/content/devtools/cssruleview.xul",
                         "ruleview" == defaultTab);
 
     this.sidebar.addTab("computedview",
                         "chrome://browser/content/devtools/csshtmltree.xul",
                         "computedview" == defaultTab);
 
+    if (Services.prefs.getBoolPref("devtools.fontinspector.enabled")) {
+      this.sidebar.addTab("fontinspector",
+                          "chrome://browser/content/devtools/fontinspector/font-inspector.xhtml",
+                          "fontinspector" == defaultTab);
+    }
+
     this.sidebar.addTab("layoutview",
                         "chrome://browser/content/devtools/layoutview/view.xhtml",
                         "layoutview" == defaultTab);
 
     let ruleViewTab = this.sidebar.getTab("ruleview");
     ruleViewTab.addEventListener("mouseover", this.toggleHighlighter, false);
     ruleViewTab.addEventListener("mouseout", this.toggleHighlighter, false);
 
--- a/browser/devtools/jar.mn
+++ b/browser/devtools/jar.mn
@@ -14,16 +14,19 @@ browser.jar:
     content/browser/styleeditor.xul               (styleeditor/styleeditor.xul)
     content/browser/styleeditor.css               (styleeditor/styleeditor.css)
     content/browser/devtools/csshtmltree.xul      (styleinspector/csshtmltree.xul)
     content/browser/devtools/cssruleview.xul      (styleinspector/cssruleview.xul)
     content/browser/devtools/styleinspector.css   (styleinspector/styleinspector.css)
     content/browser/devtools/layoutview/view.js   (layoutview/view.js)
     content/browser/devtools/layoutview/view.xhtml  (layoutview/view.xhtml)
     content/browser/devtools/layoutview/view.css  (layoutview/view.css)
+    content/browser/devtools/fontinspector/font-inspector.js    (fontinspector/font-inspector.js)
+    content/browser/devtools/fontinspector/font-inspector.xhtml (fontinspector/font-inspector.xhtml)
+    content/browser/devtools/fontinspector/font-inspector.css   (fontinspector/font-inspector.css)
     content/browser/orion.js                      (sourceeditor/orion/orion.js)
 *   content/browser/source-editor-overlay.xul     (sourceeditor/source-editor-overlay.xul)
     content/browser/debugger.xul                  (debugger/debugger.xul)
     content/browser/debugger.css                  (debugger/debugger.css)
     content/browser/debugger-controller.js        (debugger/debugger-controller.js)
     content/browser/debugger-view.js              (debugger/debugger-view.js)
     content/browser/debugger-toolbar.js           (debugger/debugger-toolbar.js)
     content/browser/debugger-panes.js             (debugger/debugger-panes.js)
--- a/browser/devtools/layoutview/view.js
+++ b/browser/devtools/layoutview/view.js
@@ -99,17 +99,17 @@ LayoutView.prototype = {
    */
   destroy: function LV_destroy() {
     this.inspector.sidebar.off("layoutview-selected", this.onNewNode);
     this.inspector.selection.off("new-node", this.onNewNode);
     if (this.browser) {
       this.browser.removeEventListener("MozAfterPaint", this.update, true);
     }
     if (this.inspector.highlighter) {
-      this.inspector.highlighter.on("locked", this.onHighlighterLocked);
+      this.inspector.highlighter.off("locked", this.onHighlighterLocked);
     }
     this.sizeHeadingLabel = null;
     this.sizeLabel = null;
     this.inspector = null;
     this.doc = null;
   },
 
   /**
--- a/browser/devtools/moz.build
+++ b/browser/devtools/moz.build
@@ -14,9 +14,10 @@ DIRS += [
     'tilt',
     'scratchpad',
     'debugger',
     'layoutview',
     'shared',
     'responsivedesign',
     'framework',
     'profiler',
+    'fontinspector',
 ]
new file mode 100644
--- /dev/null
+++ b/browser/locales/en-US/chrome/browser/devtools/font-inspector.dtd
@@ -0,0 +1,12 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<!-- LOCALIZATION NOTE : FILE This file contains the Font Inspector strings.
+  - The Font Inspector is the panel accessible in the Inspector sidebar. -->
+
+<!ENTITY title "Fonts">
+<!ENTITY showAllFonts "See all the fonts used in the page">
+<!ENTITY usedAs "Used as: ">
+<!ENTITY system "system">
+<!ENTITY remote "remote">
--- a/browser/locales/jar.mn
+++ b/browser/locales/jar.mn
@@ -42,16 +42,17 @@
     locale/browser/devtools/profiler.properties       (%chrome/browser/devtools/profiler.properties)
     locale/browser/devtools/layoutview.dtd            (%chrome/browser/devtools/layoutview.dtd)
     locale/browser/devtools/responsiveUI.properties   (%chrome/browser/devtools/responsiveUI.properties)
     locale/browser/devtools/toolbox.dtd            (%chrome/browser/devtools/toolbox.dtd)
     locale/browser/devtools/toolbox.properties     (%chrome/browser/devtools/toolbox.properties)
     locale/browser/devtools/inspector.dtd          (%chrome/browser/devtools/inspector.dtd)
     locale/browser/devtools/connection-screen.dtd  (%chrome/browser/devtools/connection-screen.dtd)
     locale/browser/devtools/connection-screen.properties (%chrome/browser/devtools/connection-screen.properties)
+    locale/browser/devtools/font-inspector.dtd     (%chrome/browser/devtools/font-inspector.dtd)
     locale/browser/newTab.dtd                      (%chrome/browser/newTab.dtd)
     locale/browser/newTab.properties               (%chrome/browser/newTab.properties)
     locale/browser/openLocation.dtd                (%chrome/browser/openLocation.dtd)
     locale/browser/openLocation.properties         (%chrome/browser/openLocation.properties)
     locale/browser/pageInfo.dtd                    (%chrome/browser/pageInfo.dtd)
     locale/browser/pageInfo.properties             (%chrome/browser/pageInfo.properties)
     locale/browser/quitDialog.properties           (%chrome/browser/quitDialog.properties)
     locale/browser/safeMode.dtd                    (%chrome/browser/safeMode.dtd)
new file mode 100644
--- /dev/null
+++ b/browser/themes/linux/devtools/font-inspector.css
@@ -0,0 +1,79 @@
+* {
+  -moz-box-sizing: border-box;
+}
+
+body {
+  background: #F9F9F9;
+  margin: 0;
+  padding-bottom: 20px;
+}
+
+#all-fonts {
+  padding: 0 5px;
+  margin: 0;
+}
+
+#showall {
+  border-radius: 0;
+  border: 1px solid black;
+  margin: 3px;
+  cursor: pointer;
+  position: fixed;
+  bottom: 0;
+  right: 0;
+}
+
+.font {
+  border-bottom: 1px solid #DDD;
+  padding: 10px 5px;
+  font-size: 0;
+}
+
+.font:last-of-type {
+  border-bottom: 0;
+}
+
+.font:nth-child(even) {
+  background: #F4F4F4;
+}
+
+.font-preview {
+  height: 60px;
+  width: 100%;
+  border: 0;
+  display: block;
+}
+
+.font-info {
+  font-size: 1rem;
+  display: block;
+}
+
+.font-name {
+  display: inline;
+}
+
+.font-css-code {
+  max-width: 100%;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  background: white;
+  padding: 5px;
+  border: 1px dotted #CCC;
+}
+
+.font-is-local,
+.font-is-remote,
+.font-format-url,
+.font-css {
+  color: #999
+}
+
+.font-url {
+  border: 1px solid #CCC;
+  color: #888;
+}
+
+.font-url:focus {
+  color: black;
+}
--- a/browser/themes/linux/jar.mn
+++ b/browser/themes/linux/jar.mn
@@ -185,16 +185,17 @@ browser.jar:
   skin/classic/browser/devtools/toolbox.css               (devtools/toolbox.css)
   skin/classic/browser/devtools/tool-webconsole.png       (devtools/tool-webconsole.png)
   skin/classic/browser/devtools/tool-debugger.png         (devtools/tool-debugger.png)
   skin/classic/browser/devtools/tool-inspector.png        (devtools/tool-inspector.png)
   skin/classic/browser/devtools/tool-styleeditor.png      (devtools/tool-styleeditor.png)
   skin/classic/browser/devtools/tool-profiler.png         (devtools/tool-profiler.png)
   skin/classic/browser/devtools/close.png                 (devtools/close.png)
   skin/classic/browser/devtools/undock.png                (devtools/undock.png)
+  skin/classic/browser/devtools/font-inspector.css        (devtools/font-inspector.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-128.png
   skin/classic/browser/sync-desktopIcon.png
new file mode 100644
--- /dev/null
+++ b/browser/themes/osx/devtools/font-inspector.css
@@ -0,0 +1,79 @@
+* {
+  -moz-box-sizing: border-box;
+}
+
+body {
+  background: #F9F9F9;
+  margin: 0;
+  padding-bottom: 20px;
+}
+
+#all-fonts {
+  padding: 0 5px;
+  margin: 0;
+}
+
+#showall {
+  border-radius: 0;
+  border: 1px solid black;
+  margin: 3px;
+  cursor: pointer;
+  position: fixed;
+  bottom: 0;
+  right: 0;
+}
+
+.font {
+  border-bottom: 1px solid #DDD;
+  padding: 10px 5px;
+  font-size: 0;
+}
+
+.font:last-of-type {
+  border-bottom: 0;
+}
+
+.font:nth-child(even) {
+  background: #F4F4F4;
+}
+
+.font-preview {
+  height: 60px;
+  width: 100%;
+  border: 0;
+  display: block;
+}
+
+.font-info {
+  font-size: 1rem;
+  display: block;
+}
+
+.font-name {
+  display: inline;
+}
+
+.font-css-code {
+  max-width: 100%;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  background: white;
+  padding: 5px;
+  border: 1px dotted #CCC;
+}
+
+.font-is-local,
+.font-is-remote,
+.font-format-url,
+.font-css {
+  color: #999
+}
+
+.font-url {
+  border: 1px solid #CCC;
+  color: #888;
+}
+
+.font-url:focus {
+  color: black;
+}
--- a/browser/themes/osx/jar.mn
+++ b/browser/themes/osx/jar.mn
@@ -266,16 +266,17 @@ browser.jar:
   skin/classic/browser/devtools/toolbox.css                 (devtools/toolbox.css)
   skin/classic/browser/devtools/tool-webconsole.png         (devtools/tool-webconsole.png)
   skin/classic/browser/devtools/tool-debugger.png           (devtools/tool-debugger.png)
   skin/classic/browser/devtools/tool-inspector.png          (devtools/tool-inspector.png)
   skin/classic/browser/devtools/tool-styleeditor.png        (devtools/tool-styleeditor.png)
   skin/classic/browser/devtools/tool-profiler.png           (devtools/tool-profiler.png)
   skin/classic/browser/devtools/close.png                   (devtools/close.png)
   skin/classic/browser/devtools/undock.png                  (devtools/undock.png)
+  skin/classic/browser/devtools/font-inspector.css          (devtools/font-inspector.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-128.png
   skin/classic/browser/sync-desktopIcon.png
   skin/classic/browser/sync-mobileIcon.png
new file mode 100644
--- /dev/null
+++ b/browser/themes/windows/devtools/font-inspector.css
@@ -0,0 +1,79 @@
+* {
+  -moz-box-sizing: border-box;
+}
+
+body {
+  background: #F9F9F9;
+  margin: 0;
+  padding-bottom: 20px;
+}
+
+#all-fonts {
+  padding: 0 5px;
+  margin: 0;
+}
+
+#showall {
+  border-radius: 0;
+  border: 1px solid black;
+  margin: 3px;
+  cursor: pointer;
+  position: fixed;
+  bottom: 0;
+  right: 0;
+}
+
+.font {
+  border-bottom: 1px solid #DDD;
+  padding: 10px 5px;
+  font-size: 0;
+}
+
+.font:last-of-type {
+  border-bottom: 0;
+}
+
+.font:nth-child(even) {
+  background: #F4F4F4;
+}
+
+.font-preview {
+  height: 60px;
+  width: 100%;
+  border: 0;
+  display: block;
+}
+
+.font-info {
+  font-size: 1rem;
+  display: block;
+}
+
+.font-name {
+  display: inline;
+}
+
+.font-css-code {
+  max-width: 100%;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  background: white;
+  padding: 5px;
+  border: 1px dotted #CCC;
+}
+
+.font-is-local,
+.font-is-remote,
+.font-format-url,
+.font-css {
+  color: #999
+}
+
+.font-url {
+  border: 1px solid #CCC;
+  color: #888;
+}
+
+.font-url:focus {
+  color: black;
+}
--- a/browser/themes/windows/jar.mn
+++ b/browser/themes/windows/jar.mn
@@ -212,16 +212,17 @@ browser.jar:
         skin/classic/browser/devtools/toolbox.css                   (devtools/toolbox.css)
         skin/classic/browser/devtools/tool-webconsole.png           (devtools/tool-webconsole.png)
         skin/classic/browser/devtools/tool-debugger.png             (devtools/tool-debugger.png)
         skin/classic/browser/devtools/tool-inspector.png            (devtools/tool-inspector.png)
         skin/classic/browser/devtools/tool-styleeditor.png          (devtools/tool-styleeditor.png)
         skin/classic/browser/devtools/tool-profiler.png             (devtools/tool-profiler.png)
         skin/classic/browser/devtools/close.png                     (devtools/close.png)
         skin/classic/browser/devtools/undock.png                    (devtools/undock.png)
+        skin/classic/browser/devtools/font-inspector.css            (devtools/font-inspector.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-128.png
         skin/classic/browser/sync-bg.png
         skin/classic/browser/sync-desktopIcon.png
         skin/classic/browser/sync-mobileIcon.png
@@ -440,16 +441,17 @@ browser.jar:
         skin/classic/aero/browser/devtools/toolbox.css               (devtools/toolbox.css)
         skin/classic/aero/browser/devtools/tool-webconsole.png       (devtools/tool-webconsole.png)
         skin/classic/aero/browser/devtools/tool-debugger.png         (devtools/tool-debugger.png)
         skin/classic/aero/browser/devtools/tool-inspector.png        (devtools/tool-inspector.png)
         skin/classic/aero/browser/devtools/tool-styleeditor.png      (devtools/tool-styleeditor.png)
         skin/classic/aero/browser/devtools/tool-profiler.png         (devtools/tool-profiler.png)
         skin/classic/aero/browser/devtools/close.png                 (devtools/close.png)
         skin/classic/aero/browser/devtools/undock.png                (devtools/undock.png)
+        skin/classic/aero/browser/devtools/font-inspector.css        (devtools/font-inspector.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-128.png
         skin/classic/aero/browser/sync-bg.png
         skin/classic/aero/browser/sync-desktopIcon.png
         skin/classic/aero/browser/sync-mobileIcon.png