summaryrefslogtreecommitdiffstats
path: root/devtools/client/inspector/fonts
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /devtools/client/inspector/fonts
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'devtools/client/inspector/fonts')
-rw-r--r--devtools/client/inspector/fonts/fonts.js250
-rw-r--r--devtools/client/inspector/fonts/moz.build11
-rw-r--r--devtools/client/inspector/fonts/test/.eslintrc.js6
-rw-r--r--devtools/client/inspector/fonts/test/OstrichLicense.txt41
-rw-r--r--devtools/client/inspector/fonts/test/browser.ini20
-rw-r--r--devtools/client/inspector/fonts/test/browser_fontinspector.html52
-rw-r--r--devtools/client/inspector/fonts/test/browser_fontinspector.js108
-rw-r--r--devtools/client/inspector/fonts/test/browser_fontinspector_edit-previews-show-all.js44
-rw-r--r--devtools/client/inspector/fonts/test/browser_fontinspector_edit-previews.js60
-rw-r--r--devtools/client/inspector/fonts/test/browser_fontinspector_theme-change.js55
-rw-r--r--devtools/client/inspector/fonts/test/head.js86
-rwxr-xr-xdevtools/client/inspector/fonts/test/ostrich-black.ttfbin0 -> 12872 bytes
-rwxr-xr-xdevtools/client/inspector/fonts/test/ostrich-regular.ttfbin0 -> 12476 bytes
-rw-r--r--devtools/client/inspector/fonts/test/test_iframe.html11
14 files changed, 744 insertions, 0 deletions
diff --git a/devtools/client/inspector/fonts/fonts.js b/devtools/client/inspector/fonts/fonts.js
new file mode 100644
index 000000000..b0087e9f6
--- /dev/null
+++ b/devtools/client/inspector/fonts/fonts.js
@@ -0,0 +1,250 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 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 {gDevTools} = require("devtools/client/framework/devtools");
+
+const DEFAULT_PREVIEW_TEXT = "Abc";
+const PREVIEW_UPDATE_DELAY = 150;
+
+const {Task} = require("devtools/shared/task");
+const {getColor} = require("devtools/client/shared/theme");
+
+function FontInspector(inspector, window) {
+ this.inspector = inspector;
+ this.pageStyle = this.inspector.pageStyle;
+ this.chromeDoc = window.document;
+ this.init();
+}
+
+FontInspector.prototype = {
+ init: function () {
+ this.update = this.update.bind(this);
+ this.onNewNode = this.onNewNode.bind(this);
+ this.onThemeChanged = this.onThemeChanged.bind(this);
+ this.inspector.selection.on("new-node-front", this.onNewNode);
+ this.inspector.sidebar.on("fontinspector-selected", this.onNewNode);
+ this.showAll = this.showAll.bind(this);
+ this.showAllLink = this.chromeDoc.getElementById("font-showall");
+ this.showAllLink.addEventListener("click", this.showAll);
+ this.previewTextChanged = this.previewTextChanged.bind(this);
+ this.previewInput = this.chromeDoc.getElementById("font-preview-text-input");
+ this.previewInput.addEventListener("input", this.previewTextChanged);
+ this.previewInput.addEventListener("contextmenu",
+ this.inspector.onTextBoxContextMenu);
+
+ // Listen for theme changes as the color of the previews depend on the theme
+ gDevTools.on("theme-switched", this.onThemeChanged);
+
+ this.update();
+ },
+
+ /**
+ * Is the fontinspector visible in the sidebar?
+ */
+ isActive: function () {
+ return this.inspector.sidebar &&
+ this.inspector.sidebar.getCurrentTabID() == "fontinspector";
+ },
+
+ /**
+ * Remove listeners.
+ */
+ destroy: function () {
+ this.chromeDoc = null;
+ this.inspector.sidebar.off("fontinspector-selected", this.onNewNode);
+ this.inspector.selection.off("new-node-front", this.onNewNode);
+ this.showAllLink.removeEventListener("click", this.showAll);
+ this.previewInput.removeEventListener("input", this.previewTextChanged);
+ this.previewInput.removeEventListener("contextmenu",
+ this.inspector.onTextBoxContextMenu);
+
+ gDevTools.off("theme-switched", this.onThemeChanged);
+
+ if (this._previewUpdateTimeout) {
+ clearTimeout(this._previewUpdateTimeout);
+ }
+ },
+
+ /**
+ * Selection 'new-node' event handler.
+ */
+ onNewNode: function () {
+ if (this.isActive() &&
+ this.inspector.selection.isConnected() &&
+ this.inspector.selection.isElementNode()) {
+ this.undim();
+ this.update();
+ } else {
+ this.dim();
+ }
+ },
+
+ /**
+ * The text to use for previews. Returns either the value user has typed to
+ * the preview input or DEFAULT_PREVIEW_TEXT if the input is empty or contains
+ * only whitespace.
+ */
+ getPreviewText: function () {
+ let inputText = this.previewInput.value.trim();
+ if (inputText === "") {
+ return DEFAULT_PREVIEW_TEXT;
+ }
+
+ return inputText;
+ },
+
+ /**
+ * Preview input 'input' event handler.
+ */
+ previewTextChanged: function () {
+ if (this._previewUpdateTimeout) {
+ clearTimeout(this._previewUpdateTimeout);
+ }
+
+ this._previewUpdateTimeout = setTimeout(() => {
+ this.update(this._lastUpdateShowedAllFonts);
+ }, PREVIEW_UPDATE_DELAY);
+ },
+
+ /**
+ * Callback for the theme-switched event.
+ */
+ onThemeChanged: function (event, frame) {
+ if (frame === this.chromeDoc.defaultView) {
+ this.update(this._lastUpdateShowedAllFonts);
+ }
+ },
+
+ /**
+ * Hide the font list. No node are selected.
+ */
+ dim: function () {
+ let panel = this.chromeDoc.getElementById("sidebar-panel-fontinspector");
+ panel.classList.add("dim");
+ this.clear();
+ },
+
+ /**
+ * Show the font list. A node is selected.
+ */
+ undim: function () {
+ let panel = this.chromeDoc.getElementById("sidebar-panel-fontinspector");
+ panel.classList.remove("dim");
+ },
+
+ /**
+ * Clears the font list.
+ */
+ clear: function () {
+ this.chromeDoc.querySelector("#all-fonts").innerHTML = "";
+ },
+
+ /**
+ * Retrieve all the font info for the selected node and display it.
+ */
+ update: Task.async(function* (showAllFonts) {
+ let node = this.inspector.selection.nodeFront;
+ let panel = this.chromeDoc.getElementById("sidebar-panel-fontinspector");
+
+ if (!node ||
+ !this.isActive() ||
+ !this.inspector.selection.isConnected() ||
+ !this.inspector.selection.isElementNode() ||
+ panel.classList.contains("dim")) {
+ return;
+ }
+
+ this._lastUpdateShowedAllFonts = showAllFonts;
+
+ let options = {
+ includePreviews: true,
+ previewText: this.getPreviewText(),
+ previewFillStyle: getColor("body-color")
+ };
+
+ let fonts = [];
+ if (showAllFonts) {
+ fonts = yield this.pageStyle.getAllUsedFontFaces(options)
+ .then(null, console.error);
+ } else {
+ fonts = yield this.pageStyle.getUsedFontFaces(node, options)
+ .then(null, console.error);
+ }
+
+ if (!fonts || !fonts.length) {
+ // No fonts to display. Clear the previously shown fonts.
+ this.clear();
+ return;
+ }
+
+ for (let font of fonts) {
+ font.previewUrl = yield font.preview.data.string();
+ }
+
+ // in case we've been destroyed in the meantime
+ if (!this.chromeDoc) {
+ return;
+ }
+
+ // Make room for the new fonts.
+ this.clear();
+
+ for (let font of fonts) {
+ this.render(font);
+ }
+
+ this.inspector.emit("fontinspector-updated");
+ }),
+
+ /**
+ * Display the information of one font.
+ */
+ render: function (font) {
+ let s = this.chromeDoc.querySelector("#font-template > section");
+ s = s.cloneNode(true);
+
+ s.querySelector(".font-name").textContent = font.name;
+ s.querySelector(".font-css-name").textContent = font.CSSFamilyName;
+
+ if (font.URI) {
+ s.classList.add("is-remote");
+ } else {
+ s.classList.add("is-local");
+ }
+
+ let formatElem = s.querySelector(".font-format");
+ if (font.format) {
+ formatElem.textContent = font.format;
+ } else {
+ formatElem.hidden = true;
+ }
+
+ s.querySelector(".font-url").value = font.URI;
+
+ if (font.rule) {
+ // This is the @font-face{…} code.
+ let cssText = font.ruleText;
+
+ s.classList.add("has-code");
+ s.querySelector(".font-css-code").textContent = cssText;
+ }
+ let preview = s.querySelector(".font-preview");
+ preview.src = font.previewUrl;
+
+ this.chromeDoc.querySelector("#all-fonts").appendChild(s);
+ },
+
+ /**
+ * Show all fonts for the document (including iframes)
+ */
+ showAll: function () {
+ this.update(true);
+ },
+};
+
+exports.FontInspector = FontInspector;
diff --git a/devtools/client/inspector/fonts/moz.build b/devtools/client/inspector/fonts/moz.build
new file mode 100644
index 000000000..a66982b71
--- /dev/null
+++ b/devtools/client/inspector/fonts/moz.build
@@ -0,0 +1,11 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# 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/.
+
+DevToolsModules(
+ 'fonts.js',
+)
+
+BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
diff --git a/devtools/client/inspector/fonts/test/.eslintrc.js b/devtools/client/inspector/fonts/test/.eslintrc.js
new file mode 100644
index 000000000..698ae9181
--- /dev/null
+++ b/devtools/client/inspector/fonts/test/.eslintrc.js
@@ -0,0 +1,6 @@
+"use strict";
+
+module.exports = {
+ // Extend from the shared list of defined globals for mochitests.
+ "extends": "../../../../.eslintrc.mochitests.js"
+};
diff --git a/devtools/client/inspector/fonts/test/OstrichLicense.txt b/devtools/client/inspector/fonts/test/OstrichLicense.txt
new file mode 100644
index 000000000..14c043d60
--- /dev/null
+++ b/devtools/client/inspector/fonts/test/OstrichLicense.txt
@@ -0,0 +1,41 @@
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment.
+
+"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission.
+
+5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. \ No newline at end of file
diff --git a/devtools/client/inspector/fonts/test/browser.ini b/devtools/client/inspector/fonts/test/browser.ini
new file mode 100644
index 000000000..99b00231d
--- /dev/null
+++ b/devtools/client/inspector/fonts/test/browser.ini
@@ -0,0 +1,20 @@
+[DEFAULT]
+tags = devtools
+subsuite = devtools
+support-files =
+ browser_fontinspector.html
+ test_iframe.html
+ ostrich-black.ttf
+ ostrich-regular.ttf
+ head.js
+ !/devtools/client/commandline/test/helpers.js
+ !/devtools/client/framework/test/shared-head.js
+ !/devtools/client/inspector/test/head.js
+ !/devtools/client/inspector/test/shared-head.js
+ !/devtools/client/shared/test/test-actor.js
+ !/devtools/client/shared/test/test-actor-registry.js
+
+[browser_fontinspector.js]
+[browser_fontinspector_edit-previews.js]
+[browser_fontinspector_edit-previews-show-all.js]
+[browser_fontinspector_theme-change.js]
diff --git a/devtools/client/inspector/fonts/test/browser_fontinspector.html b/devtools/client/inspector/fonts/test/browser_fontinspector.html
new file mode 100644
index 000000000..009b2f087
--- /dev/null
+++ b/devtools/client/inspector/fonts/test/browser_fontinspector.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+
+<style>
+ @font-face {
+ font-family: bar;
+ src: url(bad/font/name.ttf), url(ostrich-regular.ttf) format("truetype");
+ }
+ @font-face {
+ font-family: barnormal;
+ font-weight: normal;
+ src: url(ostrich-regular.ttf);
+ }
+ @font-face {
+ font-family: bar;
+ font-weight: bold;
+ src: url(ostrich-black.ttf);
+ }
+ @font-face {
+ font-family: bar;
+ font-weight: 800;
+ src: url(ostrich-black.ttf);
+ }
+ body{
+ font-family:Arial;
+ font-size: 36px;
+ }
+ div {
+ font-family:Arial;
+ font-family:bar;
+ }
+ .normal-text {
+ font-family: barnormal;
+ font-weight: normal;
+ }
+ .bold-text {
+ font-family: bar;
+ font-weight: bold;
+ }
+ .black-text {
+ font-family: bar;
+ font-weight: 800;
+ }
+</style>
+
+<body>
+ BODY
+ <div>DIV</div>
+ <iframe src="test_iframe.html"></iframe>
+ <div class="normal-text">NORMAL DIV</div>
+ <div class="bold-text">BOLD DIV</div>
+ <div class="black-text">800 DIV</div>
+</body>
diff --git a/devtools/client/inspector/fonts/test/browser_fontinspector.js b/devtools/client/inspector/fonts/test/browser_fontinspector.js
new file mode 100644
index 000000000..a36c57771
--- /dev/null
+++ b/devtools/client/inspector/fonts/test/browser_fontinspector.js
@@ -0,0 +1,108 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+requestLongerTimeout(2);
+
+const TEST_URI = URL_ROOT + "browser_fontinspector.html";
+const FONTS = [{
+ name: "Ostrich Sans Medium",
+ remote: true,
+ url: URL_ROOT + "ostrich-regular.ttf",
+ format: "truetype",
+ cssName: "bar"
+}, {
+ name: "Ostrich Sans Black",
+ remote: true,
+ url: URL_ROOT + "ostrich-black.ttf",
+ format: "",
+ cssName: "bar"
+}, {
+ name: "Ostrich Sans Black",
+ remote: true,
+ url: URL_ROOT + "ostrich-black.ttf",
+ format: "",
+ cssName: "bar"
+}, {
+ name: "Ostrich Sans Medium",
+ remote: true,
+ url: URL_ROOT + "ostrich-regular.ttf",
+ format: "",
+ cssName: "barnormal"
+}];
+
+add_task(function* () {
+ let { inspector, view } = yield openFontInspectorForURL(TEST_URI);
+ ok(!!view, "Font inspector document is alive.");
+
+ let viewDoc = view.chromeDoc;
+
+ yield testBodyFonts(inspector, viewDoc);
+ yield testDivFonts(inspector, viewDoc);
+ yield testShowAllFonts(inspector, viewDoc);
+});
+
+function* testBodyFonts(inspector, viewDoc) {
+ let s = viewDoc.querySelectorAll("#all-fonts > section");
+ is(s.length, 5, "Found 5 fonts");
+
+ for (let i = 0; i < FONTS.length; i++) {
+ let section = s[i];
+ let font = FONTS[i];
+ is(section.querySelector(".font-name").textContent, font.name,
+ "font " + i + " right font name");
+ is(section.classList.contains("is-remote"), font.remote,
+ "font " + i + " remote value correct");
+ is(section.querySelector(".font-url").value, font.url,
+ "font " + i + " url correct");
+ is(section.querySelector(".font-format").hidden, !font.format,
+ "font " + i + " format hidden value correct");
+ is(section.querySelector(".font-format").textContent,
+ font.format, "font " + i + " format correct");
+ is(section.querySelector(".font-css-name").textContent,
+ font.cssName, "font " + i + " css name correct");
+ }
+
+ // test that the bold and regular fonts have different previews
+ let regSrc = s[0].querySelector(".font-preview").src;
+ let boldSrc = s[1].querySelector(".font-preview").src;
+ isnot(regSrc, boldSrc, "preview for bold font is different from regular");
+
+ // test system font
+ let localFontName = s[4].querySelector(".font-name").textContent;
+ let localFontCSSName = s[4].querySelector(".font-css-name").textContent;
+
+ // On Linux test machines, the Arial font doesn't exist.
+ // The fallback is "Liberation Sans"
+ ok((localFontName == "Arial") || (localFontName == "Liberation Sans"),
+ "local font right font name");
+ ok(s[4].classList.contains("is-local"), "local font is local");
+ ok((localFontCSSName == "Arial") || (localFontCSSName == "Liberation Sans"),
+ "Arial", "local font has right css name");
+}
+
+function* testDivFonts(inspector, viewDoc) {
+ let updated = inspector.once("fontinspector-updated");
+ yield selectNode("div", inspector);
+ yield updated;
+
+ let sections1 = viewDoc.querySelectorAll("#all-fonts > section");
+ is(sections1.length, 1, "Found 1 font on DIV");
+ is(sections1[0].querySelector(".font-name").textContent,
+ "Ostrich Sans Medium",
+ "The DIV font has the right name");
+}
+
+function* testShowAllFonts(inspector, viewDoc) {
+ info("testing showing all fonts");
+
+ let updated = inspector.once("fontinspector-updated");
+ viewDoc.querySelector("#font-showall").click();
+ yield updated;
+
+ // shouldn't change the node selection
+ is(inspector.selection.nodeFront.nodeName, "DIV", "Show all fonts selected");
+ let sections = viewDoc.querySelectorAll("#all-fonts > section");
+ is(sections.length, 6, "Font inspector shows 6 fonts (1 from iframe)");
+}
diff --git a/devtools/client/inspector/fonts/test/browser_fontinspector_edit-previews-show-all.js b/devtools/client/inspector/fonts/test/browser_fontinspector_edit-previews-show-all.js
new file mode 100644
index 000000000..f1319b400
--- /dev/null
+++ b/devtools/client/inspector/fonts/test/browser_fontinspector_edit-previews-show-all.js
@@ -0,0 +1,44 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+// Test that correct previews are shown if the text is edited after 'Show all'
+// button is pressed.
+
+const TEST_URI = URL_ROOT + "browser_fontinspector.html";
+
+add_task(function* () {
+ let { inspector, view } = yield openFontInspectorForURL(TEST_URI);
+ let viewDoc = view.chromeDoc;
+
+ info("Selecting a node that doesn't contain all document fonts.");
+ yield selectNode(".normal-text", inspector);
+
+ let normalTextNumPreviews =
+ viewDoc.querySelectorAll("#all-fonts .font-preview").length;
+
+ let onUpdated = inspector.once("fontinspector-updated");
+
+ info("Clicking 'Select all' button.");
+ viewDoc.getElementById("font-showall").click();
+
+ info("Waiting for font-inspector to update.");
+ yield onUpdated;
+
+ let allFontsNumPreviews =
+ viewDoc.querySelectorAll("#all-fonts .font-preview").length;
+
+ // Sanity check. If this fails all fonts apply also to the .normal-text node
+ // meaning we won't detect if preview editing causes the panel not to show all
+ // fonts.
+ isnot(allFontsNumPreviews, normalTextNumPreviews,
+ "The .normal-text didn't show all fonts.");
+
+ info("Editing the preview text.");
+ yield updatePreviewText(view, "The quick brown");
+
+ let numPreviews = viewDoc.querySelectorAll("#all-fonts .font-preview").length;
+ is(numPreviews, allFontsNumPreviews,
+ "All fonts are still shown after the preview text was edited.");
+});
diff --git a/devtools/client/inspector/fonts/test/browser_fontinspector_edit-previews.js b/devtools/client/inspector/fonts/test/browser_fontinspector_edit-previews.js
new file mode 100644
index 000000000..adc421b6b
--- /dev/null
+++ b/devtools/client/inspector/fonts/test/browser_fontinspector_edit-previews.js
@@ -0,0 +1,60 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+// Test that previews change when the preview text changes. It doesn't check the
+// exact preview images because they are drawn on a canvas causing them to vary
+// between systems, platforms and software versions.
+
+const TEST_URI = URL_ROOT + "browser_fontinspector.html";
+
+add_task(function* () {
+ let {view} = yield openFontInspectorForURL(TEST_URI);
+ let viewDoc = view.chromeDoc;
+
+ let previews = viewDoc.querySelectorAll("#all-fonts .font-preview");
+ let initialPreviews = [...previews].map(p => p.src);
+
+ info("Typing 'Abc' to check that the reference previews are correct.");
+ yield updatePreviewText(view, "Abc");
+ checkPreviewImages(viewDoc, initialPreviews, true);
+
+ info("Typing something else to the preview box.");
+ yield updatePreviewText(view, "The quick brown");
+ checkPreviewImages(viewDoc, initialPreviews, false);
+
+ info("Blanking the input to restore default previews.");
+ yield updatePreviewText(view, "");
+ checkPreviewImages(viewDoc, initialPreviews, true);
+});
+
+/**
+ * Compares the previous preview image URIs to the current URIs.
+ *
+ * @param {Document} viewDoc
+ * The FontInspector document.
+ * @param {Array[String]} originalURIs
+ * An array of URIs to compare with the current URIs.
+ * @param {Boolean} assertIdentical
+ * If true, this method asserts that the previous and current URIs are
+ * identical. If false, this method asserts that the previous and current
+ * URI's are different.
+ */
+function checkPreviewImages(viewDoc, originalURIs, assertIdentical) {
+ let previews = viewDoc.querySelectorAll("#all-fonts .font-preview");
+ let newURIs = [...previews].map(p => p.src);
+
+ is(newURIs.length, originalURIs.length,
+ "The number of previews has not changed.");
+
+ for (let i = 0; i < newURIs.length; ++i) {
+ if (assertIdentical) {
+ is(newURIs[i], originalURIs[i],
+ `The preview image at index ${i} has stayed the same.`);
+ } else {
+ isnot(newURIs[i], originalURIs[i],
+ `The preview image at index ${i} has changed.`);
+ }
+ }
+}
diff --git a/devtools/client/inspector/fonts/test/browser_fontinspector_theme-change.js b/devtools/client/inspector/fonts/test/browser_fontinspector_theme-change.js
new file mode 100644
index 000000000..7fcfc9cc2
--- /dev/null
+++ b/devtools/client/inspector/fonts/test/browser_fontinspector_theme-change.js
@@ -0,0 +1,55 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+requestLongerTimeout(2);
+
+// Test that the preview images are updated when the theme changes.
+
+const { getTheme, setTheme } = require("devtools/client/shared/theme");
+
+const TEST_URI = URL_ROOT + "browser_fontinspector.html";
+const originalTheme = getTheme();
+
+registerCleanupFunction(() => {
+ info(`Restoring theme to '${originalTheme}.`);
+ setTheme(originalTheme);
+});
+
+add_task(function* () {
+ let { inspector, view } = yield openFontInspectorForURL(TEST_URI);
+ let { chromeDoc: doc } = view;
+
+ yield selectNode(".normal-text", inspector);
+
+ // Store the original preview URI for later comparison.
+ let originalURI = doc.querySelector("#all-fonts .font-preview").src;
+ let newTheme = originalTheme === "light" ? "dark" : "light";
+
+ info(`Original theme was '${originalTheme}'.`);
+
+ yield setThemeAndWaitForUpdate(newTheme, inspector);
+ isnot(doc.querySelector("#all-fonts .font-preview").src, originalURI,
+ "The preview image changed with the theme.");
+
+ yield setThemeAndWaitForUpdate(originalTheme, inspector);
+ is(doc.querySelector("#all-fonts .font-preview").src, originalURI,
+ "The preview image is correct after the original theme was restored.");
+});
+
+/**
+ * Sets the current theme and waits for fontinspector-updated event.
+ *
+ * @param {String} theme - the new theme
+ * @param {Object} inspector - the inspector panel
+ */
+function* setThemeAndWaitForUpdate(theme, inspector) {
+ let onUpdated = inspector.once("fontinspector-updated");
+
+ info(`Setting theme to '${theme}'.`);
+ setTheme(theme);
+
+ info("Waiting for font-inspector to update.");
+ yield onUpdated;
+}
diff --git a/devtools/client/inspector/fonts/test/head.js b/devtools/client/inspector/fonts/test/head.js
new file mode 100644
index 000000000..f510ed798
--- /dev/null
+++ b/devtools/client/inspector/fonts/test/head.js
@@ -0,0 +1,86 @@
+ /* vim: set 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/. */
+/* eslint no-unused-vars: [2, {"vars": "local"}] */
+/* import-globals-from ../../test/head.js */
+"use strict";
+
+// Import the inspector's head.js first (which itself imports shared-head.js).
+Services.scriptloader.loadSubScript(
+ "chrome://mochitests/content/browser/devtools/client/inspector/test/head.js",
+ this);
+
+Services.prefs.setBoolPref("devtools.fontinspector.enabled", true);
+Services.prefs.setCharPref("devtools.inspector.activeSidebar", "fontinspector");
+registerCleanupFunction(() => {
+ Services.prefs.clearUserPref("devtools.fontinspector.enabled");
+});
+
+/**
+ * The font-inspector doesn't participate in the inspector's update mechanism
+ * (i.e. it doesn't call inspector.updating() when updating), so simply calling
+ * the default selectNode isn't enough to guaranty that the panel has finished
+ * updating. We also need to wait for the fontinspector-updated event.
+ */
+var _selectNode = selectNode;
+selectNode = function* (node, inspector, reason) {
+ let onUpdated = inspector.once("fontinspector-updated");
+ yield _selectNode(node, inspector, reason);
+ yield onUpdated;
+};
+
+/**
+ * Adds a new tab with the given URL, opens the inspector and selects the
+ * font-inspector tab.
+ * @return {Promise} resolves to a {toolbox, inspector, view} object
+ */
+var openFontInspectorForURL = Task.async(function* (url) {
+ yield addTab(url);
+ let {toolbox, inspector} = yield openInspector();
+
+ // Call selectNode again here to force a fontinspector update since we don't
+ // know if the fontinspector-updated event has been sent while the inspector
+ // was being opened or not.
+ yield selectNode("body", inspector);
+
+ return {
+ toolbox,
+ inspector,
+ view: inspector.fontInspector
+ };
+});
+
+/**
+ * Clears the preview input field, types new text into it and waits for the
+ * preview images to be updated.
+ *
+ * @param {FontInspector} view - The FontInspector instance.
+ * @param {String} text - The text to preview.
+ */
+function* updatePreviewText(view, text) {
+ info(`Changing the preview text to '${text}'`);
+
+ let doc = view.chromeDoc;
+ let input = doc.getElementById("font-preview-text-input");
+ let update = view.inspector.once("fontinspector-updated");
+
+ info("Focusing the input field.");
+ input.focus();
+
+ is(doc.activeElement, input, "The input was focused.");
+
+ info("Blanking the input field.");
+ for (let i = input.value.length; i >= 0; i--) {
+ EventUtils.sendKey("BACK_SPACE", doc.defaultView);
+ }
+
+ is(input.value, "", "The input is now blank.");
+
+ info("Typing the specified text to the input field.");
+ EventUtils.sendString(text, doc.defaultView);
+ is(input.value, text, "The input now contains the correct text.");
+
+ info("Waiting for the font-inspector to update.");
+ yield update;
+}
diff --git a/devtools/client/inspector/fonts/test/ostrich-black.ttf b/devtools/client/inspector/fonts/test/ostrich-black.ttf
new file mode 100755
index 000000000..a0ef8fe1c
--- /dev/null
+++ b/devtools/client/inspector/fonts/test/ostrich-black.ttf
Binary files differ
diff --git a/devtools/client/inspector/fonts/test/ostrich-regular.ttf b/devtools/client/inspector/fonts/test/ostrich-regular.ttf
new file mode 100755
index 000000000..9682c0735
--- /dev/null
+++ b/devtools/client/inspector/fonts/test/ostrich-regular.ttf
Binary files differ
diff --git a/devtools/client/inspector/fonts/test/test_iframe.html b/devtools/client/inspector/fonts/test/test_iframe.html
new file mode 100644
index 000000000..29393a9e9
--- /dev/null
+++ b/devtools/client/inspector/fonts/test/test_iframe.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+
+<style>
+ div{
+ font-family: "Times New Roman";
+ }
+</style>
+
+<body>
+ <div>Hello world</div>
+</body>