mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge fx-team to m-c.
This commit is contained in:
commit
7bcffdd7d4
@ -1146,6 +1146,9 @@ pref("devtools.editor.expandtab", true);
|
||||
// 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");
|
||||
|
@ -7022,8 +7022,8 @@ define("text!gcli/ui/intro.html", [], "\n" +
|
||||
" <p>\n" +
|
||||
" ${l10n.introTextCommands}\n" +
|
||||
" <span class=\"gcli-out-shortcut\" onclick=\"${onclick}\"\n" +
|
||||
" ondblclick=\"${ondblclick}\" data-command=\"help\">help</span>\n" +
|
||||
" ${l10n.introTextKeys2} <code>${l10n.introTextF1Escape}</code>.\n" +
|
||||
" ondblclick=\"${ondblclick}\" data-command=\"help\">help</span>${l10n.introTextKeys2}\n" +
|
||||
" <code>${l10n.introTextF1Escape}</code>.\n" +
|
||||
" </p>\n" +
|
||||
"\n" +
|
||||
" <button onclick=\"${onGotIt}\" if=\"${showHideButton}\">${l10n.introTextGo}</button>\n" +
|
||||
|
@ -47,13 +47,21 @@ function testCommands(dbg, cmd) {
|
||||
is(output.value, "dbg continue", "debugger continued");
|
||||
DeveloperToolbarTest.exec({
|
||||
typed: "dbg close",
|
||||
completed: false,
|
||||
blankOutput: true
|
||||
});
|
||||
|
||||
let target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
ok(!gDevTools.getToolbox(target),
|
||||
"Debugger was closed.");
|
||||
finish();
|
||||
let toolbox = gDevTools.getToolbox(target);
|
||||
if (!toolbox) {
|
||||
ok(true, "Debugger was closed.");
|
||||
finish();
|
||||
} else {
|
||||
toolbox.on("destroyed", function () {
|
||||
ok(true, "Debugger was closed.");
|
||||
finish();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -10,9 +10,11 @@ const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
this.EXPORTED_SYMBOLS = ["DebuggerPanel"];
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
||||
"resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DebuggerServer",
|
||||
"resource://gre/modules/devtools/dbg-server.jsm");
|
||||
|
||||
@ -37,13 +39,6 @@ DebuggerPanel.prototype = {
|
||||
|
||||
this._ensureOnlyOneRunningDebugger();
|
||||
|
||||
if (!this.target.isRemote) {
|
||||
if (!DebuggerServer.initialized) {
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors();
|
||||
}
|
||||
}
|
||||
|
||||
let onDebuggerLoaded = function () {
|
||||
this.panelWin.removeEventListener("Debugger:Loaded",
|
||||
onDebuggerLoaded, true);
|
||||
@ -62,7 +57,16 @@ DebuggerPanel.prototype = {
|
||||
this.panelWin.addEventListener("Debugger:Connected",
|
||||
onDebuggerConnected, true);
|
||||
|
||||
return deferred.promise;
|
||||
// Remote debugging gets the debuggee from a RemoteTarget object.
|
||||
if (this.target.isRemote) {
|
||||
this.panelWin._remoteFlag = true;
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
// Local debugging needs to convert the TabTarget to a RemoteTarget.
|
||||
return this.target.makeRemote().then(function success() {
|
||||
return deferred.promise;
|
||||
});
|
||||
},
|
||||
|
||||
// DevToolPanel API
|
||||
@ -71,6 +75,7 @@ DebuggerPanel.prototype = {
|
||||
get isReady() this._isReady,
|
||||
|
||||
destroy: function() {
|
||||
this.emit("destroyed");
|
||||
return Promise.resolve(null);
|
||||
},
|
||||
|
||||
|
@ -99,7 +99,7 @@ let DebuggerController = {
|
||||
/**
|
||||
* Prepares the hostname and port number for a remote debugger connection
|
||||
* and handles connection retries and timeouts.
|
||||
*
|
||||
* XXX: remove all this (bug 823577)
|
||||
* @return boolean
|
||||
* True if connection should proceed normally, false otherwise.
|
||||
*/
|
||||
@ -165,15 +165,11 @@ let DebuggerController = {
|
||||
window.dispatchEvent("Debugger:Connected");
|
||||
}
|
||||
|
||||
let client;
|
||||
|
||||
// Remote debugging gets the debuggee from a RemoteTarget object.
|
||||
if (this._target && this._target.isRemote) {
|
||||
window._isRemoteDebugger = true;
|
||||
|
||||
client = this.client = this._target.client;
|
||||
if (!window._isChromeDebugger) {
|
||||
let client = this.client = this._target.client;
|
||||
this._target.on("close", this._onTabDetached);
|
||||
this._target.on("navigate", this._onTabNavigated);
|
||||
this._target.on("will-navigate", this._onTabNavigated);
|
||||
|
||||
if (this._target.chrome) {
|
||||
let dbg = this._target.form.chromeDebugger;
|
||||
@ -184,25 +180,16 @@ let DebuggerController = {
|
||||
return;
|
||||
}
|
||||
|
||||
// Content or chrome debugging can connect directly to the debuggee.
|
||||
// TODO: convert this to use a TabTarget.
|
||||
let transport = window._isChromeDebugger
|
||||
? debuggerSocketConnect(Prefs.remoteHost, Prefs.remotePort)
|
||||
: DebuggerServer.connectPipe();
|
||||
// Chrome debugging needs to make the connection to the debuggee.
|
||||
let transport = debuggerSocketConnect(Prefs.remoteHost, Prefs.remotePort);
|
||||
|
||||
client = this.client = new DebuggerClient(transport);
|
||||
let client = this.client = new DebuggerClient(transport);
|
||||
client.addListener("tabNavigated", this._onTabNavigated);
|
||||
client.addListener("tabDetached", this._onTabDetached);
|
||||
|
||||
client.connect(function(aType, aTraits) {
|
||||
client.listTabs(function(aResponse) {
|
||||
if (window._isChromeDebugger) {
|
||||
let dbg = aResponse.chromeDebugger;
|
||||
this._startChromeDebugging(client, dbg, callback);
|
||||
} else {
|
||||
let tab = aResponse.tabs[aResponse.selected];
|
||||
this._startDebuggingTab(client, tab, callback);
|
||||
}
|
||||
this._startChromeDebugging(client, aResponse.chromeDebugger, callback);
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
},
|
||||
@ -218,8 +205,9 @@ let DebuggerController = {
|
||||
this.client.removeListener("tabNavigated", this._onTabNavigated);
|
||||
this.client.removeListener("tabDetached", this._onTabDetached);
|
||||
|
||||
// When remote debugging, the connection is closed by the RemoteTarget.
|
||||
if (!window._isRemoteDebugger) {
|
||||
// When debugging content or a remote instance, the connection is closed by
|
||||
// the RemoteTarget.
|
||||
if (window._isChromeDebugger) {
|
||||
this.client.close();
|
||||
}
|
||||
|
||||
|
13
browser/devtools/fontinspector/Makefile.in
Normal file
13
browser/devtools/fontinspector/Makefile.in
Normal file
@ -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
|
16
browser/devtools/fontinspector/font-inspector.css
Normal file
16
browser/devtools/fontinspector/font-inspector.css
Normal file
@ -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;
|
||||
}
|
226
browser/devtools/fontinspector/font-inspector.js
Normal file
226
browser/devtools/fontinspector/font-inspector.js
Normal file
@ -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();
|
||||
}
|
41
browser/devtools/fontinspector/font-inspector.xhtml
Normal file
41
browser/devtools/fontinspector/font-inspector.xhtml
Normal file
@ -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>
|
6
browser/devtools/fontinspector/moz.build
Normal file
6
browser/devtools/fontinspector/moz.build
Normal file
@ -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']
|
22
browser/devtools/fontinspector/test/Makefile.in
Normal file
22
browser/devtools/fontinspector/test/Makefile.in
Normal file
@ -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)
|
BIN
browser/devtools/fontinspector/test/browser_font.woff
Normal file
BIN
browser/devtools/fontinspector/test/browser_font.woff
Normal file
Binary file not shown.
@ -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>
|
89
browser/devtools/fontinspector/test/browser_fontinspector.js
Normal file
89
browser/devtools/fontinspector/test/browser_fontinspector.js
Normal file
@ -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();
|
||||
}
|
||||
}
|
5
browser/devtools/fontinspector/test/moz.build
Normal file
5
browser/devtools/fontinspector/test/moz.build
Normal file
@ -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/.
|
||||
|
@ -12,6 +12,11 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DebuggerServer",
|
||||
"resource://gre/modules/devtools/dbg-server.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DebuggerClient",
|
||||
"resource://gre/modules/devtools/dbg-client.jsm");
|
||||
|
||||
const targets = new WeakMap();
|
||||
|
||||
@ -21,8 +26,10 @@ const targets = new WeakMap();
|
||||
this.TargetFactory = {
|
||||
/**
|
||||
* Construct a Target
|
||||
* @param {XULTab} tab
|
||||
* The tab to use in creating a new target
|
||||
* @param {XULTab} | {Object} tab
|
||||
* The tab to use in creating a new target, or an options object in
|
||||
* case of remote targets.
|
||||
*
|
||||
* @return A target object
|
||||
*/
|
||||
forTab: function TF_forTab(tab) {
|
||||
@ -61,27 +68,7 @@ this.TargetFactory = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Construct a Target for a remote global
|
||||
* @param {Object} form
|
||||
* The serialized form of a debugging protocol actor.
|
||||
* @param {DebuggerClient} client
|
||||
* The debuger client instance to communicate with the server.
|
||||
* @param {boolean} chrome
|
||||
* A flag denoting that the debugging target is the remote process as a
|
||||
* whole and not a single tab.
|
||||
* @return A target object
|
||||
*/
|
||||
forRemote: function TF_forRemote(form, client, chrome) {
|
||||
let target = targets.get(form);
|
||||
if (target == null) {
|
||||
target = new RemoteTarget(form, client, chrome);
|
||||
targets.set(form, target);
|
||||
}
|
||||
return target;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get all of the targets known to some browser instance (local if null)
|
||||
* Get all of the targets known to the local browser instance
|
||||
* @return An array of target objects
|
||||
*/
|
||||
allTargets: function TF_allTargets() {
|
||||
@ -171,8 +158,16 @@ Object.defineProperty(Target.prototype, "version", {
|
||||
*/
|
||||
function TabTarget(tab) {
|
||||
EventEmitter.decorate(this);
|
||||
this._tab = tab;
|
||||
this._setupListeners();
|
||||
this.destroy = this.destroy.bind(this);
|
||||
this._handleThreadState = this._handleThreadState.bind(this);
|
||||
this.on("thread-resumed", this._handleThreadState);
|
||||
this.on("thread-paused", this._handleThreadState);
|
||||
// Only real tabs need initialization here. Placeholder objects for remote
|
||||
// targets will be initialized after a makeRemote method call.
|
||||
if (tab && !["client", "form", "chrome"].every(tab.hasOwnProperty, tab)) {
|
||||
this._tab = tab;
|
||||
this._setupListeners();
|
||||
}
|
||||
}
|
||||
|
||||
TabTarget.prototype = {
|
||||
@ -185,30 +180,99 @@ TabTarget.prototype = {
|
||||
return this._tab;
|
||||
},
|
||||
|
||||
get form() {
|
||||
return this._form;
|
||||
},
|
||||
|
||||
get client() {
|
||||
return this._client;
|
||||
},
|
||||
|
||||
get chrome() {
|
||||
return this._chrome;
|
||||
},
|
||||
|
||||
get window() {
|
||||
return this._tab.linkedBrowser.contentWindow;
|
||||
// Be extra careful here, since this may be called by HS_getHudByWindow
|
||||
// during shutdown.
|
||||
if (this._tab && this._tab.linkedBrowser) {
|
||||
return this._tab.linkedBrowser.contentWindow;
|
||||
}
|
||||
},
|
||||
|
||||
get name() {
|
||||
return this._tab.linkedBrowser.contentDocument.title;
|
||||
return this._tab ? this._tab.linkedBrowser.contentDocument.title :
|
||||
this._form.title;
|
||||
},
|
||||
|
||||
get url() {
|
||||
return this._tab.linkedBrowser.contentDocument.location.href;
|
||||
return this._tab ? this._tab.linkedBrowser.contentDocument.location.href :
|
||||
this._form.url;
|
||||
},
|
||||
|
||||
get isRemote() {
|
||||
return false;
|
||||
return !this.isLocalTab;
|
||||
},
|
||||
|
||||
get isLocalTab() {
|
||||
return true;
|
||||
return !!this._tab;
|
||||
},
|
||||
|
||||
get isThreadPaused() {
|
||||
return !!this._isThreadPaused;
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds remote protocol capabilities to the target, so that it can be used
|
||||
* for tools that support the Remote Debugging Protocol even for local
|
||||
* connections.
|
||||
*
|
||||
* @param object aOptions
|
||||
* An optional object containing remote connection options that is
|
||||
* supplied when connecting to another instance.
|
||||
*/
|
||||
makeRemote: function TabTarget_makeRemote(aOptions) {
|
||||
if (this._remote) {
|
||||
return this._remote.promise;
|
||||
}
|
||||
|
||||
this._remote = Promise.defer();
|
||||
|
||||
if (aOptions) {
|
||||
this._form = aOptions.form;
|
||||
this._client = aOptions.client;
|
||||
this._chrome = aOptions.chrome;
|
||||
} else {
|
||||
// Since a remote protocol connection will be made, let's start the
|
||||
// DebuggerServer here, once and for all tools.
|
||||
if (!DebuggerServer.initialized) {
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors();
|
||||
}
|
||||
|
||||
this._client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
// A local TabTarget will never perform chrome debugging.
|
||||
this._chrome = false;
|
||||
}
|
||||
|
||||
this._setupRemoteListeners();
|
||||
|
||||
if (aOptions) {
|
||||
// In the remote debugging case, the protocol connection will have been
|
||||
// already initialized in the connection screen code.
|
||||
this._remote.resolve(null);
|
||||
} else {
|
||||
this._client.connect(function(aType, aTraits) {
|
||||
this._client.listTabs(function(aResponse) {
|
||||
this._form = aResponse.tabs[aResponse.selected];
|
||||
this._remote.resolve(null);
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
return this._remote.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* Listen to the different events.
|
||||
*/
|
||||
@ -218,9 +282,27 @@ TabTarget.prototype = {
|
||||
this.tab.addEventListener("TabClose", this);
|
||||
this.tab.parentNode.addEventListener("TabSelect", this);
|
||||
this.tab.ownerDocument.defaultView.addEventListener("unload", this);
|
||||
this._handleThreadState = this._handleThreadState.bind(this);
|
||||
this.on("thread-resumed", this._handleThreadState);
|
||||
this.on("thread-paused", this._handleThreadState);
|
||||
},
|
||||
|
||||
/**
|
||||
* Setup listeners for remote debugging, updating existing ones as necessary.
|
||||
*/
|
||||
_setupRemoteListeners: function TabTarget__setupRemoteListeners() {
|
||||
// Reset any conflicting event handlers that were set before makeRemote().
|
||||
if (this._webProgressListener) {
|
||||
this._webProgressListener.destroy();
|
||||
}
|
||||
|
||||
this.client.addListener("tabDetached", this.destroy);
|
||||
|
||||
this._onTabNavigated = function onRemoteTabNavigated(aType, aPacket) {
|
||||
if (aPacket.state == "start") {
|
||||
this.emit("will-navigate", aPacket);
|
||||
} else {
|
||||
this.emit("navigate", aPacket);
|
||||
}
|
||||
}.bind(this);
|
||||
this.client.addListener("tabNavigated", this._onTabNavigated);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -260,28 +342,66 @@ TabTarget.prototype = {
|
||||
* Target is not alive anymore.
|
||||
*/
|
||||
destroy: function() {
|
||||
if (!this._destroyed) {
|
||||
this._destroyed = true;
|
||||
// If several things call destroy then we give them all the same
|
||||
// destruction promise so we're sure to destroy only once
|
||||
if (this._destroyer) {
|
||||
return this._destroyer.promise;
|
||||
}
|
||||
|
||||
this.tab.linkedBrowser.removeProgressListener(this._webProgressListener)
|
||||
this._webProgressListener.target = null;
|
||||
this._webProgressListener = null;
|
||||
this.tab.ownerDocument.defaultView.removeEventListener("unload", this);
|
||||
this.tab.removeEventListener("TabClose", this);
|
||||
this.tab.parentNode.removeEventListener("TabSelect", this);
|
||||
this.off("thread-resumed", this._handleThreadState);
|
||||
this.off("thread-paused", this._handleThreadState);
|
||||
this.emit("close");
|
||||
this._destroyer = Promise.defer();
|
||||
|
||||
// Before taking any action, notify listeners that destruction is imminent.
|
||||
this.emit("close");
|
||||
|
||||
// First of all, do cleanup tasks that pertain to both remoted and
|
||||
// non-remoted targets.
|
||||
this.off("thread-resumed", this._handleThreadState);
|
||||
this.off("thread-paused", this._handleThreadState);
|
||||
|
||||
if (this._tab) {
|
||||
this._tab.ownerDocument.defaultView.removeEventListener("unload", this);
|
||||
this._tab.removeEventListener("TabClose", this);
|
||||
this._tab.parentNode.removeEventListener("TabSelect", this);
|
||||
}
|
||||
|
||||
// If this target was not remoted, the promise will be resolved before the
|
||||
// function returns.
|
||||
// if (!this._remote) {
|
||||
if (this._tab && !this._client) {
|
||||
if (this._webProgressListener) {
|
||||
this._webProgressListener.destroy();
|
||||
}
|
||||
|
||||
targets.delete(this._tab);
|
||||
this._tab = null;
|
||||
this._client = null;
|
||||
this._form = null;
|
||||
this._remote = null;
|
||||
|
||||
this._destroyer.resolve(null);
|
||||
} else if (this._client) {
|
||||
// If, on the other hand, this target was remoted, the promise will be
|
||||
// resolved after the remote connection is closed.
|
||||
this.client.removeListener("tabNavigated", this._onTabNavigated);
|
||||
this.client.removeListener("tabDetached", this.destroy);
|
||||
|
||||
this._client.close(function onClosed() {
|
||||
let key = this._tab ? this._tab : this._form;
|
||||
targets.delete(key);
|
||||
this._client = null;
|
||||
this._tab = null;
|
||||
this._form = null;
|
||||
this._remote = null;
|
||||
|
||||
this._destroyer.resolve(null);
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
return Promise.resolve(null);
|
||||
return this._destroyer.promise;
|
||||
},
|
||||
|
||||
toString: function() {
|
||||
return 'TabTarget:' + this.tab;
|
||||
return 'TabTarget:' + (this._tab ? this._tab : (this._form && this._form.actor));
|
||||
},
|
||||
};
|
||||
|
||||
@ -322,13 +442,24 @@ TabWebProgressListener.prototype = {
|
||||
onSecurityChange: function() {},
|
||||
onStatusChange: function() {},
|
||||
|
||||
onLocationChange: function TwPL_onLocationChange(webProgress, request, URI, flags) {
|
||||
onLocationChange: function TWPL_onLocationChange(webProgress, request, URI, flags) {
|
||||
if (this.target &&
|
||||
!(flags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT)) {
|
||||
let window = webProgress.DOMWindow;
|
||||
this.target.emit("navigate", window);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroy the progress listener instance.
|
||||
*/
|
||||
destroy: function TWPL_destroy() {
|
||||
if (this.target.tab) {
|
||||
this.target.tab.linkedBrowser.removeProgressListener(this);
|
||||
}
|
||||
this.target._webProgressListener = null;
|
||||
this.target = null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -412,101 +543,3 @@ WindowTarget.prototype = {
|
||||
return 'WindowTarget:' + this.window;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* A RemoteTarget represents a page living in a remote Firefox instance.
|
||||
*/
|
||||
function RemoteTarget(form, client, chrome) {
|
||||
EventEmitter.decorate(this);
|
||||
this._client = client;
|
||||
this._form = form;
|
||||
this._chrome = chrome;
|
||||
this._setupListeners();
|
||||
}
|
||||
|
||||
RemoteTarget.prototype = {
|
||||
supports: supports,
|
||||
get version() getVersion(),
|
||||
|
||||
get isRemote() true,
|
||||
|
||||
get chrome() this._chrome,
|
||||
|
||||
get name() this._form.title,
|
||||
|
||||
get url() this._form.url,
|
||||
|
||||
get client() this._client,
|
||||
|
||||
get form() this._form,
|
||||
|
||||
get isLocalTab() false,
|
||||
|
||||
get isThreadPaused() !!this._isThreadPaused,
|
||||
|
||||
/**
|
||||
* Listen to the different events.
|
||||
*/
|
||||
_setupListeners: function() {
|
||||
this.destroy = this.destroy.bind(this);
|
||||
this.client.addListener("tabDetached", this.destroy);
|
||||
|
||||
this._onTabNavigated = function onRemoteTabNavigated(aType, aPacket) {
|
||||
if (aPacket.state == "start") {
|
||||
this.emit("will-navigate", aPacket);
|
||||
} else {
|
||||
this.emit("navigate", aPacket);
|
||||
}
|
||||
}.bind(this);
|
||||
this.client.addListener("tabNavigated", this._onTabNavigated);
|
||||
|
||||
this._handleThreadState = this._handleThreadState.bind(this);
|
||||
this.on("thread-resumed", this._handleThreadState);
|
||||
this.on("thread-paused", this._handleThreadState);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle script status.
|
||||
*/
|
||||
_handleThreadState: function(event) {
|
||||
switch (event) {
|
||||
case "thread-resumed":
|
||||
this._isThreadPaused = false;
|
||||
break;
|
||||
case "thread-paused":
|
||||
this._isThreadPaused = true;
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Target is not alive anymore.
|
||||
*/
|
||||
destroy: function RT_destroy() {
|
||||
// If several things call destroy then we give them all the same
|
||||
// destruction promise so we're sure to destroy only once
|
||||
if (this._destroyer) {
|
||||
return this._destroyer.promise;
|
||||
}
|
||||
|
||||
this._destroyer = Promise.defer();
|
||||
|
||||
this.client.removeListener("tabNavigated", this._onTabNavigated);
|
||||
this.client.removeListener("tabDetached", this.destroy);
|
||||
|
||||
this._client.close(function onClosed() {
|
||||
this._client = null;
|
||||
this.off("thread-resumed", this._handleThreadState);
|
||||
this.off("thread-paused", this._handleThreadState);
|
||||
this.emit("close");
|
||||
|
||||
this._destroyer.resolve(null);
|
||||
}.bind(this));
|
||||
|
||||
return this._destroyer.promise;
|
||||
},
|
||||
|
||||
toString: function() {
|
||||
return 'RemoteTarget:' + this.form.actor;
|
||||
},
|
||||
};
|
||||
|
@ -126,7 +126,7 @@ this.Toolbox = function Toolbox(target, selectedTool, hostType) {
|
||||
this._toolUnregistered = this._toolUnregistered.bind(this);
|
||||
this.destroy = this.destroy.bind(this);
|
||||
|
||||
this._target.once("close", this.destroy);
|
||||
this._target.on("close", this.destroy);
|
||||
|
||||
if (!hostType) {
|
||||
hostType = Services.prefs.getCharPref(this._prefs.LAST_HOST);
|
||||
@ -432,12 +432,13 @@ Toolbox.prototype = {
|
||||
* The id of the tool to switch to
|
||||
*/
|
||||
selectTool: function TBOX_selectTool(id) {
|
||||
if (this._currentToolId == id) {
|
||||
return;
|
||||
}
|
||||
|
||||
let deferred = Promise.defer();
|
||||
|
||||
if (this._currentToolId == id) {
|
||||
// Return the existing panel in order to have a consistent return value.
|
||||
return Promise.resolve(this._toolPanels.get(id));
|
||||
}
|
||||
|
||||
if (!this.isReady) {
|
||||
throw new Error("Can't select tool, wait for toolbox 'ready' event");
|
||||
}
|
||||
@ -686,13 +687,10 @@ Toolbox.prototype = {
|
||||
this.off("select", this._refreshHostTitle);
|
||||
this.off("host-changed", this._refreshHostTitle);
|
||||
|
||||
let outstanding = [];
|
||||
gDevTools.off("tool-registered", this._toolRegistered);
|
||||
gDevTools.off("tool-unregistered", this._toolUnregistered);
|
||||
|
||||
// Remote targets need to be notified that the toolbox is being torn down.
|
||||
if (this._target && this._target.isRemote) {
|
||||
outstanding.push(this._target.destroy());
|
||||
}
|
||||
this._target = null;
|
||||
let outstanding = [];
|
||||
|
||||
for (let [id, panel] of this._toolPanels) {
|
||||
outstanding.push(panel.destroy());
|
||||
@ -700,8 +698,13 @@ Toolbox.prototype = {
|
||||
|
||||
outstanding.push(this._host.destroy());
|
||||
|
||||
gDevTools.off("tool-registered", this._toolRegistered);
|
||||
gDevTools.off("tool-unregistered", this._toolUnregistered);
|
||||
// Targets need to be notified that the toolbox is being torn down, so that
|
||||
// remote protocol connections can be gracefully terminated.
|
||||
if (this._target) {
|
||||
this._target.off("close", this.destroy);
|
||||
outstanding.push(this._target.destroy());
|
||||
}
|
||||
this._target = null;
|
||||
|
||||
Promise.all(outstanding).then(function() {
|
||||
this.emit("destroyed");
|
||||
|
@ -164,7 +164,14 @@ function handleConnectionTimeout() {
|
||||
* Opens the toolbox.
|
||||
*/
|
||||
function openToolbox(form, chrome=false) {
|
||||
let target = TargetFactory.forRemote(form, gClient, chrome);
|
||||
gDevTools.showToolbox(target, "webconsole", Toolbox.HostType.WINDOW);
|
||||
window.close();
|
||||
let options = {
|
||||
form: form,
|
||||
client: gClient,
|
||||
chrome: chrome
|
||||
};
|
||||
let target = TargetFactory.forTab(options);
|
||||
target.makeRemote(options).then(function() {
|
||||
gDevTools.showToolbox(target, "webconsole", Toolbox.HostType.WINDOW);
|
||||
window.close();
|
||||
});
|
||||
}
|
||||
|
@ -51,7 +51,10 @@ function selectAndCheckById(id) {
|
||||
|
||||
function testToggle() {
|
||||
toolbox.once("destroyed", function() {
|
||||
gDevTools.showToolbox(target, "styleeditor").then(function() {
|
||||
// Cannot reuse a target after it's destroyed.
|
||||
target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
gDevTools.showToolbox(target, "styleeditor").then(function(aToolbox) {
|
||||
toolbox = aToolbox;
|
||||
is(toolbox.currentToolId, "styleeditor", "The style editor is selected");
|
||||
finishUp();
|
||||
});
|
||||
@ -61,9 +64,10 @@ function testToggle() {
|
||||
}
|
||||
|
||||
function finishUp() {
|
||||
toolbox.destroy();
|
||||
toolbox = null;
|
||||
target = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
toolbox.destroy().then(function() {
|
||||
toolbox = null;
|
||||
target = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
@ -41,7 +41,9 @@ function onVisible() {
|
||||
|
||||
function onWillNavigate(event, request) {
|
||||
ok(true, "will-navigate event received");
|
||||
target.once("navigate", onNavigate);
|
||||
// Wait for navigation handling to complete before removing the tab, in order
|
||||
// to avoid triggering assertions.
|
||||
target.once("navigate", executeSoon.bind(null, onNavigate));
|
||||
}
|
||||
|
||||
function onNavigate() {
|
||||
|
@ -90,12 +90,14 @@ function testToolSelect()
|
||||
function testDestroy()
|
||||
{
|
||||
toolbox.destroy().then(function() {
|
||||
target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
gDevTools.showToolbox(target).then(testRememberHost);
|
||||
});
|
||||
}
|
||||
|
||||
function testRememberHost()
|
||||
function testRememberHost(aToolbox)
|
||||
{
|
||||
toolbox = aToolbox;
|
||||
// last host was the window - make sure it's the same when re-opening
|
||||
is(toolbox.hostType, Toolbox.HostType.WINDOW, "host remembered");
|
||||
|
||||
@ -123,8 +125,9 @@ function cleanup()
|
||||
{
|
||||
Services.prefs.setCharPref("devtools.toolbox.host", Toolbox.HostType.BOTTOM);
|
||||
|
||||
toolbox.destroy();
|
||||
DevTools = Toolbox = toolbox = target = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
toolbox.destroy().then(function() {
|
||||
DevTools = Toolbox = toolbox = target = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
@ -66,9 +66,10 @@ function selectCB(event, id) {
|
||||
}
|
||||
|
||||
function tidyUp() {
|
||||
toolbox.destroy();
|
||||
gBrowser.removeCurrentTab();
|
||||
toolbox.destroy().then(function() {
|
||||
gBrowser.removeCurrentTab();
|
||||
|
||||
toolbox = toolIDs = idIndex = Toolbox = null;
|
||||
finish();
|
||||
toolbox = toolIDs = idIndex = Toolbox = null;
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
@ -54,23 +54,32 @@ function test() {
|
||||
|
||||
// destroy toolbox, create new one hosted in a window (with a
|
||||
// different tool id), and check title
|
||||
.then(function () toolbox.destroy())
|
||||
.then(function () gDevTools.showToolbox(target, null,
|
||||
Toolbox.HostType.WINDOW))
|
||||
.then(function (aToolbox) { toolbox = aToolbox; })
|
||||
.then(function () toolbox.selectTool(TOOL_ID_1))
|
||||
.then(checkTitle.bind(null, LABEL_1, URL_2,
|
||||
"toolbox destroyed and recreated"))
|
||||
|
||||
// clean up
|
||||
.then(function () toolbox.destroy())
|
||||
.then(function () {
|
||||
toolbox = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
Services.prefs.clearUserPref("devtools.toolbox.host");
|
||||
Services.prefs.clearUserPref("devtools.toolbox.selectedTool");
|
||||
Services.prefs.clearUserPref("devtools.toolbox.sideEnabled");
|
||||
finish();
|
||||
// Give the tools a chance to handle the navigation event before
|
||||
// destroying the toolbox.
|
||||
executeSoon(function() {
|
||||
toolbox.destroy()
|
||||
.then(function () {
|
||||
// After destroying the toolbox, a fresh target is required.
|
||||
target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
return gDevTools.showToolbox(target, null, Toolbox.HostType.WINDOW);
|
||||
})
|
||||
.then(function (aToolbox) { toolbox = aToolbox; })
|
||||
.then(function () toolbox.selectTool(TOOL_ID_1))
|
||||
.then(checkTitle.bind(null, LABEL_1, URL_2,
|
||||
"toolbox destroyed and recreated"))
|
||||
|
||||
// clean up
|
||||
.then(function () toolbox.destroy())
|
||||
.then(function () {
|
||||
toolbox = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
Services.prefs.clearUserPref("devtools.toolbox.host");
|
||||
Services.prefs.clearUserPref("devtools.toolbox.selectedTool");
|
||||
Services.prefs.clearUserPref("devtools.toolbox.sideEnabled");
|
||||
finish();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -219,6 +219,12 @@ InspectorPanel.prototype = {
|
||||
"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);
|
||||
@ -412,6 +418,7 @@ InspectorPanel.prototype = {
|
||||
this.nodemenu = null;
|
||||
this.searchBox = null;
|
||||
this.highlighter = null;
|
||||
this._searchResults = null;
|
||||
|
||||
return Promise.resolve(null);
|
||||
},
|
||||
|
@ -20,7 +20,7 @@ function createDocument()
|
||||
'solely to provide some things to test the inspector initialization.</p>\n' +
|
||||
'If you are reading this, you should go do something else instead. Maybe ' +
|
||||
'read a book. Or better yet, write some test-cases for another bit of code. ' +
|
||||
'<span style="{font-style: italic}">Maybe more inspector test-cases!</span></p>\n' +
|
||||
'<span style="{font-style: italic}">Inspector\'s!</span></p>\n' +
|
||||
'<p id="closing">end transmission</p>\n' +
|
||||
'</div>';
|
||||
doc.title = "Inspector Initialization Test";
|
||||
|
@ -19,6 +19,9 @@ browser.jar:
|
||||
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)
|
||||
|
@ -104,7 +104,7 @@ LayoutView.prototype = {
|
||||
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;
|
||||
|
@ -644,7 +644,7 @@ MarkupView.prototype = {
|
||||
delete this._boundFocus;
|
||||
|
||||
this._frame.contentWindow.removeEventListener("scroll", this._boundUpdatePreview, true);
|
||||
this._frame.contentWindow.removeEventListener("resize", this._boundUpdatePreview, true);
|
||||
this._frame.contentWindow.removeEventListener("resize", this._boundResizePreview, true);
|
||||
this._frame.contentWindow.removeEventListener("overflow", this._boundResizePreview, true);
|
||||
this._frame.contentWindow.removeEventListener("underflow", this._boundResizePreview, true);
|
||||
delete this._boundUpdatePreview;
|
||||
|
@ -19,4 +19,5 @@ DIRS += [
|
||||
'responsivedesign',
|
||||
'framework',
|
||||
'profiler',
|
||||
'fontinspector',
|
||||
]
|
||||
|
@ -23,19 +23,6 @@ XPCOMUtils.defineLazyGetter(this, "DebuggerServer", function () {
|
||||
* DebuggerServer.
|
||||
*/
|
||||
function ProfilerConnection(client) {
|
||||
if (!DebuggerServer.initialized) {
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors();
|
||||
}
|
||||
|
||||
this.isRemote = true;
|
||||
|
||||
if (!client) {
|
||||
let transport = DebuggerServer.connectPipe();
|
||||
client = new DebuggerClient(transport);
|
||||
this.isRemote = false;
|
||||
}
|
||||
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
@ -49,22 +36,10 @@ ProfilerConnection.prototype = {
|
||||
* Function to be called once we're connected to the client.
|
||||
*/
|
||||
connect: function PCn_connect(aCallback) {
|
||||
let client = this.client;
|
||||
|
||||
let listTabs = function () {
|
||||
client.listTabs(function (aResponse) {
|
||||
this.actor = aResponse.profilerActor;
|
||||
aCallback();
|
||||
}.bind(this));
|
||||
}.bind(this);
|
||||
|
||||
if (this.isRemote) {
|
||||
return void listTabs();
|
||||
}
|
||||
|
||||
client.connect(function (aType, aTraits) {
|
||||
listTabs();
|
||||
});
|
||||
this.client.listTabs(function (aResponse) {
|
||||
this.actor = aResponse.profilerActor;
|
||||
aCallback();
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
@ -129,9 +104,7 @@ ProfilerConnection.prototype = {
|
||||
* Cleanup.
|
||||
*/
|
||||
destroy: function PCn_destroy() {
|
||||
this.client.close(function () {
|
||||
this.client = null;
|
||||
}.bind(this));
|
||||
this.client = null;
|
||||
}
|
||||
};
|
||||
|
||||
@ -139,14 +112,13 @@ ProfilerConnection.prototype = {
|
||||
* Object defining the profiler controller components.
|
||||
*/
|
||||
function ProfilerController(target) {
|
||||
let client;
|
||||
|
||||
if (target.isRemote) {
|
||||
client = target.client;
|
||||
this.profiler = new ProfilerConnection(target.client);
|
||||
// Chrome debugging targets have already obtained a reference to the profiler
|
||||
// actor.
|
||||
this._connected = !!target.chrome;
|
||||
if (target.chrome) {
|
||||
this.profiler.actor = target.form.profilerActor;
|
||||
}
|
||||
|
||||
this.profiler = new ProfilerConnection(client);
|
||||
this._connected = false;
|
||||
}
|
||||
|
||||
ProfilerController.prototype = {
|
||||
@ -160,7 +132,7 @@ ProfilerController.prototype = {
|
||||
*/
|
||||
connect: function (aCallback) {
|
||||
if (this._connected) {
|
||||
aCallback();
|
||||
return void aCallback();
|
||||
}
|
||||
|
||||
this.profiler.connect(function onConnect() {
|
||||
|
@ -9,12 +9,14 @@ const Cu = Components.utils;
|
||||
Cu.import("resource:///modules/devtools/gDevTools.jsm");
|
||||
Cu.import("resource:///modules/devtools/ProfilerController.jsm");
|
||||
Cu.import("resource:///modules/devtools/ProfilerHelpers.jsm");
|
||||
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["ProfilerPanel"];
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
||||
"resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DebuggerServer",
|
||||
"resource://gre/modules/devtools/dbg-server.jsm");
|
||||
|
||||
@ -205,7 +207,6 @@ function ProfilerPanel(frame, toolbox) {
|
||||
this.window = frame.window;
|
||||
this.document = frame.document;
|
||||
this.target = toolbox.target;
|
||||
this.controller = new ProfilerController(this.target);
|
||||
|
||||
this.profiles = new Map();
|
||||
this._uid = 0;
|
||||
@ -256,23 +257,39 @@ ProfilerPanel.prototype = {
|
||||
* @return Promise
|
||||
*/
|
||||
open: function PP_open() {
|
||||
let deferred = Promise.defer();
|
||||
let promise;
|
||||
// Local profiling needs to make the target remote.
|
||||
if (!this.target.isRemote) {
|
||||
promise = this.target.makeRemote();
|
||||
} else {
|
||||
promise = Promise.resolve(this.target);
|
||||
}
|
||||
|
||||
this.controller.connect(function onConnect() {
|
||||
let create = this.document.getElementById("profiler-create");
|
||||
create.addEventListener("click", this.createProfile.bind(this), false);
|
||||
create.removeAttribute("disabled");
|
||||
return promise
|
||||
.then(function(target) {
|
||||
let deferred = Promise.defer();
|
||||
this.controller = new ProfilerController(this.target);
|
||||
|
||||
let profile = this.createProfile();
|
||||
this.switchToProfile(profile, function () {
|
||||
this.isReady = true;
|
||||
this.emit("ready");
|
||||
this.controller.connect(function onConnect() {
|
||||
let create = this.document.getElementById("profiler-create");
|
||||
create.addEventListener("click", this.createProfile.bind(this), false);
|
||||
create.removeAttribute("disabled");
|
||||
|
||||
deferred.resolve(this);
|
||||
let profile = this.createProfile();
|
||||
this.switchToProfile(profile, function () {
|
||||
this.isReady = true;
|
||||
this.emit("ready");
|
||||
|
||||
deferred.resolve(this);
|
||||
}.bind(this))
|
||||
}.bind(this));
|
||||
|
||||
return deferred.promise;
|
||||
}.bind(this))
|
||||
}.bind(this));
|
||||
|
||||
return deferred.promise;
|
||||
.then(null, function onError(reason) {
|
||||
Cu.reportError("ProfilerPanel open failed. " +
|
||||
reason.error + ": " + reason.message);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -53,10 +53,12 @@ gcli.addCommand({
|
||||
mgr.on("off", aChangeHandler);
|
||||
},
|
||||
offChange: function(aTarget, aChangeHandler) {
|
||||
let browserWindow = aTarget.tab.ownerDocument.defaultView;
|
||||
let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
|
||||
mgr.off("on", aChangeHandler);
|
||||
mgr.off("off", aChangeHandler);
|
||||
if (aTarget.tab) {
|
||||
let browserWindow = aTarget.tab.ownerDocument.defaultView;
|
||||
let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
|
||||
mgr.off("on", aChangeHandler);
|
||||
mgr.off("off", aChangeHandler);
|
||||
}
|
||||
},
|
||||
},
|
||||
exec: gcli_cmd_resize
|
||||
|
@ -57,9 +57,11 @@ gcli.addCommand({
|
||||
tilt.on("change", aChangeHandler);
|
||||
},
|
||||
offChange: function(aTarget, aChangeHandler) {
|
||||
let browserWindow = aTarget.tab.ownerDocument.defaultView;
|
||||
let tilt = TiltManager.getTiltForBrowser(browserWindow);
|
||||
tilt.off("change", aChangeHandler);
|
||||
if (aTarget.tab) {
|
||||
let browserWindow = aTarget.tab.ownerDocument.defaultView;
|
||||
let tilt = TiltManager.getTiltForBrowser(browserWindow);
|
||||
tilt.off("change", aChangeHandler);
|
||||
}
|
||||
},
|
||||
},
|
||||
exec: function(args, context) {
|
||||
|
@ -225,7 +225,9 @@ AutocompletePopup.prototype = {
|
||||
*/
|
||||
set selectedIndex(aIndex) {
|
||||
this._list.selectedIndex = aIndex;
|
||||
this._list.ensureIndexIsVisible(this._list.selectedIndex);
|
||||
if (this._list.ensureIndexIsVisible) {
|
||||
this._list.ensureIndexIsVisible(this._list.selectedIndex);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -237,12 +237,11 @@ WebConsole.prototype = {
|
||||
if ((win = this.iframe.contentWindow) &&
|
||||
(doc = win.document) &&
|
||||
doc.readyState == "complete") {
|
||||
this.iframe.addEventListener("load", onIframeLoad, true);
|
||||
}
|
||||
else {
|
||||
initUI();
|
||||
}
|
||||
|
||||
else {
|
||||
this.iframe.addEventListener("load", onIframeLoad, true);
|
||||
}
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
@ -344,6 +343,67 @@ WebConsole.prototype = {
|
||||
this.viewSource(aSourceURL, aSourceLine);
|
||||
},
|
||||
|
||||
/**
|
||||
* Tries to open a JavaScript file related to the web page for the web console
|
||||
* instance in the Script Debugger. If the file is not found, it is opened in
|
||||
* source view instead.
|
||||
*
|
||||
* @param string aSourceURL
|
||||
* The URL of the file.
|
||||
* @param integer aSourceLine
|
||||
* The line number which you want to place the caret.
|
||||
*/
|
||||
viewSourceInDebugger:
|
||||
function WC_viewSourceInDebugger(aSourceURL, aSourceLine)
|
||||
{
|
||||
let self = this;
|
||||
let panelWin = null;
|
||||
let debuggerWasOpen = true;
|
||||
let toolbox = gDevTools.getToolbox(this.target);
|
||||
|
||||
if (!toolbox.getPanel("jsdebugger")) {
|
||||
debuggerWasOpen = false;
|
||||
let toolboxWin = toolbox.doc.defaultView;
|
||||
toolboxWin.addEventListener("Debugger:AfterSourcesAdded",
|
||||
function afterSourcesAdded() {
|
||||
toolboxWin.removeEventListener("Debugger:AfterSourcesAdded",
|
||||
afterSourcesAdded);
|
||||
loadScript();
|
||||
});
|
||||
}
|
||||
|
||||
toolbox.selectTool("jsdebugger").then(function onDebuggerOpen(dbg) {
|
||||
panelWin = dbg.panelWin;
|
||||
if (debuggerWasOpen) {
|
||||
loadScript();
|
||||
}
|
||||
});
|
||||
|
||||
function loadScript() {
|
||||
let debuggerView = panelWin.DebuggerView;
|
||||
if (!debuggerView.Sources.containsValue(aSourceURL)) {
|
||||
toolbox.selectTool("webconsole");
|
||||
self.viewSource(aSourceURL, aSourceLine);
|
||||
return;
|
||||
}
|
||||
if (debuggerWasOpen && debuggerView.Sources.selectedValue == aSourceURL) {
|
||||
debuggerView.editor.setCaretPosition(aSourceLine - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
panelWin.addEventListener("Debugger:SourceShown", onSource, false);
|
||||
debuggerView.Sources.preferredSource = aSourceURL;
|
||||
}
|
||||
|
||||
function onSource(aEvent) {
|
||||
if (aEvent.detail.url != aSourceURL) {
|
||||
return;
|
||||
}
|
||||
panelWin.removeEventListener("Debugger:SourceShown", onSource, false);
|
||||
panelWin.DebuggerView.editor.setCaretPosition(aSourceLine - 1);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroy the object. Call this method to avoid memory leaks when the Web
|
||||
* Console is closed.
|
||||
@ -359,8 +419,6 @@ WebConsole.prototype = {
|
||||
|
||||
delete HUDService.hudReferences[this.hudId];
|
||||
|
||||
let tabWindow = this.target.isLocalTab ? this.target.window : null;
|
||||
|
||||
this._destroyer = Promise.defer();
|
||||
|
||||
let popupset = this.mainPopupSet;
|
||||
@ -371,15 +429,15 @@ WebConsole.prototype = {
|
||||
|
||||
let onDestroy = function WC_onDestroyUI() {
|
||||
try {
|
||||
let tabWindow = this.target.isLocalTab ? this.target.window : null;
|
||||
tabWindow && tabWindow.focus();
|
||||
}
|
||||
catch (ex) {
|
||||
// Tab focus can fail if the tab is closed.
|
||||
// Tab focus can fail if the tab or target is closed.
|
||||
}
|
||||
|
||||
let id = WebConsoleUtils.supportsString(this.hudId);
|
||||
Services.obs.notifyObservers(id, "web-console-destroyed", null);
|
||||
|
||||
this._destroyer.resolve(null);
|
||||
}.bind(this);
|
||||
|
||||
|
@ -10,6 +10,9 @@ const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
||||
"resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "HUDService",
|
||||
"resource:///modules/HUDService.jsm");
|
||||
|
||||
@ -38,17 +41,31 @@ WebConsolePanel.prototype = {
|
||||
{
|
||||
let parentDoc = this._toolbox.doc;
|
||||
let iframe = parentDoc.getElementById("toolbox-panel-iframe-webconsole");
|
||||
let promise = HUDService.openWebConsole(this.target, iframe);
|
||||
let promise;
|
||||
|
||||
return promise.then(function onSuccess(aWebConsole) {
|
||||
this.hud = aWebConsole;
|
||||
this._isReady = true;
|
||||
this.emit("ready");
|
||||
return this;
|
||||
}.bind(this), function onError(aReason) {
|
||||
Cu.reportError("WebConsolePanel open failed. " +
|
||||
aReason.error + ": " + aReason.message);
|
||||
});
|
||||
// Local debugging needs to make the target remote.
|
||||
if (!this.target.isRemote) {
|
||||
promise = this.target.makeRemote();
|
||||
} else {
|
||||
promise = Promise.resolve(this.target);
|
||||
}
|
||||
|
||||
return promise
|
||||
.then(function(aTarget) {
|
||||
this._frameWindow._remoteTarget = aTarget;
|
||||
return HUDService.openWebConsole(this.target, iframe);
|
||||
}.bind(this))
|
||||
.then(function onSuccess(aWebConsole) {
|
||||
this.hud = aWebConsole;
|
||||
this._isReady = true;
|
||||
this.emit("ready");
|
||||
return this;
|
||||
}.bind(this), function onError(aReason) {
|
||||
let msg = "WebConsolePanel open failed. " +
|
||||
aReason.error + ": " + aReason.message;
|
||||
dump(msg + "\n");
|
||||
Cu.reportError(msg);
|
||||
});
|
||||
},
|
||||
|
||||
get target() this._toolbox.target,
|
||||
|
@ -104,6 +104,7 @@ MOCHITEST_BROWSER_FILES = \
|
||||
browser_webconsole_bug_622303_persistent_filters.js \
|
||||
browser_webconsole_bug_770099_bad_policyuri.js \
|
||||
browser_webconsole_bug_770099_violation.js \
|
||||
browser_webconsole_bug_766001_JS_Console_in_Debugger.js \
|
||||
browser_webconsole_bug_782653_CSS_links_in_Style_Editor.js \
|
||||
browser_cached_messages.js \
|
||||
browser_bug664688_sandbox_update_after_navigation.js \
|
||||
@ -210,6 +211,9 @@ MOCHITEST_BROWSER_FILES += \
|
||||
test-result-format-as-string.html \
|
||||
test-bug-737873-mixedcontent.html \
|
||||
test-repeated-messages.html \
|
||||
test-bug-766001-console-log.js \
|
||||
test-bug-766001-js-console-links.html \
|
||||
test-bug-766001-js-errors.js \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -77,21 +77,21 @@ function tab2Loaded(aEvent) {
|
||||
|
||||
try {
|
||||
let target1 = TargetFactory.forTab(tab1);
|
||||
gDevTools.closeToolbox(target1);
|
||||
gDevTools.closeToolbox(target1).then(function() {
|
||||
try {
|
||||
let target2 = TargetFactory.forTab(tab2);
|
||||
gDevTools.closeToolbox(target2);
|
||||
}
|
||||
catch (ex) {
|
||||
ok(false, "gDevTools.closeToolbox(target2) exception: " + ex);
|
||||
noErrors = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (ex) {
|
||||
ok(false, "gDevTools.closeToolbox(target1) exception: " + ex);
|
||||
noErrors = false;
|
||||
}
|
||||
|
||||
try {
|
||||
let target2 = TargetFactory.forTab(tab2);
|
||||
gDevTools.closeToolbox(target2);
|
||||
}
|
||||
catch (ex) {
|
||||
ok(false, "gDevTools.closeToolbox(target2) exception: " + ex);
|
||||
noErrors = false;
|
||||
}
|
||||
}
|
||||
|
||||
function testEnd() {
|
||||
|
@ -0,0 +1,113 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test" +
|
||||
"/test-bug-766001-js-console-links.html";
|
||||
|
||||
let nodes, dbg, toolbox, target, index = 0, src, line;
|
||||
|
||||
function test()
|
||||
{
|
||||
expectUncaughtException();
|
||||
requestLongerTimeout(2);
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole(null, testViewSource);
|
||||
}, true);
|
||||
}
|
||||
|
||||
function testViewSource(aHud)
|
||||
{
|
||||
registerCleanupFunction(function() {
|
||||
nodes = dbg = toolbox = target = index = src = line = null;
|
||||
});
|
||||
|
||||
let JSSelector = ".webconsole-msg-exception .webconsole-location";
|
||||
let consoleSelector = ".webconsole-msg-console .webconsole-location";
|
||||
|
||||
waitForSuccess({
|
||||
name: "find the location node",
|
||||
validatorFn: function()
|
||||
{
|
||||
return aHud.outputNode.querySelector(JSSelector) &&
|
||||
aHud.outputNode.querySelector(consoleSelector);
|
||||
},
|
||||
successFn: function()
|
||||
{
|
||||
nodes = [aHud.outputNode.querySelector(JSSelector),
|
||||
aHud.outputNode.querySelector(consoleSelector)];
|
||||
|
||||
target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
toolbox = gDevTools.getToolbox(target);
|
||||
toolbox.once("jsdebugger-selected", checkLineAndClickNext);
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" }, nodes[index%2]);
|
||||
},
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
|
||||
function checkLineAndClickNext(aEvent, aPanel)
|
||||
{
|
||||
if (index == 3) {
|
||||
finishTest();
|
||||
return;
|
||||
}
|
||||
info(aEvent + " event fired for index " + index);
|
||||
|
||||
dbg = aPanel;
|
||||
|
||||
src = nodes[index%2].getAttribute("title");
|
||||
ok(src, "source url found for index " + index);
|
||||
line = nodes[index%2].sourceLine;
|
||||
ok(line, "found source line for index " + index);
|
||||
|
||||
info("Waiting for the correct script to be selected for index " + index);
|
||||
dbg.panelWin.addEventListener("Debugger:SourceShown", onSource, false);
|
||||
}
|
||||
|
||||
function onSource(aEvent) {
|
||||
if (aEvent.detail.url != src) {
|
||||
return;
|
||||
}
|
||||
dbg.panelWin.removeEventListener("Debugger:SourceShown", onSource, false);
|
||||
|
||||
ok(true, "Correct script is selected for index " + index);
|
||||
|
||||
checkCorrectLine(function() {
|
||||
gDevTools.showToolbox(target, "webconsole").then(function() {
|
||||
index++;
|
||||
info("webconsole selected for index " + index);
|
||||
|
||||
toolbox.once("jsdebugger-selected", checkLineAndClickNext);
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" }, nodes[index%2]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function checkCorrectLine(aCallback)
|
||||
{
|
||||
waitForSuccess({
|
||||
name: "correct source and line test for debugger for index " + index,
|
||||
validatorFn: function()
|
||||
{
|
||||
let debuggerView = dbg.panelWin.DebuggerView;
|
||||
if (debuggerView.editor &&
|
||||
debuggerView.editor.getCaretPosition().line == line - 1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
successFn: function()
|
||||
{
|
||||
aCallback && executeSoon(aCallback);
|
||||
},
|
||||
failureFn: finishTest,
|
||||
timeout: 10000,
|
||||
});
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
window.addEventListener("load", function() {
|
||||
console.log("Blah Blah");
|
||||
}, false);
|
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Web Console test for bug 766001 : Open JS/Console call Links in Debugger</title>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<script type="text/javascript" src="test-bug-766001-js-errors.js"></script>
|
||||
<script type="text/javascript" src="test-bug-766001-console-log.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<p>Web Console test for bug 766001 : Open JS/Console call Links in Debugger.</p>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,7 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
window.addEventListener("load", function() {
|
||||
document.bar();
|
||||
}, false);
|
@ -15,15 +15,6 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
||||
"resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DebuggerServer",
|
||||
"resource://gre/modules/devtools/dbg-server.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DebuggerClient",
|
||||
"resource://gre/modules/devtools/dbg-client.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "debuggerSocketConnect",
|
||||
"resource://gre/modules/devtools/dbg-client.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper",
|
||||
"@mozilla.org/widget/clipboardhelper;1",
|
||||
"nsIClipboardHelper");
|
||||
@ -2419,6 +2410,10 @@ WebConsoleFrame.prototype = {
|
||||
else if (locationNode.parentNode.category == CATEGORY_CSS) {
|
||||
this.owner.viewSourceInStyleEditor(aSourceURL, aSourceLine);
|
||||
}
|
||||
else if (locationNode.parentNode.category == CATEGORY_JS ||
|
||||
locationNode.parentNode.category == CATEGORY_WEBDEV) {
|
||||
this.owner.viewSourceInDebugger(aSourceURL, aSourceLine);
|
||||
}
|
||||
else {
|
||||
this.owner.viewSource(aSourceURL, aSourceLine);
|
||||
}
|
||||
@ -3988,7 +3983,6 @@ function WebConsoleConnectionProxy(aWebConsole, aTarget)
|
||||
this._onNetworkEventUpdate = this._onNetworkEventUpdate.bind(this);
|
||||
this._onFileActivity = this._onFileActivity.bind(this);
|
||||
this._onTabNavigated = this._onTabNavigated.bind(this);
|
||||
this._onListTabs = this._onListTabs.bind(this);
|
||||
this._onAttachTab = this._onAttachTab.bind(this);
|
||||
this._onAttachConsole = this._onAttachConsole.bind(this);
|
||||
this._onCachedMessages = this._onCachedMessages.bind(this);
|
||||
@ -4072,17 +4066,6 @@ WebConsoleConnectionProxy.prototype = {
|
||||
*/
|
||||
_hasNativeConsoleAPI: false,
|
||||
|
||||
/**
|
||||
* Initialize the debugger server.
|
||||
*/
|
||||
initServer: function WCCP_initServer()
|
||||
{
|
||||
if (!DebuggerServer.initialized) {
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize a debugger client and connect it to the debugger server.
|
||||
*
|
||||
@ -4111,16 +4094,7 @@ WebConsoleConnectionProxy.prototype = {
|
||||
this._connectTimer = null;
|
||||
}.bind(this));
|
||||
|
||||
// TODO: convert the non-remote path to use the target API as well.
|
||||
let transport, client;
|
||||
if (this.target.isRemote) {
|
||||
client = this.client = this.target.client;
|
||||
}
|
||||
else {
|
||||
this.initServer();
|
||||
transport = DebuggerServer.connectPipe();
|
||||
client = this.client = new DebuggerClient(transport);
|
||||
}
|
||||
let client = this.client = this.target.client;
|
||||
|
||||
client.addListener("pageError", this._onPageError);
|
||||
client.addListener("consoleAPICall", this._onConsoleAPICall);
|
||||
@ -4129,21 +4103,14 @@ WebConsoleConnectionProxy.prototype = {
|
||||
client.addListener("fileActivity", this._onFileActivity);
|
||||
client.addListener("tabNavigated", this._onTabNavigated);
|
||||
|
||||
if (this.target.isRemote) {
|
||||
if (!this.target.chrome) {
|
||||
// target.form is a TabActor grip
|
||||
this._attachTab(this.target.form);
|
||||
}
|
||||
else {
|
||||
// target.form is a RootActor grip
|
||||
this._consoleActor = this.target.form.consoleActor;
|
||||
this._attachConsole();
|
||||
}
|
||||
if (!this.target.chrome) {
|
||||
// target.form is a TabActor grip
|
||||
this._attachTab(this.target.form);
|
||||
}
|
||||
else {
|
||||
client.connect(function(aType, aTraits) {
|
||||
client.listTabs(this._onListTabs);
|
||||
}.bind(this));
|
||||
// target.form is a RootActor grip
|
||||
this._consoleActor = this.target.form.consoleActor;
|
||||
this._attachConsole();
|
||||
}
|
||||
|
||||
return promise;
|
||||
@ -4163,25 +4130,6 @@ WebConsoleConnectionProxy.prototype = {
|
||||
this._connectDefer.reject(error);
|
||||
},
|
||||
|
||||
/**
|
||||
* The "listTabs" response handler.
|
||||
*
|
||||
* @private
|
||||
* @param object aResponse
|
||||
* The JSON response object received from the server.
|
||||
*/
|
||||
_onListTabs: function WCCP__onListTabs(aResponse)
|
||||
{
|
||||
if (aResponse.error) {
|
||||
Cu.reportError("listTabs failed: " + aResponse.error + " " +
|
||||
aResponse.message);
|
||||
this._connectDefer.reject(aResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
this._attachTab(aResponse.tabs[aResponse.selected]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Attach to the tab actor.
|
||||
*
|
||||
@ -4433,21 +4381,6 @@ WebConsoleConnectionProxy.prototype = {
|
||||
return this._disconnecter.promise;
|
||||
}
|
||||
|
||||
let onDisconnect = function() {
|
||||
if (timer) {
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
this._disconnecter.resolve(null);
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
let timer = null;
|
||||
let remoteTarget = this.target.isRemote;
|
||||
if (!remoteTarget) {
|
||||
timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
timer.initWithCallback(onDisconnect, 1500, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
}
|
||||
|
||||
this.client.removeListener("pageError", this._onPageError);
|
||||
this.client.removeListener("consoleAPICall", this._onConsoleAPICall);
|
||||
this.client.removeListener("networkEvent", this._onNetworkEvent);
|
||||
@ -4455,28 +4388,13 @@ WebConsoleConnectionProxy.prototype = {
|
||||
this.client.removeListener("fileActivity", this._onFileActivity);
|
||||
this.client.removeListener("tabNavigated", this._onTabNavigated);
|
||||
|
||||
let client = this.client;
|
||||
|
||||
this.client = null;
|
||||
this.webConsoleClient = null;
|
||||
this.tabClient = null;
|
||||
this.target = null;
|
||||
this.connected = false;
|
||||
this.owner = null;
|
||||
|
||||
if (!remoteTarget) {
|
||||
try {
|
||||
client.close(onDisconnect);
|
||||
}
|
||||
catch (ex) {
|
||||
Cu.reportError("Web Console disconnect exception: " + ex);
|
||||
Cu.reportError(ex.stack);
|
||||
onDisconnect();
|
||||
}
|
||||
}
|
||||
else {
|
||||
onDisconnect();
|
||||
}
|
||||
this._disconnecter.resolve(null);
|
||||
|
||||
return this._disconnecter.promise;
|
||||
},
|
||||
|
@ -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">
|
@ -333,29 +333,29 @@ introDesc=Show the opening message
|
||||
# command. Displayed when the user asks for help on what it does.
|
||||
introManual=Redisplay the message that is shown to new users until they click the 'Got it!' button
|
||||
|
||||
# LOCALIZATION NOTE (introTextOpening): The 'intro text' opens when the user
|
||||
# LOCALIZATION NOTE (introTextOpening2): The 'intro text' opens when the user
|
||||
# first opens the developer toolbar to explain the command line, and is shown
|
||||
# each time it is opened until the user clicks the 'Got it!' button. This
|
||||
# string is the opening paragraph of the intro text.
|
||||
introTextOpening2=This command line is designed for developers. It focuses on speed of input over JavaScript syntax and a rich display over monospace output.
|
||||
|
||||
# LOCALIZATION NOTE (introTextCommands): For information about the 'intro
|
||||
# text' see introTextOpening. The second paragraph is in 2 sections, the first
|
||||
# section points the user to the 'help' command.
|
||||
# text' see introTextOpening2. The second paragraph is in 2 sections, the
|
||||
# first section points the user to the 'help' command.
|
||||
introTextCommands=For a list of commands type
|
||||
|
||||
# LOCALIZATION NOTE (introTextKeys2): For information about the 'intro text'
|
||||
# see introTextOpening. The second section in the second paragraph points the
|
||||
# see introTextOpening2. The second section in the second paragraph points the
|
||||
# user to the F1/Escape keys which show and hide hints.
|
||||
introTextKeys2=, or to show/hide command hints press
|
||||
|
||||
# LOCALIZATION NOTE (introTextF1Escape): For information about the 'intro
|
||||
# text' see introTextOpening. This string is used with introTextKeys, and
|
||||
# text' see introTextOpening2. This string is used with introTextKeys2, and
|
||||
# contains the keys that are pressed to open and close hints.
|
||||
introTextF1Escape=F1/Escape
|
||||
|
||||
# LOCALIZATION NOTE (introTextGo): For information about the 'intro text' see
|
||||
# introTextOpening. The text on the button that dismisses the intro text.
|
||||
# introTextOpening2. The text on the button that dismisses the intro text.
|
||||
introTextGo=Got it!
|
||||
|
||||
# LOCALIZATION NOTE (hideIntroDesc): Short description of the 'hideIntro'
|
||||
|
@ -1,3 +1,7 @@
|
||||
# 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/.
|
||||
|
||||
toolboxDockButtons.bottom.tooltip=Dock to bottom of browser window
|
||||
toolboxDockButtons.side.tooltip=Dock to side of browser window
|
||||
toolboxDockButtons.window.tooltip=Show in separate window
|
||||
|
@ -47,6 +47,7 @@
|
||||
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)
|
||||
|
79
browser/themes/linux/devtools/font-inspector.css
Normal file
79
browser/themes/linux/devtools/font-inspector.css
Normal file
@ -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;
|
||||
}
|
@ -190,6 +190,7 @@ browser.jar:
|
||||
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
|
||||
|
79
browser/themes/osx/devtools/font-inspector.css
Normal file
79
browser/themes/osx/devtools/font-inspector.css
Normal file
@ -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;
|
||||
}
|
@ -271,6 +271,7 @@ browser.jar:
|
||||
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
|
||||
|
79
browser/themes/windows/devtools/font-inspector.css
Normal file
79
browser/themes/windows/devtools/font-inspector.css
Normal file
@ -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;
|
||||
}
|
@ -217,6 +217,7 @@ browser.jar:
|
||||
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
|
||||
@ -445,6 +446,7 @@ browser.jar:
|
||||
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
|
||||
|
@ -679,7 +679,6 @@ DebuggerProgressListener.prototype = {
|
||||
from: this._tabActor.actorID,
|
||||
type: "tabNavigated",
|
||||
url: aRequest.URI.spec,
|
||||
title: "",
|
||||
nativeConsoleAPI: true,
|
||||
state: "start",
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user