Merge m-c to inbound.

This commit is contained in:
Ryan VanderMeulen 2013-03-27 22:23:59 -04:00
commit 00ebc7395d
88 changed files with 2582 additions and 2364 deletions

View File

@ -1056,6 +1056,8 @@ pref("devtools.responsiveUI.enabled", true);
// Enable the Debugger
pref("devtools.debugger.enabled", true);
pref("devtools.debugger.chrome-enabled", true);
pref("devtools.debugger.chrome-debugging-host", "localhost");
pref("devtools.debugger.chrome-debugging-port", 6080);
pref("devtools.debugger.remote-host", "localhost");
pref("devtools.debugger.remote-autoconnect", false);
pref("devtools.debugger.remote-connection-retries", 3);
@ -1097,6 +1099,9 @@ pref("devtools.styleeditor.transitions", true);
// Enable tools for Chrome development.
pref("devtools.chrome.enabled", false);
// Default theme ("dark" or "light")
pref("devtools.theme", "light");
// Display the introductory text
pref("devtools.gcli.hideIntro", false);

View File

@ -11,7 +11,7 @@ const Cu = Components.utils;
const DBG_XUL = "chrome://browser/content/debugger.xul";
const DBG_STRINGS_URI = "chrome://browser/locale/devtools/debugger.properties";
const CHROME_DEBUGGER_PROFILE_NAME = "_chrome-debugger-profile";
const CHROME_DEBUGGER_PROFILE_NAME = "-chrome-debugger";
const TAB_SWITCH_NOTIFICATION = "debugger-tab-switch";
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
@ -475,7 +475,7 @@ ChromeDebuggerProcess.prototype = {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
}
DebuggerServer.openListener(Prefs.remotePort);
DebuggerServer.openListener(Prefs.chromeDebuggingPort);
},
/**
@ -597,27 +597,11 @@ XPCOMUtils.defineLazyGetter(L10N, "stringBundle", function() {
let Prefs = {};
/**
* Gets the preferred default remote debugging host.
* @return string
*/
XPCOMUtils.defineLazyGetter(Prefs, "remoteHost", function() {
return Services.prefs.getCharPref("devtools.debugger.remote-host");
});
/**
* Gets the preferred default remote debugging port.
* Gets the preferred default remote browser debugging port.
* @return number
*/
XPCOMUtils.defineLazyGetter(Prefs, "remotePort", function() {
return Services.prefs.getIntPref("devtools.debugger.remote-port");
});
/**
* Gets the preferred default remote debugging port.
* @return number
*/
XPCOMUtils.defineLazyGetter(Prefs, "wantLogging", function() {
return Services.prefs.getBoolPref("devtools.debugger.log");
XPCOMUtils.defineLazyGetter(Prefs, "chromeDebuggingPort", function() {
return Services.prefs.getIntPref("devtools.debugger.chrome-debugging-port");
});
/**
@ -625,7 +609,9 @@ XPCOMUtils.defineLazyGetter(Prefs, "wantLogging", function() {
* @param string
*/
function dumpn(str) {
if (Prefs.wantLogging) {
if (wantLogging) {
dump("DBG-FRONTEND: " + str + "\n");
}
}
let wantLogging = Services.prefs.getBoolPref("devtools.debugger.log");

View File

@ -185,7 +185,8 @@ let DebuggerController = {
}
// Chrome debugging needs to make the connection to the debuggee.
let transport = debuggerSocketConnect(Prefs.remoteHost, Prefs.remotePort);
let transport = debuggerSocketConnect(Prefs.chromeDebuggingHost,
Prefs.chromeDebuggingPort);
let client = this.client = new DebuggerClient(transport);
client.addListener("tabNavigated", this._onTabNavigated);
@ -1731,6 +1732,8 @@ let Prefs = {
}
};
Prefs.map("Char", "chromeDebuggingHost", "devtools.debugger.chrome-debugging-host");
Prefs.map("Int", "chromeDebuggingPort", "devtools.debugger.chrome-debugging-port");
Prefs.map("Int", "windowX", "devtools.debugger.ui.win-x");
Prefs.map("Int", "windowY", "devtools.debugger.ui.win-y");
Prefs.map("Int", "windowWidth", "devtools.debugger.ui.win-width");

View File

@ -977,25 +977,18 @@ let SourceUtils = {
*
* @param string aUrl
* The source url.
* @param number aLength [optional]
* The expected source url length.
* @param number aSection [optional]
* The section to trim. Supported values: "start", "center", "end"
* @return string
* The simplified label.
*/
getSourceLabel: function SU_getSourceLabel(aUrl, aLength, aSection) {
aLength = aLength || SOURCE_URL_DEFAULT_MAX_LENGTH;
aSection = aSection || "end";
let id = [aUrl, aLength, aSection].join();
let cachedLabel = this._labelsCache.get(id);
getSourceLabel: function SU_getSourceLabel(aUrl) {
let cachedLabel = this._labelsCache.get(aUrl);
if (cachedLabel) {
return cachedLabel;
}
let sourceLabel = this.trimUrlLength(this.trimUrl(aUrl), aLength, aSection);
let sourceLabel = this.trimUrl(aUrl);
let unicodeLabel = this.convertToUnicode(window.unescape(sourceLabel));
this._labelsCache.set(id, unicodeLabel);
this._labelsCache.set(aUrl, unicodeLabel);
return unicodeLabel;
},

View File

@ -432,10 +432,11 @@ create({ constructor: StackFramesView, proto: MenuContainer.prototype }, {
*/
_createFrameView:
function DVSF__createFrameView(aFrameTitle, aSourceLocation, aLineNumber, aDepth) {
let frameDetails = SourceUtils.getSourceLabel(aSourceLocation,
STACK_FRAMES_SOURCE_URL_MAX_LENGTH,
STACK_FRAMES_SOURCE_URL_TRIM_SECTION) +
SEARCH_LINE_FLAG + aLineNumber;
let frameDetails =
SourceUtils.trimUrlLength(
SourceUtils.getSourceLabel(aSourceLocation),
STACK_FRAMES_SOURCE_URL_MAX_LENGTH,
STACK_FRAMES_SOURCE_URL_TRIM_SECTION) + SEARCH_LINE_FLAG + aLineNumber;
let frameTitleNode = document.createElement("label");
frameTitleNode.className = "plain dbg-stackframe-title breadcrumbs-widget-item-tag";
@ -471,10 +472,11 @@ create({ constructor: StackFramesView, proto: MenuContainer.prototype }, {
*/
_createMenuEntry:
function DVSF__createMenuEntry(aFrameTitle, aSourceLocation, aLineNumber, aDepth) {
let frameDescription = SourceUtils.getSourceLabel(aSourceLocation,
STACK_FRAMES_POPUP_SOURCE_URL_MAX_LENGTH,
STACK_FRAMES_POPUP_SOURCE_URL_TRIM_SECTION) +
SEARCH_LINE_FLAG + aLineNumber;
let frameDescription =
SourceUtils.trimUrlLength(
SourceUtils.getSourceLabel(aSourceLocation),
STACK_FRAMES_POPUP_SOURCE_URL_MAX_LENGTH,
STACK_FRAMES_POPUP_SOURCE_URL_TRIM_SECTION) + SEARCH_LINE_FLAG + aLineNumber;
let prefix = "sf-cMenu-"; // "stackframes context menu"
let commandId = prefix + aDepth + "-" + "-command";

View File

@ -81,7 +81,7 @@ function testlabelshortening() {
urls.forEach(function(url) {
executeSoon(function() {
let loc = url.href + url.leaf;
vs.push([sv.getSourceLabel(loc), loc], { forced: true });
vs.push([sv.trimUrlLength(sv.getSourceLabel(loc)), loc], { forced: true });
});
});

View File

@ -182,6 +182,7 @@ FontInspector.prototype = {
* <p contenteditable>Abc</p>
*/
let extraCSS = "* {padding:0;margin:0}";
extraCSS += ".theme-dark {color: white}";
extraCSS += "p {font-family: '" + name + "';}";
extraCSS += "p {font-size: 40px;line-height:60px;padding:0 10px;margin:0;}";
cssCode += extraCSS;
@ -193,6 +194,8 @@ FontInspector.prototype = {
// nightmare.
doc.querySelector("base").href = base;
doc.querySelector("style").textContent = cssCode;
// Forward theme
doc.documentElement.className = document.documentElement.className;
}, true);
iframe.src = src;
},

View File

@ -14,8 +14,9 @@
<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"/>
<script type="application/javascript;version=1.8" src="chrome://browser/content/devtools/theme-switching.js"/>
</head>
<body class="devtools-monospace" role="application">
<body class="theme-body devtools-monospace" role="application">
<script type="application/javascript;version=1.8" src="font-inspector.js"></script>
<div id="root">
<ul id="all-fonts"></ul>

View File

@ -714,6 +714,11 @@ Toolbox.prototype = {
outstanding.push(panel.destroy());
}
let container = this.doc.getElementById("toolbox-buttons");
while(container.firstChild) {
container.removeChild(container.firstChild);
}
outstanding.push(this._host.destroy());
// Targets need to be notified that the toolbox is being torn down, so that
@ -726,6 +731,9 @@ Toolbox.prototype = {
Promise.all(outstanding).then(function() {
this.emit("destroyed");
// Free _host after the call to destroyed in order to let a chance
// to destroyed listeners to still query toolbox attributes
this._host = null;
deferred.resolve();
}.bind(this));

View File

@ -607,7 +607,7 @@ let gDevToolsBrowser = {
// Destroy toolboxes for closed window
for (let [target, toolbox] of gDevTools._toolboxes) {
if (toolbox.frame.ownerDocument.defaultView == win) {
if (toolbox.frame && toolbox.frame.ownerDocument.defaultView == win) {
toolbox.destroy();
}
}

View File

@ -221,11 +221,11 @@ InspectorPanel.prototype = {
this.toggleHighlighter = this.toggleHighlighter.bind(this);
this.sidebar.addTab("ruleview",
"chrome://browser/content/devtools/cssruleview.xul",
"chrome://browser/content/devtools/cssruleview.xhtml",
"ruleview" == defaultTab);
this.sidebar.addTab("computedview",
"chrome://browser/content/devtools/csshtmltree.xul",
"chrome://browser/content/devtools/computedview.xhtml",
"computedview" == defaultTab);
if (Services.prefs.getBoolPref("devtools.fontinspector.enabled")) {

View File

@ -87,7 +87,7 @@
</vbox>
</vbox>
<splitter class="devtools-side-splitter"/>
<tabbox id="inspector-sidebar" class="devtools-sidebar-tabs" hidden="true">
<tabbox id="inspector-sidebar" handleCtrlTab="false" class="devtools-sidebar-tabs" hidden="true">
<tabs/>
<tabpanels flex="1"/>
</tabbox>

View File

@ -12,11 +12,12 @@ browser.jar:
* content/browser/scratchpad.xul (scratchpad/scratchpad.xul)
content/browser/scratchpad.js (scratchpad/scratchpad.js)
content/browser/splitview.css (shared/splitview.css)
content/browser/devtools/theme-switching.js (shared/theme-switching.js)
content/browser/styleeditor.xul (styleeditor/styleeditor.xul)
content/browser/styleeditor.css (styleeditor/styleeditor.css)
content/browser/devtools/csshtmltree.xul (styleinspector/csshtmltree.xul)
content/browser/devtools/cssruleview.xul (styleinspector/cssruleview.xul)
content/browser/devtools/styleinspector.css (styleinspector/styleinspector.css)
content/browser/devtools/computedview.xhtml (styleinspector/computedview.xhtml)
content/browser/devtools/cssruleview.xhtml (styleinspector/cssruleview.xhtml)
content/browser/devtools/ruleview.css (styleinspector/ruleview.css)
content/browser/devtools/layoutview/view.js (layoutview/view.js)
content/browser/devtools/layoutview/view.xhtml (layoutview/view.xhtml)
content/browser/devtools/layoutview/view.css (layoutview/view.css)

View File

@ -47,6 +47,16 @@ body {
font: 10px/12px monospace;
}
@media (min-width: 320px) {
body {
position: absolute;
width: 320px;
left: -160px;
margin-left: 50%;
}
}
#margins {
padding: 28px;
}

View File

@ -12,6 +12,8 @@
<head>
<title>&title;</title>
<script id="script-theme" type="application/javascript;version=1.8" src="chrome://browser/content/devtools/theme-switching.js"/>
<script type="application/javascript;version=1.8" src="view.js"></script>
<script type="application/javascript;version=1.8">
<![CDATA[
@ -67,7 +69,7 @@
<link rel="stylesheet" href="view.css" type="text/css"/>
</head>
<body>
<body class="theme-body">
<p id="header">
<span id="element-size"></span>

View File

@ -843,13 +843,13 @@ MarkupContainer.prototype = {
set expanded(aValue) {
if (aValue) {
this.expander.setAttribute("expanded", "");
this.expander.setAttribute("open", "");
this.children.setAttribute("expanded", "");
if (this.editor.summaryElt) {
this.editor.summaryElt.setAttribute("expanded", "");
}
} else {
this.expander.removeAttribute("expanded");
this.expander.removeAttribute("open");
this.children.removeAttribute("expanded");
if (this.editor.summaryElt) {
this.editor.summaryElt.removeAttribute("expanded");
@ -877,14 +877,14 @@ MarkupContainer.prototype = {
set selected(aValue) {
this._selected = aValue;
if (this._selected) {
this.editor.elt.classList.add("selected");
this.editor.elt.classList.add("theme-selected");
if (this.editor.closeElt) {
this.editor.closeElt.classList.add("selected");
this.editor.closeElt.classList.add("theme-selected");
}
} else {
this.editor.elt.classList.remove("selected");
this.editor.elt.classList.remove("theme-selected");
if (this.editor.closeElt) {
this.editor.closeElt.classList.remove("selected");
this.editor.closeElt.classList.remove("theme-selected");
}
}
},
@ -1178,28 +1178,21 @@ ElementEditor.prototype = {
* @param Element aAttrNode the attribute editor that created this
* set of attributes, used to place new attributes where the
* user put them.
* @throws SYNTAX_ERR if aValue is not well-formed.
*/
_applyAttributes: function EE__applyAttributes(aValue, aAttrNode)
{
// Create a dummy node for parsing the attribute list.
let dummyNode = this.doc.createElement("div");
let parseTag = (this.node.namespaceURI.match(/svg/i) ? "svg" :
(this.node.namespaceURI.match(/mathml/i) ? "math" : "div"));
let parseText = "<" + parseTag + " " + aValue + "/>";
// Throws exception if parseText is not well-formed.
dummyNode.innerHTML = parseText;
let parsedNode = dummyNode.firstChild;
let attrs = parsedNode.attributes;
let attrs = escapeAttributeValues(aValue);
this.undo.startBatch();
for (let i = 0; i < attrs.length; i++) {
for (let attr of attrs) {
let attribute = {
name: attr.name,
value: attr.value
};
// Create an attribute editor next to the current attribute if needed.
this._createAttribute(attrs[i], aAttrNode ? aAttrNode.nextSibling : null);
this._setAttribute(this.node, attrs[i].name, attrs[i].value);
this._createAttribute(attribute, aAttrNode ? aAttrNode.nextSibling : null);
this._setAttribute(this.node, attr.name, attr.value);
}
this.undo.endBatch();
@ -1424,6 +1417,100 @@ DocumentWalker.prototype = {
nextSibling: function DW_nextSibling() this.walker.nextSibling(),
// XXX bug 785143: not doing previousNode or nextNode, which would sure be useful.
};
/**
* Properly escape attribute values.
*
* @param {String} attr
* The attributes for which the values are to be escaped.
* @return {Array}
* An array of attribute names and their escaped values.
*/
function escapeAttributeValues(attr) {
let name = null;
let value = null;
let result = "";
let attributes = [];
while(attr.length > 0) {
let match;
let dirty = false;
// Trim quotes and spaces from attr start
match = attr.match(/^["\s]+/);
if (match && match.length == 1) {
attr = attr.substr(match[0].length);
}
// Name
if (!dirty) {
match = attr.match(/^([\w-]+)="/);
if (match && match.length == 2) {
if (name) {
// We had a name without a value e.g. disabled. Let's set the value to "";
value = "";
} else {
name = match[1];
attr = attr.substr(match[0].length);
}
dirty = true;
}
}
// Value (in the case of multiple attributes)
if (!dirty) {
match = attr.match(/^(.+?)"\s+[\w-]+="/);
if (match && match.length > 1) {
value = typeof match[1] == "undefined" ? match[2] : match[1];
attr = attr.substr(value.length);
value = simpleEscape(value);
dirty = true;
}
}
// Final value
if (!dirty && attr.indexOf("=\"") == -1) {
// No more attributes, get the remaining value minus it's ending quote.
if (attr.charAt(attr.length - 1) == '"') {
attr = attr.substr(0, attr.length - 1);
}
if (!name) {
name = attr;
value = "";
} else {
value = simpleEscape(attr);
}
attr = "";
dirty = true;
}
if (name !== null && value !== null) {
attributes.push({name: name, value: value});
name = value = null;
}
if (!dirty) {
// This should never happen but we exit here if it does.
return attributes;
}
}
return attributes;
}
/**
* Escape basic html entities <, >, " and '.
* @param {String} value
* Value to escape.
* @return {String}
* Escaped value.
*/
function simpleEscape(value) {
return value.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&apos;");
}
/**

View File

@ -10,31 +10,34 @@
<link rel="stylesheet" href="chrome://browser/content/devtools/markup-view.css" type="text/css"/>
<link rel="stylesheet" href="chrome://browser/skin/devtools/markup-view.css" type="text/css"/>
<link rel="stylesheet" href="chrome://browser/skin/devtools/common.css" type="text/css"/>
<script type="application/javascript;version=1.8" src="theme-switching.js"/>
</head>
<body class="devtools-theme-background devtools-monospace" role="application">
<body class="theme-body devtools-monospace" role="application">
<div id="root"></div>
<div id="templates" style="display:none">
<ul>
<li id="template-container" save="${elt}" class="container"><span save="${expander}" class="expander"></span><span save="${codeBox}" class="codebox"><ul save="${children}" class="children"></ul></span></li>
<li id="template-container" save="${elt}" class="container"><span save="${expander}" class="theme-twisty expander"></span><span save="${codeBox}" class="codebox"><ul save="${children}" class="children"></ul></span></li>
<li id="template-more-nodes" class="more-nodes devtools-class-comment" save="${elt}"><span>${showing}</span> <button href="#" onclick="${allButtonClick}">${showAll}</button></li>
</ul>
<span id="template-element" save="${elt}" class="editor"><span>&lt;</span><span save="${tag}" class="tagname devtools-theme-tagname"></span><span save="${attrList}"></span><span save="${newAttr}" class="newattr" tabindex="0"></span>&gt;</span>
<span id="template-element" save="${elt}" class="editor"><span>&lt;</span><span save="${tag}" class="tagname theme-fg-color3"></span><span save="${attrList}"></span><span save="${newAttr}" class="newattr" tabindex="0"></span>&gt;</span>
<span id="template-attribute" save="${attr}" data-attr="${attrName}" class="attreditor" style="display:none"> <span class="editable" save="${inner}" tabindex="0"><span save="${name}" class="attrname devtools-theme-attrname"></span>=&quot;<span save="${val}" class="attrvalue devtools-theme-attrvalue"></span>&quot;</span></span>
<span id="template-attribute" save="${attr}" data-attr="${attrName}" class="attreditor" style="display:none"> <span class="editable" save="${inner}" tabindex="0"><span save="${name}" class="attrname theme-fg-color2"></span>=&quot;<span save="${val}" class="attrvalue theme-fg-color6"></span>&quot;</span></span>
<span id="template-text" save="${elt}" class="editor text">
<pre save="${value}" style="display:inline-block;" tabindex="0"></pre>
</span>
<span id="template-comment" save="${elt}" class="editor comment devtools-theme-comment">
<span id="template-comment" save="${elt}" class="editor comment theme-comment">
<span>&lt;!--</span><pre save="${value}" style="display:inline-block;" tabindex="0"></pre><span>--&gt;</span>
</span>
<span id="template-elementContentSummary" save="${summaryElt}" class="summary"></span>
<span id="template-elementClose" save="${closeElt}">&lt;/<span save="${closeTag}" class="tagname devtools-theme-tagname"></span>&gt;</span>
<span id="template-elementClose" save="${closeElt}">&lt;/<span save="${closeTag}" class="tagname theme-fg-color3"></span>&gt;</span>
</div>
<div id="previewbar" class="disabled">
<div id="preview"/>

View File

@ -39,5 +39,6 @@
<div id="retag-me">
<div id="retag-me-2"></div>
</div>
<div id="node25"></div>
</body>
</html>

View File

@ -42,12 +42,27 @@ function test() {
EventUtils.sendKey("return", inspector.panelWin);
}
/**
* Check that the appropriate attributes are assigned to a node.
*
* @param {HTMLNode} aElement
* The node to check.
* @param {Object} aAttributes
* An object containing the arguments to check.
* e.g. {id="id1",class="someclass"}
*
* NOTE: When checking attribute values bare in mind that node.getAttribute()
* returns attribute values provided by the HTML parser. The parser only
* provides unescaped entities so &amp; will return &.
*/
function assertAttributes(aElement, aAttributes)
{
let attrs = Object.getOwnPropertyNames(aAttributes);
is(aElement.attributes.length, attrs.length, "Node has the correct number of attributes");
is(aElement.attributes.length, attrs.length,
"Node has the correct number of attributes");
for (let attr of attrs) {
is(aElement.getAttribute(attr), aAttributes[attr], "Node has the correct " + attr + " attribute.");
is(aElement.getAttribute(attr), aAttributes[attr],
"Node has the correct " + attr + " attribute.");
}
}
@ -76,7 +91,8 @@ function test() {
},
{
desc: "Try change an attribute to a badly formed string",
desc: 'Try changing an attribute to a quote (") - this should result ' +
'in it being set to an empty string',
before: function() {
assertAttributes(doc.querySelector("#node22"), {
id: "node22",
@ -92,7 +108,7 @@ function test() {
after: function() {
assertAttributes(doc.querySelector("#node22"), {
id: "node22",
class: "unchanged"
class: ""
});
}
},
@ -141,7 +157,9 @@ function test() {
},
{
desc: "Try add a badly formed attribute by clicking the empty space after a node",
desc: 'Try add an attribute containing a quote (") attribute by ' +
'clicking the empty space after a node - this should result ' +
'in it being set to an empty string',
before: function() {
assertAttributes(doc.querySelector("#node23"), {
id: "node23",
@ -156,6 +174,8 @@ function test() {
after: function() {
assertAttributes(doc.querySelector("#node23"), {
id: "node23",
class: "newclass",
style: ""
});
}
},
@ -176,6 +196,7 @@ function test() {
after: function() {
assertAttributes(doc.querySelector("#node24"), {
id: "node24",
class: ""
});
}
},
@ -198,6 +219,27 @@ function test() {
is(node.nodeValue, "New text", "Text should be changed.");
},
},
{
desc: "Add an attribute value containing < > &uuml; \" & '",
before: function() {
assertAttributes(doc.querySelector("#node25"), {
id: "node25",
});
},
execute: function(after) {
inspector.once("markupmutation", after);
let editor = markup.getContainer(doc.querySelector("#node25")).editor;
let attr = editor.newAttr;
editField(attr, 'src="somefile.html?param1=<a>&param2=&uuml;"bl\'ah"');
},
after: function() {
assertAttributes(doc.querySelector("#node25"), {
id: "node25",
src: "somefile.html?param1=&lt;a&gt;&param2=&uuml;&quot;bl&apos;ah"
});
}
},
];
// Create the helper tab for parsing...

View File

@ -3,6 +3,7 @@
function test() {
let instance, deletedPresetA, deletedPresetB, oldPrompt;
let mgr = ResponsiveUI.ResponsiveUIManager;
waitForExplicitFinish();
@ -27,8 +28,8 @@ function test() {
};
document.getElementById("Tools:ResponsiveUI").removeAttribute("disabled");
mgr.once("on", onUIOpen);
synthesizeKeyFromKeyTag("key_responsiveUI");
executeSoon(onUIOpen);
}
function onUIOpen() {
@ -66,19 +67,31 @@ function test() {
instance.menulist.selectedIndex = 1;
EventUtils.synthesizeKey("VK_ESCAPE", {});
executeSoon(restart);
mgr.once("off", restart);
// We're still in the loop of initializing the responsive mode.
// Let's wait next loop to stop it.
executeSoon(function() {
EventUtils.synthesizeKey("VK_ESCAPE", {});
});
}
function restart() {
synthesizeKeyFromKeyTag("key_responsiveUI");
info("Restarting Responsive Mode");
mgr.once("on", function() {
let container = gBrowser.getBrowserContainer();
is(container.getAttribute("responsivemode"), "true", "In responsive mode.");
let container = gBrowser.getBrowserContainer();
is(container.getAttribute("responsivemode"), "true", "In responsive mode.");
instance = gBrowser.selectedTab.__responsiveUI;
instance = gBrowser.selectedTab.__responsiveUI;
testCustomPresetInList();
});
testCustomPresetInList();
// We're still in the loop of destroying the responsive mode.
// Let's wait next loop to start it.
executeSoon(function() {
synthesizeKeyFromKeyTag("key_responsiveUI");
});
}
function testCustomPresetInList() {

View File

@ -0,0 +1,17 @@
/* 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/. */
(function() {
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/Services.jsm");
let theme = Services.prefs.getCharPref("devtools.theme");
let theme_url = Services.io.newURI("chrome://browser/skin/devtools/" + theme + "-theme.css", null, null);
let winUtils = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
winUtils.loadSheet(theme_url, window.AUTHOR_SHEET);
if (theme == "dark") {
let scrollbar_url = Services.io.newURI("chrome://browser/skin/devtools/floating-scrollbars-light.css", null, null);
winUtils.loadSheet(scrollbar_url, window.AGENT_SHEET);
}
document.documentElement.classList.add("theme-" + theme);
})()

View File

@ -134,11 +134,7 @@ this.CssHtmlTree = function CssHtmlTree(aStyleInspector)
// Create bound methods.
this.siFocusWindow = this.focusWindow.bind(this);
this.siBoundMenuUpdate = this.computedViewMenuUpdate.bind(this);
this.siBoundCopy = this.computedViewCopy.bind(this);
this.siBoundCopyDeclaration = this.computedViewCopyDeclaration.bind(this);
this.siBoundCopyProperty = this.computedViewCopyProperty.bind(this);
this.siBoundCopyPropertyValue = this.computedViewCopyPropertyValue.bind(this);
this.styleDocument.addEventListener("copy", this.siBoundCopy);
this.styleDocument.addEventListener("mousedown", this.siFocusWindow);
@ -154,7 +150,6 @@ this.CssHtmlTree = function CssHtmlTree(aStyleInspector)
// The element that we're inspecting, and the document that it comes from.
this.viewedElement = null;
this.createStyleViews();
this.createContextMenu();
}
/**
@ -206,10 +201,6 @@ CssHtmlTree.processTemplate = function CssHtmlTree_processTemplate(aTemplate,
XPCOMUtils.defineLazyGetter(CssHtmlTree, "_strings", function() Services.strings
.createBundle("chrome://browser/locale/devtools/styleinspector.properties"));
XPCOMUtils.defineLazyGetter(CssHtmlTree, "HELP_LINK_TITLE", function() {
return CssHtmlTree.HELP_LINK_TITLE = CssHtmlTree.l10n("helpLinkTitle");
});
XPCOMUtils.defineLazyGetter(this, "clipboardHelper", function() {
return Cc["@mozilla.org/widget/clipboardhelper;1"].
getService(Ci.nsIClipboardHelper);
@ -438,97 +429,6 @@ CssHtmlTree.prototype = {
return this._matchedProperties;
},
/**
* Create a context menu.
*/
createContextMenu: function SI_createContextMenu()
{
let iframe = this.styleInspector.outerIFrame;
let outerDoc = iframe.ownerDocument;
let popupSet = outerDoc.getElementById("inspectorPopupSet");
let menu = outerDoc.createElement("menupopup");
menu.addEventListener("popupshowing", this.siBoundMenuUpdate);
menu.id = "computed-view-context-menu";
popupSet.appendChild(menu);
// Copy selection
let label = CssHtmlTree.l10n("style.contextmenu.copyselection");
let accessKey = CssHtmlTree.l10n("style.contextmenu.copyselection.accesskey");
let item = outerDoc.createElement("menuitem");
item.id = "computed-view-copy";
item.setAttribute("label", label);
item.setAttribute("accesskey", accessKey);
item.addEventListener("command", this.siBoundCopy);
menu.appendChild(item);
// Copy declaration
label = CssHtmlTree.l10n("style.contextmenu.copydeclaration");
accessKey = CssHtmlTree.l10n("style.contextmenu.copydeclaration.accesskey");
item = outerDoc.createElement("menuitem");
item.id = "computed-view-copy-declaration";
item.setAttribute("label", label);
item.setAttribute("accesskey", accessKey);
item.addEventListener("command", this.siBoundCopyDeclaration);
menu.appendChild(item);
// Copy property name
label = CssHtmlTree.l10n("style.contextmenu.copyproperty");
accessKey = CssHtmlTree.l10n("style.contextmenu.copyproperty.accesskey");
item = outerDoc.createElement("menuitem");
item.id = "computed-view-copy-property";
item.setAttribute("label", label);
item.setAttribute("accesskey", accessKey);
item.addEventListener("command", this.siBoundCopyProperty);
menu.appendChild(item);
// Copy property value
label = CssHtmlTree.l10n("style.contextmenu.copypropertyvalue");
accessKey = CssHtmlTree.l10n("style.contextmenu.copypropertyvalue.accesskey");
item = outerDoc.createElement("menuitem");
item.id = "computed-view-copy-property-value";
item.setAttribute("label", label);
item.setAttribute("accesskey", accessKey);
item.addEventListener("command", this.siBoundCopyPropertyValue);
menu.appendChild(item);
iframe.setAttribute("context", menu.id);
},
/**
* Update the context menu by disabling irrelevant menuitems and enabling
* relevant ones.
*/
computedViewMenuUpdate: function si_computedViewMenuUpdate()
{
let disable = this.styleWindow.getSelection().isCollapsed;
let outerDoc = this.styleInspector.outerIFrame.ownerDocument;
let menuitem = outerDoc.querySelector("#computed-view-copy");
menuitem.disabled = disable;
let node = outerDoc.popupNode;
if (!node) {
return;
}
if (!node.classList.contains("property-view")) {
while (node = node.parentElement) {
if (node.classList.contains("property-view")) {
break;
}
}
}
let disablePropertyItems = !node;
menuitem = outerDoc.querySelector("#computed-view-copy-declaration");
menuitem.disabled = disablePropertyItems;
menuitem = outerDoc.querySelector("#computed-view-copy-property");
menuitem.disabled = disablePropertyItems;
menuitem = outerDoc.querySelector("#computed-view-copy-property-value");
menuitem.disabled = disablePropertyItems;
},
/**
* Focus the window on mousedown.
*
@ -552,10 +452,9 @@ CssHtmlTree.prototype = {
// Tidy up block headings by moving CSS property names and their values onto
// the same line and inserting a colon between them.
text = text.replace(/\t(.+)\t\t(.+)/g, "$1: $2");
text = text.replace(/(.+)\r\n(.+)/g, "$1: $2;");
text = text.replace(/(.+)\n(.+)/g, "$1: $2;");
// Remove any MDN link titles
text = text.replace(CssHtmlTree.HELP_LINK_TITLE, "");
let outerDoc = this.styleInspector.outerIFrame.ownerDocument;
clipboardHelper.copyString(text, outerDoc);
@ -564,86 +463,6 @@ CssHtmlTree.prototype = {
}
},
/**
* Copy declaration.
*
* @param aEvent The event object
*/
computedViewCopyDeclaration: function si_computedViewCopyDeclaration(aEvent)
{
let outerDoc = this.styleInspector.outerIFrame.ownerDocument;
let node = outerDoc.popupNode;
if (!node) {
return;
}
if (!node.classList.contains("property-view")) {
while (node = node.parentElement) {
if (node.classList.contains("property-view")) {
break;
}
}
}
if (node) {
let name = node.querySelector(".property-name").textContent;
let value = node.querySelector(".property-value").textContent;
clipboardHelper.copyString(name + ": " + value + ";", outerDoc);
}
},
/**
* Copy property name.
*
* @param aEvent The event object
*/
computedViewCopyProperty: function si_computedViewCopyProperty(aEvent)
{
let outerDoc = this.styleInspector.outerIFrame.ownerDocument;
let node = outerDoc.popupNode;
if (!node) {
return;
}
if (!node.classList.contains("property-view")) {
while (node = node.parentElement) {
if (node.classList.contains("property-view")) {
break;
}
}
}
if (node) {
node = node.querySelector(".property-name");
clipboardHelper.copyString(node.textContent, outerDoc);
}
},
/**
* Copy property value.
*
* @param aEvent The event object
*/
computedViewCopyPropertyValue: function si_computedViewCopyPropertyValue(aEvent)
{
let outerDoc = this.styleInspector.outerIFrame.ownerDocument;
let node = outerDoc.popupNode;
if (!node) {
return;
}
if (!node.classList.contains("property-view")) {
while (node = node.parentElement) {
if (node.classList.contains("property-view")) {
break;
}
}
}
if (node) {
node = node.querySelector(".property-value");
clipboardHelper.copyString(node.textContent, outerDoc);
}
},
/**
* Destructor for CssHtmlTree.
*/
@ -808,7 +627,7 @@ PropertyView.prototype = {
if (this.visible) {
this.tree._darkStripe = !this.tree._darkStripe;
let darkValue = this.tree._darkStripe ?
"property-view darkrow" : "property-view";
"property-view theme-bg-darker" : "property-view";
return darkValue;
}
return "property-view-hidden";
@ -823,7 +642,7 @@ PropertyView.prototype = {
{
if (this.visible) {
let darkValue = this.tree._darkStripe ?
"property-content darkrow" : "property-content";
"property-content theme-bg-darker" : "property-content";
return darkValue;
}
return "property-content-hidden";
@ -832,15 +651,11 @@ PropertyView.prototype = {
buildMain: function PropertyView_buildMain()
{
let doc = this.tree.styleDocument;
this.element = doc.createElementNS(HTML_NS, "tr");
this.element = doc.createElementNS(HTML_NS, "div");
this.element.setAttribute("class", this.propertyHeaderClassName);
this.expanderContainer = doc.createElementNS(HTML_NS, "td");
this.element.appendChild(this.expanderContainer);
this.expanderContainer.setAttribute("class", "expander-container");
this.matchedExpander = doc.createElementNS(HTML_NS, "div");
this.matchedExpander.setAttribute("class", "match expander");
this.matchedExpander.className = "expander theme-twisty";
this.matchedExpander.setAttribute("tabindex", "0");
this.matchedExpander.addEventListener("click",
this.matchedExpanderClick.bind(this), false);
@ -854,32 +669,21 @@ PropertyView.prototype = {
this.matchedExpanderClick(aEvent);
}
}.bind(this), false);
this.expanderContainer.appendChild(this.matchedExpander);
this.element.appendChild(this.matchedExpander);
this.nameNode = doc.createElementNS(HTML_NS, "td");
this.nameNode = doc.createElementNS(HTML_NS, "div");
this.element.appendChild(this.nameNode);
this.nameNode.setAttribute("class", "property-name");
this.nameNode.textContent = this.name;
this.nameNode.setAttribute("class", "property-name theme-fg-color5");
this.nameNode.textContent = this.nameNode.title = this.name;
this.nameNode.addEventListener("click", function(aEvent) {
this.matchedExpander.focus();
}.bind(this), false);
let helpcontainer = doc.createElementNS(HTML_NS, "td");
this.element.appendChild(helpcontainer);
helpcontainer.setAttribute("class", "helplink-container");
let helplink = doc.createElementNS(HTML_NS, "a");
helpcontainer.appendChild(helplink);
helplink.setAttribute("class", "helplink");
helplink.setAttribute("title", CssHtmlTree.HELP_LINK_TITLE);
helplink.textContent = CssHtmlTree.HELP_LINK_TITLE;
helplink.addEventListener("click", this.mdnLinkClick.bind(this), false);
this.valueNode = doc.createElementNS(HTML_NS, "td");
this.valueNode = doc.createElementNS(HTML_NS, "div");
this.element.appendChild(this.valueNode);
this.valueNode.setAttribute("class", "property-value");
this.valueNode.setAttribute("class", "property-value theme-fg-color1");
this.valueNode.setAttribute("dir", "ltr");
this.valueNode.textContent = this.value;
this.valueNode.textContent = this.valueNode.title = this.value;
return this.element;
},
@ -887,11 +691,10 @@ PropertyView.prototype = {
buildSelectorContainer: function PropertyView_buildSelectorContainer()
{
let doc = this.tree.styleDocument;
let element = doc.createElementNS(HTML_NS, "tr");
let element = doc.createElementNS(HTML_NS, "div");
element.setAttribute("class", this.propertyContentClassName);
this.matchedSelectorsContainer = doc.createElementNS(HTML_NS, "td");
this.matchedSelectorsContainer.setAttribute("colspan", "0");
this.matchedSelectorsContainer.setAttribute("class", "rulelink");
this.matchedSelectorsContainer = doc.createElementNS(HTML_NS, "div");
this.matchedSelectorsContainer.setAttribute("class", "matchedselectors");
element.appendChild(this.matchedSelectorsContainer);
return element;
@ -911,7 +714,7 @@ PropertyView.prototype = {
}
if (!this.tree.viewedElement || !this.visible) {
this.valueNode.textContent = "";
this.valueNode.textContent = this.valueNode.title = "";
this.matchedSelectorsContainer.parentNode.hidden = true;
this.matchedSelectorsContainer.textContent = "";
this.matchedExpander.removeAttribute("open");
@ -919,7 +722,7 @@ PropertyView.prototype = {
}
this.tree.numVisibleProperties++;
this.valueNode.textContent = this.propertyInfo.value;
this.valueNode.textContent = this.valueNode.title = this.propertyInfo.value;
this.refreshMatchedSelectors();
},
@ -1056,21 +859,12 @@ SelectorView.prototype = {
*/
get statusClass()
{
return SelectorView.CLASS_NAMES[this.selectorInfo.status];
return SelectorView.CLASS_NAMES[this.selectorInfo.status - 1];
},
/**
* A localized Get localized human readable info
*/
humanReadableText: function SelectorView_humanReadableText(aElement)
{
if (this.tree.getRTLAttr == "rtl") {
return this.selectorInfo.value + " \u2190 " + this.text(aElement);
} else {
return this.text(aElement) + " \u2192 " + this.selectorInfo.value;
}
},
text: function SelectorView_text(aElement) {
let result = this.selectorInfo.selector.text;
if (this.selectorInfo.elementStyle) {

View File

@ -863,21 +863,21 @@ TextProperty.prototype = {
* The CSS rule view can use this object to store metadata
* that might outlast the rule view, particularly the current
* set of disabled properties.
* @param {<iframe>} aOuterIFrame
* The iframe containing the ruleview.
* @constructor
*/
this.CssRuleView = function CssRuleView(aDoc, aStore)
{
this.doc = aDoc;
this.store = aStore;
this.element = this.doc.createElementNS(XUL_NS, "vbox");
this.element.setAttribute("tabindex", "0");
this.element = this.doc.createElementNS(HTML_NS, "div");
this.element.className = "ruleview devtools-monospace";
this.element.flex = 1;
this._boundCopy = this._onCopy.bind(this);
this.element.addEventListener("copy", this._boundCopy);
this._createContextMenu();
this._showEmpty();
}
@ -897,25 +897,8 @@ CssRuleView.prototype = {
this.clear();
this.element.removeEventListener("copy", this._boundCopy);
this._copyItem.removeEventListener("command", this._boundCopy);
delete this._boundCopy;
this._ruleItem.removeEventListener("command", this._boundCopyRule);
delete this._boundCopyRule;
this._declarationItem.removeEventListener("command", this._boundCopyDeclaration);
delete this._boundCopyDeclaration;
this._propertyItem.removeEventListener("command", this._boundCopyProperty);
delete this._boundCopyProperty;
this._propertyValueItem.removeEventListener("command", this._boundCopyPropertyValue);
delete this._boundCopyPropertyValue;
this._contextMenu.removeEventListener("popupshowing", this._boundMenuUpdate);
delete this._boundMenuUpdate;
delete this._contextMenu;
if (this.element.parentNode) {
this.element.parentNode.removeChild(this.element);
}
@ -1036,7 +1019,7 @@ CssRuleView.prototype = {
let inheritedSource = rule.inheritedSource;
if (inheritedSource != lastInheritedSource) {
let h2 = this.doc.createElementNS(HTML_NS, "div");
h2.className = "ruleview-rule-inheritance";
h2.className = "ruleview-rule-inheritance theme-gutter";
h2.textContent = inheritedSource;
lastInheritedSource = inheritedSource;
this.element.appendChild(h2);
@ -1050,104 +1033,6 @@ CssRuleView.prototype = {
}
},
/**
* Add a context menu to the rule view.
*/
_createContextMenu: function CssRuleView_createContextMenu()
{
let popupSet = this.doc.createElement("popupset");
this.doc.documentElement.appendChild(popupSet);
let menu = this.doc.createElement("menupopup");
menu.id = "rule-view-context-menu";
this._boundMenuUpdate = this._onMenuUpdate.bind(this);
menu.addEventListener("popupshowing", this._boundMenuUpdate);
// Copy selection
this._copyItem = createMenuItem(menu, {
label: "rule.contextmenu.copyselection",
accesskey: "rule.contextmenu.copyselection.accesskey",
command: this._boundCopy
});
// Copy rule
this._boundCopyRule = this._onCopyRule.bind(this);
this._ruleItem = createMenuItem(menu, {
label: "rule.contextmenu.copyrule",
accesskey: "rule.contextmenu.copyrule.accesskey",
command: this._boundCopyRule
});
// Copy declaration
this._boundCopyDeclaration = this._onCopyDeclaration.bind(this);
this._declarationItem = createMenuItem(menu, {
label: "rule.contextmenu.copydeclaration",
accesskey: "rule.contextmenu.copydeclaration.accesskey",
command: this._boundCopyDeclaration
});
this._boundCopyProperty = this._onCopyProperty.bind(this);
this._propertyItem = createMenuItem(menu, {
label: "rule.contextmenu.copyproperty",
accesskey: "rule.contextmenu.copyproperty.accesskey",
command: this._boundCopyProperty
});
this._boundCopyPropertyValue = this._onCopyPropertyValue.bind(this);
this._propertyValueItem = createMenuItem(menu,{
label: "rule.contextmenu.copypropertyvalue",
accesskey: "rule.contextmenu.copypropertyvalue.accesskey",
command: this._boundCopyPropertyValue
});
popupSet.appendChild(menu);
this.element.setAttribute("context", menu.id);
this._contextMenu = menu;
},
/**
* Update the rule view's context menu by disabling irrelevant menuitems and
* enabling relevant ones.
*
* @param {Event} aEvent
* The event object.
*/
_onMenuUpdate: function CssRuleView_onMenuUpdate(aEvent)
{
let node = this.doc.popupNode;
// Copy selection.
let editorSelection = node.className == "styleinspector-propertyeditor" &&
node.selectionEnd - node.selectionStart != 0;
let disable = this.doc.defaultView.getSelection().isCollapsed &&
!editorSelection;
this._copyItem.disabled = disable;
// Copy property, copy property name & copy property value.
if (!node) {
return;
}
if (!node.classList.contains("ruleview-property") &&
!node.classList.contains("ruleview-computed")) {
while (node = node.parentElement) {
if (node.classList.contains("ruleview-property") ||
node.classList.contains("ruleview-computed")) {
break;
}
}
}
let disablePropertyItems = !node || (node &&
!node.classList.contains("ruleview-property") &&
!node.classList.contains("ruleview-computed"));
this._declarationItem.disabled = disablePropertyItems;
this._propertyItem.disabled = disablePropertyItems;
this._propertyValueItem.disabled = disablePropertyItems;
},
/**
* Copy selected text from the rule view.
*
@ -1156,7 +1041,8 @@ CssRuleView.prototype = {
*/
_onCopy: function CssRuleView_onCopy(aEvent)
{
let target = this.doc.popupNode || aEvent.target;
let target = aEvent.target;
let text;
if (target.nodeName == "input") {
@ -1179,149 +1065,9 @@ CssRuleView.prototype = {
clipboardHelper.copyString(text, this.doc);
if (aEvent) {
aEvent.preventDefault();
}
aEvent.preventDefault();
},
/**
* Copy a rule from the rule view.
*
* @param {Event} aEvent
* The event object.
*/
_onCopyRule: function CssRuleView_onCopyRule(aEvent)
{
let terminator;
let node = this.doc.popupNode;
if (!node) {
return;
}
if (node.className != "ruleview-rule") {
while (node = node.parentElement) {
if (node.className == "ruleview-rule") {
break;
}
}
}
node = node.cloneNode();
let computedLists = node.querySelectorAll(".ruleview-computedlist");
for (let computedList of computedLists) {
computedList.parentNode.removeChild(computedList);
}
let autosizers = node.querySelectorAll(".autosizer");
for (let autosizer of autosizers) {
autosizer.parentNode.removeChild(autosizer);
}
let selector = node.querySelector(".ruleview-selector").textContent;
let propertyNames = node.querySelectorAll(".ruleview-propertyname");
let propertyValues = node.querySelectorAll(".ruleview-propertyvalue");
// Format the rule
if (osString == "WINNT") {
terminator = "\r\n";
} else {
terminator = "\n";
}
let out = selector + " {" + terminator;
for (let i = 0; i < propertyNames.length; i++) {
let name = propertyNames[i].textContent;
let value = propertyValues[i].textContent;
out += " " + name + ": " + value + ";" + terminator;
}
out += "}" + terminator;
clipboardHelper.copyString(out, this.doc);
},
/**
* Copy a declaration from the rule view.
*
* @param {Event} aEvent
* The event object.
*/
_onCopyDeclaration: function CssRuleView_onCopyDeclaration(aEvent)
{
let node = this.doc.popupNode;
if (!node) {
return;
}
if (!node.classList.contains("ruleview-property") &&
!node.classList.contains("ruleview-computed")) {
while (node = node.parentElement) {
if (node.classList.contains("ruleview-property") ||
node.classList.contains("ruleview-computed")) {
break;
}
}
}
// We need to strip expanded properties from the node because we use
// node.textContent below, which also gets text from hidden nodes. The
// simplest way to do this is to clone the node and remove them from the
// clone.
node = node.cloneNode();
let computedLists = node.querySelectorAll(".ruleview-computedlist");
for (let computedList of computedLists) {
computedList.parentNode.removeChild(computedList);
}
let propertyName = node.querySelector(".ruleview-propertyname").textContent;
let propertyValue = node.querySelector(".ruleview-propertyvalue").textContent;
let out = propertyName + ": " + propertyValue + ";";
clipboardHelper.copyString(out, this.doc);
},
/**
* Copy a property name from the rule view.
*
* @param {Event} aEvent
* The event object.
*/
_onCopyProperty: function CssRuleView_onCopyProperty(aEvent)
{
let node = this.doc.popupNode;
if (!node) {
return;
}
if (!node.classList.contains("ruleview-propertyname")) {
node = node.parentNode.parentNode.querySelector(".ruleview-propertyname");
}
if (node) {
clipboardHelper.copyString(node.textContent, this.doc);
}
},
/**
* Copy a property value from the rule view.
*
* @param {Event} aEvent
* The event object.
*/
_onCopyPropertyValue: function CssRuleView_onCopyPropertyValue(aEvent)
{
let node = this.doc.popupNode;
if (!node) {
return;
}
if (!node.classList.contains("ruleview-propertyvalue")) {
node = node.parentNode.parentNode.querySelector(".ruleview-propertyvalue");
}
if (node) {
clipboardHelper.copyString(node.textContent, this.doc);
}
}
};
/**
@ -1350,7 +1096,7 @@ RuleEditor.prototype = {
_create: function RuleEditor_create()
{
this.element = this.doc.createElementNS(HTML_NS, "div");
this.element.className = "ruleview-rule";
this.element.className = "ruleview-rule theme-separator";
this.element._ruleEditor = this;
// Give a relative position for the inplace editor's measurement
@ -1359,7 +1105,7 @@ RuleEditor.prototype = {
// Add the source link.
let source = createChild(this.element, "div", {
class: "ruleview-rule-source",
class: "ruleview-rule-source theme-link",
textContent: this.rule.title
});
source.addEventListener("click", function() {
@ -1378,7 +1124,7 @@ RuleEditor.prototype = {
let header = createChild(code, "div", {});
this.selectorText = createChild(header, "span", {
class: "ruleview-selector"
class: "ruleview-selector theme-fg-color3"
});
this.openBrace = createChild(header, "span", {
@ -1599,16 +1345,15 @@ TextPropertyEditor.prototype = {
this.element.classList.add("ruleview-property");
// The enable checkbox will disable or enable the rule.
this.enable = createChild(this.element, "input", {
class: "ruleview-enableproperty",
type: "checkbox",
this.enable = createChild(this.element, "div", {
class: "ruleview-enableproperty theme-checkbox",
tabindex: "-1"
});
this.enable.addEventListener("click", this._onEnableClicked, true);
// Click to expand the computed properties of the text property.
this.expander = createChild(this.element, "span", {
class: "ruleview-expander"
class: "ruleview-expander theme-twisty"
});
this.expander.addEventListener("click", this._onExpandClicked, true);
@ -1626,7 +1371,7 @@ TextPropertyEditor.prototype = {
// Property name, editable when focused. Property name
// is committed when the editor is unfocused.
this.nameSpan = createChild(this.nameContainer, "span", {
class: "ruleview-propertyname",
class: "ruleview-propertyname theme-fg-color5",
tabindex: "0",
});
@ -1657,7 +1402,7 @@ TextPropertyEditor.prototype = {
// property value are applied as they are typed, and reverted
// if the user presses escape.
this.valueSpan = createChild(propertyContainer, "span", {
class: "ruleview-propertyvalue",
class: "ruleview-propertyvalue theme-fg-color1",
tabindex: "0",
});
@ -1768,13 +1513,13 @@ TextPropertyEditor.prototype = {
}
createChild(li, "span", {
class: "ruleview-propertyname",
class: "ruleview-propertyname theme-fg-color5",
textContent: computed.name
});
appendText(li, ": ");
createChild(li, "span", {
class: "ruleview-propertyvalue",
class: "ruleview-propertyvalue theme-fg-color1",
textContent: computed.value
});
appendText(li, ";");
@ -1793,7 +1538,13 @@ TextPropertyEditor.prototype = {
*/
_onEnableClicked: function TextPropertyEditor_onEnableClicked(aEvent)
{
this.prop.setEnabled(this.enable.checked);
let checked = this.enable.hasAttribute("checked");
if (checked) {
this.enable.removeAttribute("checked");
} else {
this.enable.setAttribute("checked", "");
}
this.prop.setEnabled(!checked);
aEvent.stopPropagation();
},
@ -1802,8 +1553,12 @@ TextPropertyEditor.prototype = {
*/
_onExpandClicked: function TextPropertyEditor_onExpandClicked(aEvent)
{
this.expander.classList.toggle("styleinspector-open");
this.computed.classList.toggle("styleinspector-open");
if (this.computed.classList.contains("styleinspector-open")) {
this.expander.setAttribute("open", "true");
} else {
this.expander.removeAttribute("open");
}
aEvent.stopPropagation();
},
@ -2046,10 +1801,6 @@ XPCOMUtils.defineLazyGetter(this, "_strings", function() {
"chrome://browser/locale/devtools/styleinspector.properties");
});
XPCOMUtils.defineLazyGetter(this, "osString", function() {
return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
});
XPCOMUtils.defineLazyGetter(this, "domUtils", function() {
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
});

View File

@ -26,7 +26,7 @@ this.RuleViewTool = function RVT_RuleViewTool(aInspector, aWindow, aIFrame)
this.doc = aWindow.document;
this.outerIFrame = aIFrame;
this.view = new CssRuleView(this.doc);
this.view = new CssRuleView(this.doc, null);
this.doc.documentElement.appendChild(this.view.element);
this._changeHandler = function() {

View File

@ -0,0 +1,113 @@
<?xml version="1.0"?>
<!-- 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 window [
<!ENTITY % inspectorDTD SYSTEM "chrome://browser/locale/devtools/styleinspector.dtd">
%inspectorDTD;
<!ELEMENT loop ANY>
<!ATTLIST li foreach CDATA #IMPLIED>
<!ATTLIST div foreach CDATA #IMPLIED>
<!ATTLIST loop foreach CDATA #IMPLIED>
<!ATTLIST a target CDATA #IMPLIED>
<!ATTLIST a __pathElement CDATA #IMPLIED>
<!ATTLIST div _id CDATA #IMPLIED>
<!ATTLIST div save CDATA #IMPLIED>
<!ATTLIST table save CDATA #IMPLIED>
<!ATTLIST loop if CDATA #IMPLIED>
<!ATTLIST tr if CDATA #IMPLIED>
]>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
class="theme-body">
<head>
<title>&computedViewTitle;</title>
<link rel="stylesheet" href="chrome://global/skin/global.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/computedview.css" type="text/css"/>
<script type="application/javascript;version=1.8" src="theme-switching.js"/>
<script type="application/javascript;version=1.8">
window.setPanel = function(panel, iframe) {
Components.utils.import("resource:///modules/devtools/StyleInspector.jsm");
this.computedview = new ComputedViewTool(panel, window, iframe);
}
window.onunload = function() {
if (this.computedview) {
this.computedview.destroy();
}
}
</script>
</head>
<body>
<!-- The output from #templateProperty (below) is appended here. -->
<div id="propertyContainer" class="devtools-monospace">
</div>
<!-- When no properties are found the following block is displayed. -->
<div id="noResults" hidden="">
&noPropertiesFound;
</div>
<!-- The output from #templateRoot (below) is inserted here. -->
<div id="root" class="devtools-monospace"></div>
<!--
To visually debug the templates without running firefox, alter the display:none
-->
<div style="display:none;">
<!--
templateRoot sits at the top of the window and contains the "include default
styles" checkbox. For data it needs an instance of CssHtmlTree.
-->
<div id="templateRoot">
<xul:hbox class="devtools-toolbar" flex="1" align="center">
<xul:checkbox class="includebrowserstyles"
save="${includeBrowserStylesCheckbox}"
oncommand="${includeBrowserStylesChanged}" checked="false"
label="&browserStylesLabel;"/>
<xul:textbox class="devtools-searchinput" type="search" save="${searchField}"
placeholder="&userStylesSearch;" flex="1"
oncommand="${filterChanged}"/>
</xul:hbox>
</div>
<!--
A templateMatchedSelectors sits inside each templateProperties showing the
list of selectors that affect that property. Each needs data like this:
{
matchedSelectorViews: ..., // from cssHtmlTree.propertyViews[name].matchedSelectorViews
}
This is a template so the parent does not need to be a table, except that
using a div as the parent causes the DOM to muck with the tr elements
-->
<div id="templateMatchedSelectors">
<loop foreach="selector in ${matchedSelectorViews}">
<p>
<span class="rule-link">
<a target="_blank" class="link theme-link"
onclick="${selector.openStyleEditor}"
onkeydown="${selector.maybeOpenStyleEditor}"
title="${selector.selectorInfo.href}"
tabindex="0">${selector.selectorInfo.source}</a>
</span>
<span dir="ltr" class="rule-text ${selector.statusClass} theme-fg-color3" title="${selector.statusText}">
${selector.text(__element)}
<span class="other-property-value theme-fg-color1">${selector.selectorInfo.value}</span>
</span>
</p>
</loop>
</div>
</div>
</body>
</html>

View File

@ -1,110 +0,0 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?xml-stylesheet href="chrome://global/skin/global.css"?>
<?xml-stylesheet href="chrome://browser/content/devtools/styleinspector.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/devtools/csshtmltree.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/devtools/common.css" type="text/css"?>
<!DOCTYPE window [
<!ENTITY % inspectorDTD SYSTEM "chrome://browser/locale/devtools/styleinspector.dtd">
%inspectorDTD;
<!ELEMENT loop ANY>
<!ATTLIST li foreach CDATA #IMPLIED>
<!ATTLIST div foreach CDATA #IMPLIED>
<!ATTLIST loop foreach CDATA #IMPLIED>
<!ATTLIST a target CDATA #IMPLIED>
<!ATTLIST a __pathElement CDATA #IMPLIED>
<!ATTLIST div _id CDATA #IMPLIED>
<!ATTLIST div save CDATA #IMPLIED>
<!ATTLIST table save CDATA #IMPLIED>
<!ATTLIST loop if CDATA #IMPLIED>
<!ATTLIST tr if CDATA #IMPLIED>
]>
<xul:window xmlns="http://www.w3.org/1999/xhtml"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="&computedViewTitle;">
<script type="application/javascript;version=1.8">
window.setPanel = function(panel, iframe) {
Components.utils.import("resource:///modules/devtools/StyleInspector.jsm");
this.computedview = new ComputedViewTool(panel, window, iframe);
}
window.onunload = function() {
if (this.computedview) {
this.computedview.destroy();
}
}
</script>
<!-- The output from #templateRoot (below) is inserted here. -->
<div id="root" class="devtools-monospace"></div>
<!-- When no properties are found the following block is displayed. -->
<div id="noResults" hidden="">
&noPropertiesFound;
</div>
<!-- The output from #templateProperty (below) is appended here. -->
<table id="propertyContainer" class="devtools-monospace">
</table>
<xul:hbox id="footer">
<xul:label class="legendKey bestmatch">&bestMatch;</xul:label>
<xul:label class="legendKey matched">&matched;</xul:label>
<xul:label class="legendKey parentmatch">&parentMatch;</xul:label>
</xul:hbox>
<!--
To visually debug the templates without running firefox, alter the display:none
-->
<div style="display:none;">
<!--
templateRoot sits at the top of the window and contains the "include default
styles" checkbox. For data it needs an instance of CssHtmlTree.
-->
<div id="templateRoot">
<xul:hbox class="headerControls" flex="1" align="center">
<xul:checkbox class="includebrowserstyles"
save="${includeBrowserStylesCheckbox}"
oncommand="${includeBrowserStylesChanged}" checked="false"
label="&browserStylesLabel;"/>
<xul:textbox class="searchfield" type="search" save="${searchField}"
placeholder="&userStylesSearch;" flex="1"
oncommand="${filterChanged}"/>
</xul:hbox>
</div>
<!--
A templateMatchedSelectors sits inside each templateProperties showing the
list of selectors that affect that property. Each needs data like this:
{
matchedSelectorViews: ..., // from cssHtmlTree.propertyViews[name].matchedSelectorViews
}
This is a template so the parent does not need to be a table, except that
using a div as the parent causes the DOM to muck with the tr elements
-->
<div id="templateMatchedSelectors">
<table>
<loop foreach="selector in ${matchedSelectorViews}">
<tr>
<td dir="ltr" class="rule-text ${selector.statusClass}">
${selector.humanReadableText(__element)}
</td>
<td class="rule-link">
<a target="_blank" class="link"
onclick="${selector.openStyleEditor}"
onkeydown="${selector.maybeOpenStyleEditor}"
title="${selector.selectorInfo.href}"
tabindex="0">${selector.selectorInfo.source}</a>
</td>
</tr>
</loop>
</table>
</div>
</div>
</xul:window>

View File

@ -0,0 +1,37 @@
<?xml version="1.0"?>
<!-- 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 window [
<!ENTITY % inspectorDTD SYSTEM "chrome://browser/locale/devtools/styleinspector.dtd">
%inspectorDTD;
]>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
class="theme-body">
<head>
<title>&ruleViewTitle;</title>
<link rel="stylesheet" href="chrome://global/skin/global.css" type="text/css"/>
<link rel="stylesheet" href="chrome://browser/skin/devtools/common.css" type="text/css"/>
<link rel="stylesheet" href="chrome://browser/content/devtools/ruleview.css" type="text/css"/>
<link rel="stylesheet" href="chrome://browser/skin/devtools/ruleview.css" type="text/css"/>
<script type="application/javascript;version=1.8" src="theme-switching.js"/>
<script type="application/javascript;version=1.8">
window.setPanel = function(panel, iframe) {
Components.utils.import("resource:///modules/devtools/StyleInspector.jsm");
this.ruleview = new RuleViewTool(panel, window, iframe);
}
window.onunload = function() {
if (this.ruleview) {
this.ruleview.destroy();
}
}
</script>
</head>
</html>

View File

@ -1,26 +0,0 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?xml-stylesheet href="chrome://global/skin/global.css"?>
<?xml-stylesheet href="chrome://browser/content/devtools/styleinspector.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/devtools/csshtmltree.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/devtools/common.css" type="text/css"?>
<!DOCTYPE window [
<!ENTITY % inspectorDTD SYSTEM "chrome://browser/locale/devtools/styleinspector.dtd">
%inspectorDTD;
]>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" title="&ruleViewTitle;">
<script type="application/javascript;version=1.8">
window.setPanel = function(panel, iframe) {
Components.utils.import("resource:///modules/devtools/StyleInspector.jsm");
this.ruleview = new RuleViewTool(panel, window, iframe);
}
window.onunload = function() {
if (this.ruleview) {
this.ruleview.destroy();
}
}
</script>
</window>

View File

@ -6,38 +6,11 @@
display: -moz-box;
}
.helplink {
display: block;
}
.expander,
.property-name,
.ruleview-propertyname,
.ruleview-warning,
.ruleview-expander {
display: inline-block;
}
#propertyContainer {
display: -moz-box;
-moz-box-orient: vertical;
-moz-box-flex: 1;
overflow-y: auto;
-moz-user-select: text;
}
.ruleview {
overflow: auto;
-moz-user-select: text;
}
.property-view-hidden,
.property-content-hidden,
.ruleview-computedlist:not(.styleinspector-open),
.ruleview-warning[hidden] {
display: none;
}
.ruleview-code {
direction: ltr;
}
@ -54,3 +27,8 @@
cursor: text;
padding-right: 15px;
}
.ruleview-computedlist:not(.styleinspector-open),
.ruleview-warning[hidden] {
display: none;
}

View File

@ -23,7 +23,7 @@ MOCHITEST_BROWSER_FILES = \
browser_ruleview_734259_style_editor_link.js \
browser_ruleview_editor.js \
browser_ruleview_editor_changedvalues.js \
browser_ruleview_bug_703643_context_menu_copy.js \
browser_ruleview_copy.js \
browser_ruleview_focus.js \
browser_ruleview_inherit.js \
browser_ruleview_manipulation.js \
@ -36,7 +36,7 @@ MOCHITEST_BROWSER_FILES = \
browser_bug_592743_specificity.js \
browser_bug722691_rule_view_increment.js \
browser_computedview_734259_style_editor_link.js \
browser_computedview_bug_703643_context_menu_copy.js\
browser_computedview_copy.js\
head.js \
$(NULL)

View File

@ -23,7 +23,7 @@ function setUpTests()
'background-color: #000000; >"'+
'</div>';
let testElement = doc.getElementById("test");
ruleDialog = openDialog("chrome://browser/content/devtools/cssruleview.xul",
ruleDialog = openDialog("chrome://browser/content/devtools/cssruleview.xhtml",
"cssruleviewtest",
"width=350,height=350");
ruleDialog.addEventListener("load", function onLoad(evt) {

View File

@ -52,20 +52,12 @@ function SI_checkText()
propertyView.matchedExpanded = true;
propertyView.refreshMatchedSelectors();
let td = propertyView.matchedSelectorsContainer.querySelector("td.rule-text");
ok(td, "found the first table row");
let span = propertyView.matchedSelectorsContainer.querySelector("span.rule-text");
ok(span, "found the first table row");
let selector = propertyView.matchedSelectorViews[0];
ok(selector, "found the first matched selector view");
try {
is(td.textContent.trim(), selector.humanReadableText(td).trim(),
"selector text is correct");
} catch (ex) {
info("EXCEPTION: " + ex);
ok(false, "getting the selector text should not raise an exception");
}
finishUp();
}

View File

@ -63,56 +63,7 @@ function runStyleInspectorTests()
let prop = contentDocument.querySelector(".property-view");
ok(prop, "captain, we have the property-view node");
// We need the context menu to open in the correct place in order for
// popupNode to be propertly set.
contextMenuClick(prop);
checkCopyProperty();
}
function checkCopyProperty()
{
info("Checking that cssHtmlTree.siBoundCopyDeclaration() returns the " +
"correct clipboard value");
let expectedPattern = "color: rgb\\(255, 255, 0\\);";
SimpleTest.waitForClipboard(function CS_boundCopyPropCheck() {
return checkClipboardData(expectedPattern);
},
computedView.siBoundCopyDeclaration,
checkCopyPropertyName, function() {
failedClipboard(expectedPattern, checkCopyPropertyName);
});
}
function checkCopyPropertyName()
{
info("Checking that cssHtmlTree.siBoundCopyProperty() returns the " +
"correct clipboard value");
let expectedPattern = "color";
SimpleTest.waitForClipboard(function CS_boundCopyPropNameCheck() {
return checkClipboardData(expectedPattern);
},
computedView.siBoundCopyProperty,
checkCopyPropertyValue, function() {
failedClipboard(expectedPattern, checkCopyPropertyValue);
});
}
function checkCopyPropertyValue()
{
info("Checking that cssHtmlTree.siBoundCopyPropertyValue() returns the " +
"correct clipboard value");
let expectedPattern = "rgb\\(255, 255, 0\\)";
SimpleTest.waitForClipboard(function CS_boundCopyPropValueCheck() {
return checkClipboardData(expectedPattern);
},
computedView.siBoundCopyPropertyValue,
checkCopySelection, function() {
failedClipboard(expectedPattern, checkCopySelection);
});
checkCopySelection();
}
function checkCopySelection()
@ -123,21 +74,21 @@ function checkCopySelection()
let range = document.createRange();
range.setStart(props[0], 0);
range.setEnd(props[3], 4);
range.setEnd(props[3], 3);
win.getSelection().addRange(range);
info("Checking that cssHtmlTree.siBoundCopy() " +
" returns the correct clipboard value");
let expectedPattern = "color: rgb\\(255, 255, 0\\)[\\r\\n]+" +
"font-family: helvetica,sans-serif[\\r\\n]+" +
"font-size: 16px[\\r\\n]+" +
"font-variant: small-caps[\\r\\n]*";
let expectedPattern = "color: rgb\\(255, 255, 0\\);[\\r\\n]+" +
"font-family: helvetica,sans-serif;[\\r\\n]+" +
"font-size: 16px;[\\r\\n]+" +
"font-variant: small-caps;[\\r\\n]*";
SimpleTest.waitForClipboard(function CS_boundCopyCheck() {
return checkClipboardData(expectedPattern);
},
computedView.siBoundCopy, closeStyleInspector, function() {
function() {fireCopyEvent(props[0])}, closeStyleInspector, function() {
failedClipboard(expectedPattern, closeStyleInspector);
});
}

View File

@ -47,110 +47,13 @@ function highlightNode()
inspector.selection.once("new-node", function() {
is(inspector.selection.node, div, "selection matches the div element");
testClip();
executeSoon(checkCopySelection);
});
executeSoon(function() {
inspector.selection.setNode(div);
});
}
function testClip()
{
executeSoon(function() {
info("Checking that _onCopyRule() returns " +
"the correct clipboard value");
let expectedPattern = "element {[\\r\\n]+" +
" margin: 10em;[\\r\\n]+" +
" font-size: 14pt;[\\r\\n]+" +
" font-family: helvetica,sans-serif;[\\r\\n]+" +
" color: rgb\\(170, 170, 170\\);[\\r\\n]+" +
"}[\\r\\n]*";
SimpleTest.waitForClipboard(function IUI_boundCopyPropCheck() {
return checkClipboardData(expectedPattern);
},
checkCopyRule, checkCopyProperty, function() {
failedClipboard(expectedPattern, checkCopyProperty);
});
});
}
function checkCopyRule() {
let contentDoc = win.document;
let props = contentDoc.querySelectorAll(".ruleview-property");
is(props.length, 5, "checking property length");
let prop = props[2];
let propName = prop.querySelector(".ruleview-propertyname").textContent;
let propValue = prop.querySelector(".ruleview-propertyvalue").textContent;
is(propName, "font-family", "checking property name");
is(propValue, "helvetica,sans-serif", "checking property value");
// We need the context menu to open in the correct place in order for
// popupNode to be propertly set.
contextMenuClick(prop);
ruleView()._boundCopyRule();
let menu = contentDoc.querySelector("#rule-view-context-menu");
ok(menu, "we have the context menu");
menu.hidePopup();
}
function checkCopyProperty()
{
let contentDoc = win.document;
let props = contentDoc.querySelectorAll(".ruleview-property");
let prop = props[2];
info("Checking that _onCopyDeclaration() returns " +
"the correct clipboard value");
let expectedPattern = "font-family: helvetica,sans-serif;";
// We need the context menu to open in the correct place in order for
// popupNode to be propertly set.
contextMenuClick(prop);
SimpleTest.waitForClipboard(function IUI_boundCopyPropCheck() {
return checkClipboardData(expectedPattern);
},
ruleView()._boundCopyDeclaration,
checkCopyPropertyName, function() {
failedClipboard(expectedPattern, checkCopyPropertyName);
});
}
function checkCopyPropertyName()
{
info("Checking that _onCopyProperty() returns " +
"the correct clipboard value");
let expectedPattern = "margin";
SimpleTest.waitForClipboard(function IUI_boundCopyPropNameCheck() {
return checkClipboardData(expectedPattern);
},
ruleView()._boundCopyProperty,
checkCopyPropertyValue, function() {
failedClipboard(expectedPattern, checkCopyPropertyValue);
});
}
function checkCopyPropertyValue()
{
info("Checking that _onCopyPropertyValue() " +
" returns the correct clipboard value");
let expectedPattern = "10em";
SimpleTest.waitForClipboard(function IUI_boundCopyPropValueCheck() {
return checkClipboardData(expectedPattern);
},
ruleView()._boundCopyPropertyValue,
checkCopySelection, function() {
failedClipboard(expectedPattern, checkCopySelection);
});
}
function checkCopySelection()
{
let contentDoc = win.document;
@ -176,51 +79,11 @@ function checkCopySelection()
SimpleTest.waitForClipboard(function IUI_boundCopyCheck() {
return checkClipboardData(expectedPattern);
},ruleView()._boundCopy, testSimpleCopy, function() {
failedClipboard(expectedPattern, testSimpleCopy);
},function() {fireCopyEvent(props[0])}, finishup, function() {
failedClipboard(expectedPattern, finishup);
});
}
function testSimpleCopy()
{
executeSoon(function() {
info("Checking that _onCopy() returns the correct clipboard value");
let expectedPattern = "element {[\\r\\n]+" +
" margin: 10em;[\\r\\n]+" +
" font-size: 14pt;[\\r\\n]+" +
" font-family: helvetica,sans-serif;[\\r\\n]+" +
" color: rgb\\(170, 170, 170\\);[\\r\\n]+" +
"}[\\r\\n]*";
SimpleTest.waitForClipboard(function IUI_testSimpleCopy() {
return checkClipboardData(expectedPattern);
},
checkSimpleCopy, finishup, function() {
failedClipboard(expectedPattern, finishup);
});
});
}
function checkSimpleCopy() {
let contentDoc = win.document;
let props = contentDoc.querySelectorAll(".ruleview-code");
is(props.length, 2, "checking property length");
let prop = props[0];
selectNode(prop);
// We need the context menu to open in the correct place in order for
// popupNode to be propertly set.
contextMenuClick(prop);
ruleView()._boundCopy();
let menu = contentDoc.querySelector("#rule-view-context-menu");
ok(menu, "we have the context menu");
menu.hidePopup();
}
function selectNode(aNode) {
let doc = aNode.ownerDocument;
let win = doc.defaultView;

View File

@ -37,7 +37,7 @@ function startTest()
doc.body.innerHTML = '<div id="testid" class="testclass">Styled Node</div>';
let testElement = doc.getElementById("testid");
ruleDialog = openDialog("chrome://browser/content/devtools/cssruleview.xul",
ruleDialog = openDialog("chrome://browser/content/devtools/cssruleview.xhtml",
"cssruleviewtest",
"width=200,height=350");
ruleDialog.addEventListener("load", function onLoad(evt) {

View File

@ -37,7 +37,7 @@ function startTest()
doc.body.innerHTML = '<div id="testid" class="testclass">Styled Node</div>';
let testElement = doc.getElementById("testid");
ruleDialog = openDialog("chrome://browser/content/devtools/cssruleview.xul",
ruleDialog = openDialog("chrome://browser/content/devtools/cssruleview.xhtml",
"cssruleviewtest",
"width=200,height=350");
ruleDialog.addEventListener("load", function onLoad(evt) {

View File

@ -29,7 +29,7 @@ function startTest()
let elementStyle = 'margin-top: 1px; padding-top: 5px;'
testElement.setAttribute("style", elementStyle);
ruleDialog = openDialog("chrome://browser/content/devtools/cssruleview.xul",
ruleDialog = openDialog("chrome://browser/content/devtools/cssruleview.xhtml",
"cssruleviewtest",
"width=200,height=350");
ruleDialog.addEventListener("load", function onLoad(evt) {

View File

@ -67,7 +67,7 @@ function SI_AddFilterText()
Services.obs.removeObserver(SI_AddFilterText, "StyleInspector-populated", false);
let doc = computedView.styleDocument;
let searchbar = doc.querySelector(".searchfield");
let searchbar = doc.querySelector(".devtools-searchinput");
Services.obs.addObserver(SI_checkFilter, "StyleInspector-populated", false);
info("setting filter text to \"color\"");
searchbar.focus();

View File

@ -99,6 +99,12 @@ function waitForEditorBlur(aEditor, aCallback)
}, false);
}
function fireCopyEvent(element) {
let evt = element.ownerDocument.createEvent("Event");
evt.initEvent("copy", true, true);
element.dispatchEvent(evt);
}
function contextMenuClick(element) {
var evt = element.ownerDocument.createEvent('MouseEvents');

View File

@ -27,14 +27,6 @@
- displayed. -->
<!ENTITY noPropertiesFound "No CSS properties found.">
<!-- LOCALIZATION NOTE (bestMatch, matched, parentMatch): For each style
- property the panel shows the rules containing that property. For every
- rule, the rule status is also displayed: a rule can be the best match, a
- match or a parent match. -->
<!ENTITY bestMatch "Best Match">
<!ENTITY matched "Matched">
<!ENTITY parentMatch "Parent Match">
<!-- FIXME: notes -->
<!ENTITY computedViewTitle "Computed">
<!ENTITY ruleViewTitle "Rules">

View File

@ -46,78 +46,6 @@ helpLinkTitle=Read the documentation for this property
# the title attribute of the warning icon.
rule.warning.title=Invalid property value
# LOCALIZATION NOTE (style.contextmenu.copyselection): The computed view's
# context menu copy entry.
style.contextmenu.copyselection=Copy selection
# LOCALIZATION NOTE (style.contextmenu.copyselection.accesskey): The computed
# view's context menu copy entry access key.
style.contextmenu.copyselection.accesskey=C
# LOCALIZATION NOTE (style.contextmenu.copydeclaration): The style inspector's
# context menu copy property entry allows a complete CSS property to be copied.
style.contextmenu.copydeclaration=Copy declaration line
# LOCALIZATION NOTE (style.contextmenu.copydeclaration.accesskey): The style
# inspector's context menu copy property access key.
style.contextmenu.copydeclaration.accesskey=D
# LOCALIZATION NOTE (style.contextmenu.copyproperty): The style inspector's
# context menu copy property name entry allows a CSS property name to be copied.
style.contextmenu.copyproperty=Copy property
# LOCALIZATION NOTE (style.contextmenu.copyproperty.accesskey): The style
# inspector's context menu copy property name access key.
style.contextmenu.copyproperty.accesskey=P
# LOCALIZATION NOTE (style.contextmenu.copypropertyvalue): The style inspector's
# context menu copy property value entry allows a CSS property name to be copied.
style.contextmenu.copypropertyvalue=Copy property value
# LOCALIZATION NOTE (style.contextmenu.copypropertyvalue.accesskey): The style
# inspector's context menu copy property value access key.
style.contextmenu.copypropertyvalue.accesskey=U
# LOCALIZATION NOTE (rule.contextmenu.copyselection): The rule view's context
# menu copy entry.
rule.contextmenu.copyselection=Copy selection
# LOCALIZATION NOTE (rule.contextmenu.copyselection.accesskey): The rule view's
# context menu copy entry access key.
rule.contextmenu.copyselection.accesskey=C
# LOCALIZATION NOTE (rule.contextmenu.copyrule): The rule view's context menu
# copy rule entry allows a complete CSS rule to be copied.
rule.contextmenu.copyrule=Copy rule
# LOCALIZATION NOTE (rule.contextmenu.copyrule.accesskey): The rule view's
# context menu copy rule access key.
rule.contextmenu.copyrule.accesskey=R
# LOCALIZATION NOTE (rule.contextmenu.copydeclaration): The rule view's context
# menu copy property entry allows a complete CSS property to be copied.
rule.contextmenu.copydeclaration=Copy declaration line
# LOCALIZATION NOTE (rule.contextmenu.copydeclaration.accesskey): The rule view's
# context menu copy property access key.
rule.contextmenu.copydeclaration.accesskey=D
# LOCALIZATION NOTE (rule.contextmenu.copyproperty): The rule view's context
# menu copy property entry allows a CSS property name to be copied.
rule.contextmenu.copyproperty=Copy property
# LOCALIZATION NOTE (rule.contextmenu.copyproperty.accesskey): The rule
# view's context menu copy property name access key.
rule.contextmenu.copyproperty.accesskey=P
# LOCALIZATION NOTE (rule.contextmenu.copypropertyvalue): The rule view's
# context menu copy property entry allows a CSS property value to be copied.
rule.contextmenu.copypropertyvalue=Copy property value
# LOCALIZATION NOTE (rule.contextmenu.copypropertyvalue.accesskey): The rule
# view's context menu copy property value access key.
rule.contextmenu.copypropertyvalue.accesskey=U
# LOCALIZATION NOTE (ruleView.empty): Text displayed when the highlighter is
# first opened and there's no node selected in the rule view.
rule.empty=No element selected.

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

View File

@ -139,6 +139,7 @@
.devtools-searchinput {
-moz-appearance: none;
margin: 0 3px;
min-height: 22px;
border: 1px solid hsla(210,8%,5%,.6);
border-radius: 2px;
background-color: transparent;
@ -335,34 +336,4 @@
box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset, 0 -2px 0 hsla(206,37%,4%,.05) inset, 0 -1px 1px hsla(206,37%,4%,.1) inset;
}
/* Theme */
.devtools-theme-background {
background-color: white;
}
.devtools-theme-comment {
color: hsl(90,2%,46%); /* grey */
}
.devtools-theme-keyword {
color: hsl(276,44%,45%); /* purple */
}
.devtools-theme-string {
color: hsl(72,100%,27%); /* green */
}
.devtools-theme-tagname {
color: hsl(208,81%,21%); /* dark blue */
}
.devtools-theme-attrname {
color: hsl(208,56%,40%); /* blue */
}
.devtools-theme-attrvalue {
color: hsl(24,85%,39%); /* orange */
}
%include ../../shared/devtools/common.inc.css

View File

@ -0,0 +1,157 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* 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/. */
* {
-moz-box-sizing: border-box;
}
:root {
height: 100%;
}
body {
margin: 0;
display : flex;
flex-direction: column;
height: 100%;
}
#propertyContainer {
-moz-user-select: text;
overflow: auto;
min-height: 0;
flex: 1;
}
.property-view-hidden,
.property-content-hidden {
display: none;
}
.property-view {
clear: both;
padding: 2px 0 2px 17px;
}
.property-view > * {
display: inline-block;
vertical-align: middle;
}
.property-name {
width: 50%;
overflow-x: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.property-value {
width: 50%;
max-width: 100%;
overflow-x: hidden;
text-overflow: ellipsis;
white-space: nowrap;
background-image: url(arrow-e.png);
background-repeat: no-repeat;
background-size: 5px 8px;
background-position: 2px center;
padding-left: 10px;
}
.other-property-value {
background-image: url(arrow-e.png);
background-repeat: no-repeat;
background-size: 5px 8px;
background-position: left center;
padding-left: 8px;
}
@media (min-width: 400px) {
.property-name {
width: 200px;
}
.property-value {
width: auto;
}
}
.property-content {
padding-left: 17px;
}
/* From skin */
.helplink {
/* FIXME: remove this image
background-image: url("chrome://browser/skin/devtools/goto-mdn.png");
*/
}
.expander {
visibility: hidden;
margin-left: -12px!important;
}
.expander[open] {
margin-left: -17px!important;
}
.expandable {
visibility: visible;
}
.match {
visibility: hidden;
}
.matchedselectors > p {
clear: both;
margin: 0 2px 0 0;
padding: 2px;
overflow-x: hidden;
border-style: dotted;
border-color: rgba(128,128,128,0.4);
border-width: 1px 1px 0 1px;
}
.matchedselectors > p:last-of-type {
border-bottom-width: 1px;
}
/* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
.rule-text {
direction: ltr;
}
.matched {
text-decoration: line-through;
}
.parentmatch {
opacity: 0.5;
}
#noResults {
font-size: 110%;
margin: 5px;
text-align: center;
}
.onlyuserstyles {
cursor: pointer;
}
.legendKey {
margin: 0 5px;
}
.devtools-toolbar {
width: 100%;
}
.link {
padding: 0 3px;
cursor: pointer;
float: right;
}

View File

@ -1,293 +0,0 @@
/* 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/. */
:root {
-moz-appearance: none;
background: -moz-Field;
color: -moz-FieldText;
font: message-box;
font-family: monospace;
}
/* Take away these two :visited rules to get a core dumper */
/* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
.link,
.link:visited {
color: #0091ff;
}
.link,
.helplink,
.link:visited,
.helplink:visited {
text-decoration: none;
}
.link:hover {
text-decoration: underline;
}
.helplink {
height: 14px;
width: 0;
overflow: hidden;
-moz-padding-start: 14px;
background-image: url("chrome://browser/skin/devtools/goto-mdn.png");
-moz-margin-end: 2px;
cursor: pointer;
}
.property-view:not(:hover) > .helplink-container {
visibility: hidden;
}
.rulelink {
color: -moz-dialogtext;
padding: 0;
}
.expander {
-moz-appearance: treetwisty;
padding-top: 12px;
-moz-margin-start: 5px;
vertical-align: middle;
}
.expander[open] {
-moz-appearance: treetwistyopen;
}
.match {
visibility: hidden;
}
.expandable {
cursor: pointer;
visibility: visible;
}
.expander-container {
vertical-align: text-top;
}
.property-name {
padding: 2px 0;
color: -moz-FieldText;
}
.property-value {
padding: 0;
-moz-padding-end: 6px;
color: grey;
width: 100%;
}
.rule-link {
text-align: end;
-moz-padding-start: 10px;
cursor: pointer;
}
/* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
.rule-text {
direction: ltr;
padding: 0;
-moz-padding-start: 20px;
vertical-align: text-bottom;
}
.bestmatch {
color: black;
}
.matched {
text-decoration: line-through;
}
.parentmatch {
color: #666;
}
#propertyContainer {
border-collapse: collapse;
}
.darkrow {
background-color: rgba(0,0,0,.022);
}
#noResults {
font-size: 18px;
margin-top: 5px;
text-align: center;
}
.headerControls {
color: -moz-dialogtext;
background-color: -moz-dialog;
}
.includebrowserstyles {
cursor: pointer;
font-size: 11px;
}
#footer {
border-top: 1px solid -moz-dialog;
}
.legendKey {
margin: 0 5px;
}
/**
* CSS Rule View
*/
.ruleview {
background-color: white;
}
.ruleview-rule-source {
color: hsl(90,2%,46%); /* grey */
-moz-padding-start: 5px;
cursor: pointer;
text-align: right;
float: right;
-moz-user-select: none;
}
.ruleview-rule-inheritance {
background-color: hsl(0,0%,90%);
color: hsl(0,0%,50%);
border-top: 1px solid hsl(0,0%,65%);
border-bottom: 1px solid hsl(0,0%,65%);
padding: 1px 4px;
margin-top: 4px;
-moz-user-select: none;
}
.ruleview-rule-source:hover {
text-decoration: underline;
}
.ruleview-rule {
padding: 2px 4px;
}
.ruleview-rule + .ruleview-rule {
border-top: 1px dotted #cddae5;
}
.ruleview-warning {
background: url("chrome://browser/skin/devtools/alerticon-warning.png");
-moz-margin-start: 5px;
vertical-align: middle;
width: 13px;
height: 12px;
}
.ruleview-ruleopen {
-moz-padding-end: 5px;
}
.ruleview-ruleclose {
cursor: text;
padding-right: 20px;
}
.ruleview-propertylist {
list-style: none;
padding: 0;
margin: 0;
}
.ruleview-enableproperty {
height: 10px;
width: 10px;
-moz-margin-start: 1px;
-moz-margin-end: 0;
transition: opacity 100ms;
transition-delay: 200ms;
}
.ruleview-property:not(:hover) > .ruleview-enableproperty[checked] {
opacity: 0;
transition: none;
}
.ruleview-expander {
width: 8px;
height: 8px;
background: url("chrome://browser/skin/devtools/arrows.png") 24px 0;
cursor: pointer;
-moz-margin-start: 2px;
-moz-margin-end: 5px;
}
.ruleview-expander.styleinspector-open {
background-position: 8px 0;
}
.ruleview-newproperty {
/* (enable checkbox width: 12px) + (expander width: 15px) */
-moz-margin-start: 27px;
}
.ruleview-propertyname {
padding: 1px 0;
color: hsl(276,44%,45%); /* purple */
}
.ruleview-propertyvalue {
padding: 1px 0;
}
.ruleview-namecontainer,
.ruleview-propertycontainer,
.ruleview-propertyname,
.ruleview-propertyvalue {
text-decoration: inherit;
}
.ruleview-computedlist {
list-style: none;
padding: 0;
}
.ruleview-computed {
-moz-margin-start: 4em;
}
.ruleview-overridden {
text-decoration: line-through;
}
.styleinspector-propertyeditor {
border: 1px solid #CCC;
padding: 0;
box-shadow: 2px 2px 2px #CCC;
}
.ruleview-property {
border-left: 2px solid transparent;
}
.ruleview-property > * {
vertical-align: middle;
}
.ruleview-property[dirty] {
border-left-color: #68E268;
}
.ruleview-namecontainer > .ruleview-propertyname,
.ruleview-propertycontainer > .ruleview-propertyvalue {
border-bottom: 1px dashed transparent;
}
.ruleview-namecontainer:hover > .ruleview-propertyname,
.ruleview-propertycontainer:hover > .ruleview-propertyvalue {
border-bottom-color: hsl(0,0%,50%);
}
.ruleview-selector-separator, .ruleview-selector-unmatched {
color: #888;
}

View File

@ -0,0 +1,107 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* 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/. */
/* According to:
* https://bugzilla.mozilla.org/show_bug.cgi?id=715472#c17
*/
.theme-body {
background: #131c26;
color: #8fa1b2
}
.theme-twisty {
cursor: pointer;
margin-right: 5px;
}
.theme-twisty:-moz-focusring {
outline-style: none;
}
.theme-twisty:not([open]) {
width: 0;
height: 0;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-left: 5px solid rgba(255,255,255,0.5);
margin-left: 5px;
}
.theme-twisty[open] {
width: 10px;
height: 10px;
background-image: linear-gradient(to bottom right, transparent 68%, rgba(255,255,255,0.5) 68%);
}
.theme-checkbox {
display: inline-block;
border: 1px solid rgba(160,160,160,0.4);
width: 6px;
height: 6px;
padding: 2px;
background-color: transparent;
background-repeat: no-repeat;
outline: none;
}
.theme-checkbox[checked] {
background-clip: content-box;
background-image: linear-gradient(to bottom right, transparent 48%, rgba(160,160,160,1) 48%, rgba(160,160,160,1) 52%, transparent 52%),
linear-gradient(to bottom left, transparent 48%, rgba(160,160,160,1) 48%, rgba(160,160,160,1) 52%, transparent 52%);
}
.theme-selected {
background: #26384E;
}
.theme-bg-darker {
background-color: rgba(0,0,0,0.1);
}
.theme-link { /* blue */
color: #3689b2;
}
.theme-comment { /* grey */
color: #5c6773;
}
.theme-gutter {
background-color: #0f171f;
color: #667380;
border-color: #303b47;
}
.theme-separator { /* grey */
border-color: #303b47;
}
.theme-fg-color1 { /* green */
color: #5c9966;
}
.theme-fg-color2 { /* blue */
color: #3689b2;
}
.theme-fg-color3 { /* pink/lavender */
color: #a673bf;
}
.theme-fg-color4 { /* purple/violet */
color: #6270b2;
}
.theme-fg-color5 { /* Yellow */
color: #a18650;
}
.theme-fg-color6 { /* Orange */
color: #b26b47;
}
.theme-fg-color7 { /* Red */
color: #bf5656;
}

View File

@ -0,0 +1,10 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* 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/. */
@import url("floating-scrollbars.css");
scrollbar thumb {
background-color: rgba(170,170,170,0.2) !important;
}

View File

@ -10,21 +10,21 @@ scrollbar {
}
scrollbar[orient="vertical"] {
-moz-margin-start: -8px;
min-width: 8px;
max-width: 8px;
-moz-margin-start: -10px;
min-width: 10px;
max-width: 10px;
}
scrollbar[orient="horizontal"] {
margin-top: -8px;
min-height: 8px;
max-height: 8px;
margin-top: -10px;
min-height: 10px;
max-height: 10px;
}
scrollbar thumb {
-moz-appearance: none !important;
border-width: 0px !important;
background-color: rgba(0,0,0,0.2) !important;
background-color: rgba(170,170,170,0.2) !important;
border-radius: 3px !important;
}

View File

@ -3,7 +3,6 @@
}
body {
background: #F9F9F9;
margin: 0;
padding-bottom: 20px;
}
@ -24,16 +23,23 @@ body {
}
.font {
border-bottom: 1px solid #DDD;
padding: 10px 5px;
font-size: 0;
}
.theme-dark .font {
border-bottom: 1px solid #444;
}
.theme-light .font {
border-bottom: 1px solid #DDD;
}
.font:last-of-type {
border-bottom: 0;
}
.font:nth-child(even) {
.theme-light .font:nth-child(even) {
background: #F4F4F4;
}
@ -57,23 +63,18 @@ body {
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 {
.theme-light .font-css-code,
.theme-light .font-url {
border: 1px solid #CCC;
color: #888;
background: white;
}
.font-url:focus {
color: black;
.theme-dark .font-css-code,
.theme-dark .font-url {
border: 1px solid #333;
background: black;
color: white;
}

View File

@ -2,14 +2,17 @@
* 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/. */
body {
background: url(layout-background-grid.png), -moz-radial-gradient(50% 70%, circle cover, hsl(210,53%,45%) 0%, hsl(210,54%,33%) 100%);
color: hsl(210,100%,85%);
-moz-box-sizing: border-box;
.theme-dark .theme-body {
background-image: url(layout-background-grid.png);
}
#element-size {
color: hsl(210,100%,95%);
.theme-light .theme-body {
background-image: url(layout-background-grid.png), -moz-radial-gradient(50% 70%, circle cover, hsl(210,53%,45%) 0%, hsl(210,54%,33%) 100%);
}
.theme-body {
color: hsl(210,100%,85%);
-moz-box-sizing: border-box;
}
#main {

View File

@ -0,0 +1,107 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* 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/. */
/* According to:
* https://bugzilla.mozilla.org/show_bug.cgi?id=715472#c17
*/
.theme-body {
background: white;
color: black;
}
.theme-twisty {
cursor: pointer;
margin-right: 5px;
}
.theme-twisty:-moz-focusring {
outline-style: none;
}
.theme-twisty:not([open]) {
width: 0;
height: 0;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-left: 5px solid rgba(0,0,0,0.5);
margin-left: 5px;
}
.theme-twisty[open] {
width: 10px;
height: 10px;
background-image: linear-gradient(to bottom right, transparent 68%, rgba(0,0,0,0.5) 68%);
}
.theme-checkbox {
display: inline-block;
border: 1px solid rgba(160,160,160,0.4);
width: 6px;
height: 6px;
padding: 2px;
background-color: transparent;
background-repeat: no-repeat;
outline: none;
}
.theme-checkbox[checked] {
background-clip: content-box;
background-image: linear-gradient(to bottom right, transparent 48%, rgba(160,160,160,1) 48%, rgba(160,160,160,1) 52%, transparent 52%),
linear-gradient(to bottom left, transparent 48%, rgba(160,160,160,1) 48%, rgba(160,160,160,1) 52%, transparent 52%);
}
.theme-selected {
background-color: hsl(0,0%,90%);
}
.theme-bg-darker {
background: #F9F9F9;
}
.theme-link { /* blue */
color: hsl(208,56%,40%);
}
.theme-comment { /* grey */
color: hsl(90,2%,46%);
}
.theme-gutter {
background-color: hsl(0,0%,90%);
color: #667380;
border-color: hsl(0,0%,65%);
}
.theme-separator { /* grey */
border-color: #cddae5;
}
.theme-fg-color1 { /* green */
color: hsl(72,100%,27%);
}
.theme-fg-color2 { /* blue */
color: hsl(208,56%,40%);
}
.theme-fg-color3 { /* dark blue */
color: hsl(208,81%,21%)
}
.theme-fg-color4 { /* Orange */
color: hsl(24,85%,39%);
}
.theme-fg-color5 { /* Yellow */
color: #a18650;
}
.theme-fg-color6 { /* Orange */
color: hsl(24,85%,39%);
}
.theme-fg-color7 { /* Red */
color: #bf5656;
}

View File

@ -7,14 +7,6 @@
margin: 0;
}
body {
color: hsl(0,0%,50%);
}
.text {
color: black;
}
.newattr {
cursor: pointer;
}
@ -41,12 +33,6 @@ li.container {
.expander {
position: absolute;
-moz-appearance: treetwisty;
padding: 11px 0;
}
.expander[expanded] {
-moz-appearance: treetwistyopen;
}
.more-nodes {

View File

@ -0,0 +1,125 @@
/* 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/. */
.ruleview {
height: 100%;
}
.ruleview-rule-source {
-moz-padding-start: 5px;
cursor: pointer;
text-align: right;
float: right;
-moz-user-select: none;
}
.ruleview-rule-inheritance {
border-top-width: 1px;
border-bottom-width: 1px;
border-top-style: solid;
border-bottom-style: solid;
padding: 1px 4px;
margin-top: 4px;
-moz-user-select: none;
}
.ruleview-rule-source:hover {
text-decoration: underline;
}
.ruleview-rule {
padding: 2px 4px;
}
.ruleview-rule + .ruleview-rule {
border-top-width: 1px;
border-top-style: dotted;
}
.ruleview-warning {
background: url("chrome://browser/skin/devtools/alerticon-warning.png");
-moz-margin-start: 5px;
vertical-align: middle;
width: 13px;
height: 12px;
}
.ruleview-ruleopen {
-moz-padding-end: 5px;
}
.ruleview-ruleclose {
cursor: text;
padding-right: 20px;
}
.ruleview-propertylist {
list-style: none;
padding: 0;
margin: 0;
}
.ruleview-rule:not(:hover) .ruleview-enableproperty {
visibility: hidden;
}
.ruleview-expander {
display: inline-block;
}
.ruleview-newproperty {
/* (enable checkbox width: 12px) + (expander width: 15px) */
-moz-margin-start: 27px;
}
.ruleview-namecontainer,
.ruleview-propertycontainer,
.ruleview-propertyname,
.ruleview-propertyvalue {
text-decoration: inherit;
}
.ruleview-computedlist {
list-style: none;
padding: 0;
}
.ruleview-computed {
-moz-margin-start: 35px;
}
.ruleview-overridden {
text-decoration: line-through;
}
.styleinspector-propertyeditor {
border: 1px solid #CCC;
padding: 0;
}
.ruleview-property {
border-left: 2px solid transparent;
}
.ruleview-property > * {
vertical-align: middle;
}
.ruleview-property[dirty] {
border-left-color: #68E268;
}
.ruleview-namecontainer > .ruleview-propertyname,
.ruleview-propertycontainer > .ruleview-propertyvalue {
border-bottom: 1px dashed transparent;
}
.ruleview-namecontainer:hover > .ruleview-propertyname,
.ruleview-propertycontainer:hover > .ruleview-propertyvalue {
border-bottom-color: hsl(0,0%,50%);
}
.ruleview-selector-separator, .ruleview-selector-unmatched {
color: #888;
}

View File

@ -115,6 +115,8 @@ browser.jar:
skin/classic/browser/tabview/tabview.png (tabview/tabview.png)
skin/classic/browser/tabview/tabview.css (tabview/tabview.css)
* skin/classic/browser/devtools/common.css (devtools/common.css)
skin/classic/browser/devtools/dark-theme.css (devtools/dark-theme.css)
skin/classic/browser/devtools/light-theme.css (devtools/light-theme.css)
skin/classic/browser/devtools/arrows.png (devtools/arrows.png)
skin/classic/browser/devtools/widgets.css (devtools/widgets.css)
skin/classic/browser/devtools/commandline.png (devtools/commandline.png)
@ -124,7 +126,7 @@ browser.jar:
skin/classic/browser/devtools/command-tilt.png (devtools/command-tilt.png)
skin/classic/browser/devtools/alerticon-warning.png (devtools/alerticon-warning.png)
skin/classic/browser/devtools/goto-mdn.png (devtools/goto-mdn.png)
skin/classic/browser/devtools/csshtmltree.css (devtools/csshtmltree.css)
skin/classic/browser/devtools/ruleview.css (devtools/ruleview.css)
skin/classic/browser/devtools/webconsole.css (devtools/webconsole.css)
skin/classic/browser/devtools/webconsole_networkpanel.css (devtools/webconsole_networkpanel.css)
skin/classic/browser/devtools/webconsole.png (devtools/webconsole.png)
@ -187,6 +189,7 @@ browser.jar:
skin/classic/browser/devtools/dock-bottom.png (devtools/dock-bottom.png)
skin/classic/browser/devtools/dock-side.png (devtools/dock-side.png)
skin/classic/browser/devtools/floating-scrollbars.css (devtools/floating-scrollbars.css)
skin/classic/browser/devtools/floating-scrollbars-light.css (devtools/floating-scrollbars-light.css)
skin/classic/browser/devtools/inspector.css (devtools/inspector.css)
skin/classic/browser/devtools/toolbox.css (devtools/toolbox.css)
skin/classic/browser/devtools/tool-webconsole.png (devtools/tool-webconsole.png)
@ -197,6 +200,8 @@ browser.jar:
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)
skin/classic/browser/devtools/computedview.css (devtools/computedview.css)
skin/classic/browser/devtools/arrow-e.png (devtools/arrow-e.png)
#ifdef MOZ_SERVICES_SYNC
skin/classic/browser/sync-16-throbber.png
skin/classic/browser/sync-16.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

View File

@ -144,6 +144,7 @@
.devtools-searchinput {
-moz-appearance: none;
margin: 0 3px;
min-height: 22px;
background-color: transparent;
border: 1px solid hsla(210,8%,5%,.6);
border-radius: 20px;
@ -354,34 +355,4 @@
box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset, 0 -2px 0 hsla(206,37%,4%,.05) inset, 0 -1px 1px hsla(206,37%,4%,.1) inset;
}
/* Theme */
.devtools-theme-background {
background-color: white;
}
.devtools-theme-comment {
color: hsl(90,2%,46%); /* grey */
}
.devtools-theme-keyword {
color: hsl(276,44%,45%); /* purple */
}
.devtools-theme-string {
color: hsl(72,100%,27%); /* green */
}
.devtools-theme-tagname {
color: hsl(208,81%,21%); /* dark blue */
}
.devtools-theme-attrname {
color: hsl(208,56%,40%); /* blue */
}
.devtools-theme-attrvalue {
color: hsl(24,85%,39%); /* orange */
}
%include ../../shared/devtools/common.inc.css

View File

@ -0,0 +1,175 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* 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/. */
/* Take away these two :visited rules to get a core dumper */
/* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
.link,
.link:visited {
color: #0091ff;
}
.link,
.helplink,
.link:visited,
.helplink:visited {
text-decoration: none;
}
.link:hover {
text-decoration: underline;
}
/* From content */
* {
-moz-box-sizing: border-box;
}
:root {
height: 100%;
}
body {
margin: 0;
display : flex;
flex-direction: column;
height: 100%;
}
#propertyContainer {
-moz-user-select: text;
overflow: auto;
min-height: 0;
flex: 1;
}
.property-view-hidden,
.property-content-hidden {
display: none;
}
.property-view {
clear: both;
padding: 2px 0 2px 17px;
}
.property-view > * {
display: inline-block;
vertical-align: middle;
}
.property-name {
width: 50%;
overflow-x: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.property-value {
width: 50%;
max-width: 100%;
overflow-x: hidden;
text-overflow: ellipsis;
white-space: nowrap;
background-image: url(arrow-e.png);
background-repeat: no-repeat;
background-size: 5px 8px;
background-position: 2px center;
padding-left: 10px;
}
.other-property-value {
background-image: url(arrow-e.png);
background-repeat: no-repeat;
background-size: 5px 8px;
background-position: left center;
padding-left: 8px;
}
@media (min-width: 400px) {
.property-name {
width: 200px;
}
.property-value {
width: auto;
}
}
.property-content {
padding-left: 17px;
}
/* From skin */
.helplink {
/* FIXME: remove this image
background-image: url("chrome://browser/skin/devtools/goto-mdn.png");
*/
}
.expander {
visibility: hidden;
margin-left: -12px!important;
}
.expander[open] {
margin-left: -17px!important;
}
.expandable {
visibility: visible;
}
.match {
visibility: hidden;
}
.matchedselectors > p {
clear: both;
margin: 0 2px 0 0;
padding: 2px;
overflow-x: hidden;
border-style: dotted;
border-color: rgba(128,128,128,0.4);
border-width: 1px 1px 0 1px;
}
.matchedselectors > p:last-of-type {
border-bottom-width: 1px;
}
/* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
.rule-text {
direction: ltr;
}
.matched {
text-decoration: line-through;
}
.parentmatch {
opacity: 0.5;
}
#noResults {
font-size: 110%;
margin: 5px;
text-align: center;
}
.onlyuserstyles {
cursor: pointer;
}
.legendKey {
margin: 0 5px;
}
.devtools-toolbar {
width: 100%;
}
.link {
padding: 0 3px;
cursor: pointer;
float: right;
}

View File

@ -1,296 +0,0 @@
/* 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/. */
:root {
-moz-appearance: none;
background: -moz-Field;
color: -moz-FieldText;
font: message-box;
font-family: monospace;
}
/* Take away these two :visited rules to get a core dumper */
/* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
.link,
.link:visited {
color: #0091ff;
}
.link,
.helplink,
.link:visited,
.helplink:visited {
text-decoration: none;
}
.link:hover {
text-decoration: underline;
}
.helplink {
height: 14px;
width: 0;
overflow: hidden;
-moz-padding-start: 14px;
background-image: url("chrome://browser/skin/devtools/goto-mdn.png");
-moz-margin-end: 2px;
cursor: pointer;
}
.property-view:not(:hover) > .helplink-container {
visibility: hidden;
}
.rulelink {
color: -moz-dialogtext;
padding: 0;
}
.expander {
-moz-appearance: treetwisty;
width: 12px;
height: 12px;
padding-top: 12px;
-moz-margin-start: 5px;
vertical-align: middle;
}
.expander[open] {
-moz-appearance: treetwistyopen;
}
.match {
visibility: hidden;
}
.expandable {
cursor: pointer;
visibility: visible;
}
.expander-container {
vertical-align: text-top;
}
.property-name {
padding: 2px 0;
color: -moz-FieldText;
}
.property-value {
padding: 0;
-moz-padding-end: 6px;
color: grey;
width: 100%;
}
.rule-link {
text-align: end;
-moz-padding-start: 10px;
cursor: pointer;
}
/* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
.rule-text {
direction: ltr;
padding: 0;
-moz-padding-start: 20px;
vertical-align: text-bottom;
}
.bestmatch {
color: black;
}
.matched {
text-decoration: line-through;
}
.parentmatch {
color: #666;
}
#propertyContainer {
border-collapse: collapse;
}
.darkrow {
background-color: rgba(0,0,0,.022);
}
#noResults {
font-size: 18px;
margin-top: 5px;
text-align: center;
}
.headerControls {
color: -moz-dialogtext;
background-color: -moz-dialog;
}
.includebrowserstyles {
cursor: pointer;
font-size: 11px;
}
#footer {
border-top: 1px solid -moz-dialog;
}
.legendKey {
margin: 0 5px;
}
/**
* CSS Rule View
*/
.ruleview {
background-color: white;
}
.ruleview-rule-source {
color: hsl(90,2%,46%); /* grey */
-moz-padding-start: 5px;
cursor: pointer;
text-align: right;
float: right;
-moz-user-select: none;
}
.ruleview-rule-inheritance {
background-color: hsl(0,0%,90%);
color: hsl(0,0%,50%);
border-top: 1px solid hsl(0,0%,65%);
border-bottom: 1px solid hsl(0,0%,65%);
padding: 1px 4px;
margin-top: 4px;
-moz-user-select: none;
}
.ruleview-rule-source:hover {
text-decoration: underline;
}
.ruleview-rule {
padding: 2px 4px;
}
.ruleview-rule + .ruleview-rule {
border-top: 1px dotted #cddae5;
}
.ruleview-warning {
background: url("chrome://browser/skin/devtools/alerticon-warning.png");
-moz-margin-start: 5px;
vertical-align: middle;
width: 13px;
height: 12px;
}
.ruleview-ruleopen {
-moz-padding-end: 5px;
}
.ruleview-ruleclose {
cursor: text;
padding-right: 20px;
}
.ruleview-propertylist {
list-style: none;
padding: 0;
margin: 0;
}
.ruleview-enableproperty {
height: 10px;
width: 10px;
-moz-margin-start: 1px;
-moz-margin-end: 0;
transition: opacity 100ms;
transition-delay: 200ms;
}
.ruleview-property:not(:hover) > .ruleview-enableproperty[checked] {
opacity: 0;
transition: none;
}
.ruleview-expander {
width: 8px;
height: 8px;
background: url("chrome://browser/skin/devtools/arrows.png") 24px 0;
cursor: pointer;
-moz-margin-start: 2px;
-moz-margin-end: 5px;
}
.ruleview-expander.styleinspector-open {
background-position: 8px 0;
}
.ruleview-newproperty {
/* (enable checkbox width: 12px) + (expander width: 15px) */
-moz-margin-start: 27px;
}
.ruleview-propertyname {
padding: 1px 0;
color: hsl(276,44%,45%); /* purple */
}
.ruleview-propertyvalue {
padding: 1px 0;
}
.ruleview-namecontainer,
.ruleview-propertycontainer,
.ruleview-propertyname,
.ruleview-propertyvalue {
text-decoration: inherit;
}
.ruleview-computedlist {
list-style: none;
padding: 0;
}
.ruleview-computed {
-moz-margin-start: 4em;
}
.ruleview-overridden {
text-decoration: line-through;
}
.styleinspector-propertyeditor {
border: 1px solid #CCC;
padding: 0;
box-shadow: 2px 2px 2px #CCC;
}
.ruleview-property {
border-left: 2px solid transparent;
}
.ruleview-property > * {
vertical-align: middle;
}
.ruleview-property[dirty] {
border-left-color: #68E268;
}
.ruleview-namecontainer > .ruleview-propertyname,
.ruleview-propertycontainer > .ruleview-propertyvalue {
border-bottom: 1px dashed transparent;
}
.ruleview-namecontainer:hover > .ruleview-propertyname,
.ruleview-propertycontainer:hover > .ruleview-propertyvalue {
border-bottom-color: hsl(0,0%,50%);
}
.ruleview-selector-separator, .ruleview-selector-unmatched {
color: #888;
}

View File

@ -0,0 +1,107 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* 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/. */
/* According to:
* https://bugzilla.mozilla.org/show_bug.cgi?id=715472#c17
*/
.theme-body {
background: #131c26;
color: #8fa1b2
}
.theme-twisty {
cursor: pointer;
margin-right: 5px;
}
.theme-twisty:-moz-focusring {
outline-style: none;
}
.theme-twisty:not([open]) {
width: 0;
height: 0;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-left: 5px solid rgba(255,255,255,0.5);
margin-left: 5px;
}
.theme-twisty[open] {
width: 10px;
height: 10px;
background-image: linear-gradient(to bottom right, transparent 68%, rgba(255,255,255,0.5) 68%);
}
.theme-checkbox {
display: inline-block;
border: 1px solid rgba(160,160,160,0.4);
width: 6px;
height: 6px;
padding: 2px;
background-color: transparent;
background-repeat: no-repeat;
outline: none;
}
.theme-checkbox[checked] {
background-clip: content-box;
background-image: linear-gradient(to bottom right, transparent 48%, rgba(160,160,160,1) 48%, rgba(160,160,160,1) 52%, transparent 52%),
linear-gradient(to bottom left, transparent 48%, rgba(160,160,160,1) 48%, rgba(160,160,160,1) 52%, transparent 52%);
}
.theme-selected {
background: #26384E;
}
.theme-bg-darker {
background-color: rgba(0,0,0,0.1);
}
.theme-link { /* blue */
color: #3689b2;
}
.theme-comment { /* grey */
color: #5c6773;
}
.theme-gutter {
background-color: #0f171f;
color: #667380;
border-color: #303b47;
}
.theme-separator { /* grey */
border-color: #303b47;
}
.theme-fg-color1 { /* green */
color: #5c9966;
}
.theme-fg-color2 { /* blue */
color: #3689b2;
}
.theme-fg-color3 { /* pink/lavender */
color: #a673bf;
}
.theme-fg-color4 { /* purple/violet */
color: #6270b2;
}
.theme-fg-color5 { /* Yellow */
color: #a18650;
}
.theme-fg-color6 { /* Orange */
color: #b26b47;
}
.theme-fg-color7 { /* Red */
color: #bf5656;
}

View File

@ -0,0 +1,10 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* 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/. */
@import url("floating-scrollbars.css");
scrollbar thumb {
background-color: rgba(170,170,170,0.2) !important;
}

View File

@ -3,7 +3,6 @@
}
body {
background: #F9F9F9;
margin: 0;
padding-bottom: 20px;
}
@ -24,16 +23,23 @@ body {
}
.font {
border-bottom: 1px solid #DDD;
padding: 10px 5px;
font-size: 0;
}
.theme-dark .font {
border-bottom: 1px solid #444;
}
.theme-light .font {
border-bottom: 1px solid #DDD;
}
.font:last-of-type {
border-bottom: 0;
}
.font:nth-child(even) {
.theme-light .font:nth-child(even) {
background: #F4F4F4;
}
@ -57,23 +63,18 @@ body {
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 {
.theme-light .font-css-code,
.theme-light .font-url {
border: 1px solid #CCC;
color: #888;
background: white;
}
.font-url:focus {
color: black;
.theme-dark .font-css-code,
.theme-dark .font-url {
border: 1px solid #333;
background: black;
color: white;
}

View File

@ -2,14 +2,17 @@
* 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/. */
body {
background: url(layout-background-grid.png), -moz-radial-gradient(50% 70%, circle cover, hsl(210,53%,45%) 0%, hsl(210,54%,33%) 100%);
color: hsl(210,100%,85%);
-moz-box-sizing: border-box;
.theme-dark .theme-body {
background-image: url(layout-background-grid.png);
}
#element-size {
color: hsl(210,100%,95%);
.theme-light .theme-body {
background-image: url(layout-background-grid.png), -moz-radial-gradient(50% 70%, circle cover, hsl(210,53%,45%) 0%, hsl(210,54%,33%) 100%);
}
.theme-body {
color: hsl(210,100%,85%);
-moz-box-sizing: border-box;
}
#main {

View File

@ -0,0 +1,107 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* 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/. */
/* According to:
* https://bugzilla.mozilla.org/show_bug.cgi?id=715472#c17
*/
.theme-body {
background: white;
color: black;
}
.theme-twisty {
cursor: pointer;
margin-right: 5px;
}
.theme-twisty:-moz-focusring {
outline-style: none;
}
.theme-twisty:not([open]) {
width: 0;
height: 0;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-left: 5px solid rgba(0,0,0,0.5);
margin-left: 5px;
}
.theme-twisty[open] {
width: 10px;
height: 10px;
background-image: linear-gradient(to bottom right, transparent 68%, rgba(0,0,0,0.5) 68%);
}
.theme-checkbox {
display: inline-block;
border: 1px solid rgba(160,160,160,0.4);
width: 6px;
height: 6px;
padding: 2px;
background-color: transparent;
background-repeat: no-repeat;
outline: none;
}
.theme-checkbox[checked] {
background-clip: content-box;
background-image: linear-gradient(to bottom right, transparent 48%, rgba(160,160,160,1) 48%, rgba(160,160,160,1) 52%, transparent 52%),
linear-gradient(to bottom left, transparent 48%, rgba(160,160,160,1) 48%, rgba(160,160,160,1) 52%, transparent 52%);
}
.theme-selected {
background-color: hsl(0,0%,90%);
}
.theme-bg-darker {
background: #F9F9F9;
}
.theme-link { /* blue */
color: hsl(208,56%,40%);
}
.theme-comment { /* grey */
color: hsl(90,2%,46%);
}
.theme-gutter {
background-color: hsl(0,0%,90%);
color: #667380;
border-color: hsl(0,0%,65%);
}
.theme-separator { /* grey */
border-color: #cddae5;
}
.theme-fg-color1 { /* green */
color: hsl(72,100%,27%);
}
.theme-fg-color2 { /* blue */
color: hsl(208,56%,40%);
}
.theme-fg-color3 { /* dark blue */
color: hsl(208,81%,21%)
}
.theme-fg-color4 { /* Orange */
color: hsl(24,85%,39%);
}
.theme-fg-color5 { /* Yellow */
color: #a18650;
}
.theme-fg-color6 { /* Orange */
color: hsl(24,85%,39%);
}
.theme-fg-color7 { /* Red */
color: #bf5656;
}

View File

@ -7,14 +7,6 @@
margin: 0;
}
body {
color: hsl(0,0%,50%);
}
.text {
color: black;
}
.newattr {
cursor: pointer;
}
@ -41,15 +33,6 @@ li.container {
.expander {
position: absolute;
-moz-appearance: treetwisty;
top: 0;
left: 0;
width: 14px;
height: 14px;
}
.expander[expanded] {
-moz-appearance: treetwistyopen;
}
.more-nodes {

View File

@ -0,0 +1,126 @@
/* 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/. */
.ruleview {
height: 100%;
}
.ruleview-rule-source {
-moz-padding-start: 5px;
cursor: pointer;
text-align: right;
float: right;
-moz-user-select: none;
}
.ruleview-rule-inheritance {
border-top-width: 1px;
border-bottom-width: 1px;
border-top-style: solid;
border-bottom-style: solid;
padding: 1px 4px;
margin-top: 4px;
-moz-user-select: none;
}
.ruleview-rule-source:hover {
text-decoration: underline;
}
.ruleview-rule {
padding: 2px 4px;
}
.ruleview-rule + .ruleview-rule {
border-top-width: 1px;
border-top-style: dotted;
}
.ruleview-warning {
background: url("chrome://browser/skin/devtools/alerticon-warning.png");
-moz-margin-start: 5px;
vertical-align: middle;
width: 13px;
height: 12px;
}
.ruleview-ruleopen {
-moz-padding-end: 5px;
}
.ruleview-ruleclose {
cursor: text;
padding-right: 20px;
}
.ruleview-propertylist {
list-style: none;
padding: 0;
margin: 0;
}
.ruleview-rule:not(:hover) .ruleview-enableproperty {
visibility: hidden;
}
.ruleview-expander {
display: inline-block;
}
.ruleview-newproperty {
/* (enable checkbox width: 12px) + (expander width: 15px) */
-moz-margin-start: 27px;
}
.ruleview-namecontainer,
.ruleview-propertycontainer,
.ruleview-propertyname,
.ruleview-propertyvalue {
text-decoration: inherit;
}
.ruleview-computedlist {
list-style: none;
padding: 0;
}
.ruleview-computed {
-moz-margin-start: 35px;
}
.ruleview-overridden {
text-decoration: line-through;
}
.styleinspector-propertyeditor {
border: 1px solid #CCC;
padding: 0;
}
.ruleview-property {
border-left: 2px solid transparent;
}
.ruleview-property > * {
vertical-align: middle;
}
.ruleview-property[dirty] {
border-left-color: #68E268;
}
.ruleview-namecontainer > .ruleview-propertyname,
.ruleview-propertycontainer > .ruleview-propertyvalue {
border-bottom: 1px dashed transparent;
}
.ruleview-namecontainer:hover > .ruleview-propertyname,
.ruleview-propertycontainer:hover > .ruleview-propertyvalue {
border-bottom-color: hsl(0,0%,50%);
}
.ruleview-selector-separator, .ruleview-selector-unmatched {
color: #888;
}

View File

@ -199,6 +199,8 @@ browser.jar:
skin/classic/browser/tabview/tabview.png (tabview/tabview.png)
skin/classic/browser/tabview/tabview.css (tabview/tabview.css)
* skin/classic/browser/devtools/common.css (devtools/common.css)
skin/classic/browser/devtools/dark-theme.css (devtools/dark-theme.css)
skin/classic/browser/devtools/light-theme.css (devtools/light-theme.css)
skin/classic/browser/devtools/widgets.css (devtools/widgets.css)
skin/classic/browser/devtools/arrows.png (devtools/arrows.png)
skin/classic/browser/devtools/commandline.png (devtools/commandline.png)
@ -208,8 +210,8 @@ browser.jar:
skin/classic/browser/devtools/command-tilt.png (devtools/command-tilt.png)
skin/classic/browser/devtools/alerticon-warning.png (devtools/alerticon-warning.png)
skin/classic/browser/devtools/goto-mdn.png (devtools/goto-mdn.png)
skin/classic/browser/devtools/csshtmltree.css (devtools/csshtmltree.css)
skin/classic/browser/devtools/commandline.css (devtools/commandline.css)
skin/classic/browser/devtools/ruleview.css (devtools/ruleview.css)
skin/classic/browser/devtools/commandline.css (devtools/commandline.css)
skin/classic/browser/devtools/markup-view.css (devtools/markup-view.css)
skin/classic/browser/devtools/orion.css (devtools/orion.css)
skin/classic/browser/devtools/orion-container.css (devtools/orion-container.css)
@ -272,6 +274,7 @@ browser.jar:
skin/classic/browser/devtools/dock-bottom.png (devtools/dock-bottom.png)
skin/classic/browser/devtools/dock-side.png (devtools/dock-side.png)
skin/classic/browser/devtools/floating-scrollbars.css (devtools/floating-scrollbars.css)
skin/classic/browser/devtools/floating-scrollbars-light.css (devtools/floating-scrollbars-light.css)
* skin/classic/browser/devtools/inspector.css (devtools/inspector.css)
skin/classic/browser/devtools/toolbox.css (devtools/toolbox.css)
skin/classic/browser/devtools/tool-webconsole.png (devtools/tool-webconsole.png)
@ -282,6 +285,8 @@ browser.jar:
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)
skin/classic/browser/devtools/computedview.css (devtools/computedview.css)
skin/classic/browser/devtools/arrow-e.png (devtools/arrow-e.png)
#ifdef MOZ_SERVICES_SYNC
skin/classic/browser/sync-throbber.png
skin/classic/browser/sync-16.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

View File

@ -142,6 +142,7 @@
.devtools-searchinput {
-moz-appearance: none;
margin: 0 3px;
min-height: 22px;
border: 1px solid hsla(211,68%,6%,.6);
box-shadow: inset 0 1px 0 hsla(211,68%,6%,.05), 0 0 0 1px hsla(210,40%,83%,.1);
border-radius: 2px;
@ -363,34 +364,4 @@
box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset, 0 -2px 0 hsla(206,37%,4%,.05) inset, 0 -1px 1px hsla(206,37%,4%,.1) inset;
}
/* Theme */
.devtools-theme-background {
background-color: white;
}
.devtools-theme-comment {
color: hsl(90,2%,46%); /* grey */
}
.devtools-theme-keyword {
color: hsl(276,44%,45%); /* purple */
}
.devtools-theme-string {
color: hsl(72,100%,27%); /* green */
}
.devtools-theme-tagname {
color: hsl(208,81%,21%); /* dark blue */
}
.devtools-theme-attrname {
color: hsl(208,56%,40%); /* blue */
}
.devtools-theme-attrvalue {
color: hsl(24,85%,39%); /* orange */
}
%include ../../shared/devtools/common.inc.css

View File

@ -0,0 +1,175 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* 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/. */
/* Take away these two :visited rules to get a core dumper */
/* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
.link,
.link:visited {
color: #0091ff;
}
.link,
.helplink,
.link:visited,
.helplink:visited {
text-decoration: none;
}
.link:hover {
text-decoration: underline;
}
/* From content */
* {
-moz-box-sizing: border-box;
}
:root {
height: 100%;
}
body {
margin: 0;
display : flex;
flex-direction: column;
height: 100%;
}
#propertyContainer {
-moz-user-select: text;
overflow: auto;
min-height: 0;
flex: 1;
}
.property-view-hidden,
.property-content-hidden {
display: none;
}
.property-view {
clear: both;
padding: 2px 0 2px 17px;
}
.property-view > * {
display: inline-block;
vertical-align: middle;
}
.property-name {
width: 50%;
overflow-x: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.property-value {
width: 50%;
max-width: 100%;
overflow-x: hidden;
text-overflow: ellipsis;
white-space: nowrap;
background-image: url(arrow-e.png);
background-repeat: no-repeat;
background-size: 5px 8px;
background-position: 2px center;
padding-left: 10px;
}
.other-property-value {
background-image: url(arrow-e.png);
background-repeat: no-repeat;
background-size: 5px 8px;
background-position: left center;
padding-left: 8px;
}
@media (min-width: 400px) {
.property-name {
width: 200px;
}
.property-value {
width: auto;
}
}
.property-content {
padding-left: 17px;
}
/* From skin */
.helplink {
/* FIXME: remove this image
background-image: url("chrome://browser/skin/devtools/goto-mdn.png");
*/
}
.expander {
visibility: hidden;
margin-left: -12px!important;
}
.expander[open] {
margin-left: -17px!important;
}
.expandable {
visibility: visible;
}
.match {
visibility: hidden;
}
.matchedselectors > p {
clear: both;
margin: 0 2px 0 0;
padding: 2px;
overflow-x: hidden;
border-style: dotted;
border-color: rgba(128,128,128,0.4);
border-width: 1px 1px 0 1px;
}
.matchedselectors > p:last-of-type {
border-bottom-width: 1px;
}
/* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
.rule-text {
direction: ltr;
}
.matched {
text-decoration: line-through;
}
.parentmatch {
opacity: 0.5;
}
#noResults {
font-size: 110%;
margin: 5px;
text-align: center;
}
.onlyuserstyles {
cursor: pointer;
}
.legendKey {
margin: 0 5px;
}
.devtools-toolbar {
width: 100%;
}
.link {
padding: 0 3px;
cursor: pointer;
float: right;
}

View File

@ -1,295 +0,0 @@
/* 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/. */
:root {
-moz-appearance: none;
background: -moz-Field;
color: -moz-FieldText;
font: message-box;
font-family: monospace;
}
/* Take away these two :visited rules to get a core dumper */
/* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
.link,
.link:visited {
color: #0091ff;
}
.link,
.helplink,
.link:visited,
.helplink:visited {
text-decoration: none;
}
.link:hover {
text-decoration: underline;
}
.helplink {
height: 14px;
width: 0;
overflow: hidden;
-moz-padding-start: 14px;
background-image: url("chrome://browser/skin/devtools/goto-mdn.png");
-moz-margin-end: 2px;
cursor: pointer;
}
.property-view:not(:hover) > .helplink-container {
visibility: hidden;
}
.rulelink {
color: -moz-dialogtext;
padding: 0;
}
.expander {
width: 9px;
height: 9px;
-moz-margin-start: 5px;
-moz-margin-end: 5px;
background: url("chrome://global/skin/tree/twisty-clsd.png") center center no-repeat;
vertical-align: middle;
}
.expander[open] {
background-image: url("chrome://global/skin/tree/twisty-open.png");
}
.match {
visibility: hidden;
}
.expandable {
cursor: pointer;
visibility: visible;
}
.expander-container {
vertical-align: text-top;
}
.property-name {
padding: 2px 0;
color: -moz-FieldText;
}
.property-value {
padding: 0;
-moz-padding-end: 6px;
color: grey;
width: 100%;
}
.rule-link {
text-align: end;
-moz-padding-start: 10px;
cursor: pointer;
}
/* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
.rule-text {
direction: ltr;
padding: 0;
-moz-padding-start: 20px;
vertical-align: text-bottom;
}
.bestmatch {
color: black;
}
.matched {
text-decoration: line-through;
}
.parentmatch {
color: #666;
}
#propertyContainer {
border-collapse: collapse;
}
.darkrow {
background-color: rgba(0,0,0,.022);
}
#noResults {
font-size: 18px;
margin-top: 5px;
text-align: center;
}
.headerControls {
color: -moz-dialogtext;
background-color: -moz-dialog;
}
.includebrowserstyles {
cursor: pointer;
font-size: 11px;
}
#footer {
border-top: 1px solid -moz-dialog;
}
.legendKey {
margin: 0 5px;
}
/**
* CSS Rule View
*/
.ruleview {
background-color: white;
}
.ruleview-rule-source {
color: hsl(90,2%,46%); /* grey */
-moz-padding-start: 5px;
cursor: pointer;
text-align: right;
float: right;
-moz-user-select: none;
}
.ruleview-rule-inheritance {
background-color: hsl(0,0%,90%);
color: hsl(0,0%,50%);
border-top: 1px solid hsl(0,0%,65%);
border-bottom: 1px solid hsl(0,0%,65%);
padding: 1px 4px;
margin-top: 4px;
-moz-user-select: none;
}
.ruleview-rule-source:hover {
text-decoration: underline;
}
.ruleview-rule {
padding: 2px 4px;
}
.ruleview-rule + .ruleview-rule {
border-top: 1px dotted #cddae5;
}
.ruleview-warning {
background: url("chrome://browser/skin/devtools/alerticon-warning.png");
-moz-margin-start: 5px;
vertical-align: middle;
width: 13px;
height: 12px;
}
.ruleview-ruleopen {
-moz-padding-end: 5px;
}
.ruleview-ruleclose {
cursor: text;
padding-right: 20px;
}
.ruleview-propertylist {
list-style: none;
padding: 0;
margin: 0;
}
.ruleview-enableproperty {
height: 10px;
width: 10px;
-moz-margin-start: 1px;
-moz-margin-end: 0;
transition: opacity 100ms;
transition-delay: 200ms;
}
.ruleview-property:not(:hover) > .ruleview-enableproperty[checked] {
opacity: 0;
transition: none;
}
.ruleview-expander {
width: 8px;
height: 8px;
background: url("chrome://browser/skin/devtools/arrows.png") 24px 0;
cursor: pointer;
-moz-margin-start: 2px;
-moz-margin-end: 5px;
}
.ruleview-expander.styleinspector-open {
background-position: 8px 0;
}
.ruleview-newproperty {
/* (enable checkbox width: 12px) + (expander width: 15px) */
-moz-margin-start: 27px;
}
.ruleview-propertyname {
padding: 1px 0;
color: hsl(276,44%,45%); /* purple */
}
.ruleview-propertyvalue {
padding: 1px 0;
}
.ruleview-namecontainer,
.ruleview-propertycontainer,
.ruleview-propertyname,
.ruleview-propertyvalue {
text-decoration: inherit;
}
.ruleview-computedlist {
list-style: none;
padding: 0;
}
.ruleview-computed {
-moz-margin-start: 4em;
}
.ruleview-overridden {
text-decoration: line-through;
}
.styleinspector-propertyeditor {
border: 1px solid #CCC;
padding: 0;
box-shadow: 2px 2px 2px #CCC;
}
.ruleview-property {
border-left: 2px solid transparent;
}
.ruleview-property > * {
vertical-align: middle;
}
.ruleview-property[dirty] {
border-left-color: #68E268;
}
.ruleview-namecontainer > .ruleview-propertyname,
.ruleview-propertycontainer > .ruleview-propertyvalue {
border-bottom: 1px dashed transparent;
}
.ruleview-namecontainer:hover > .ruleview-propertyname,
.ruleview-propertycontainer:hover > .ruleview-propertyvalue {
border-bottom-color: hsl(0,0%,50%);
}
.ruleview-selector-separator, .ruleview-selector-unmatched {
color: #888;
}

View File

@ -0,0 +1,107 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* 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/. */
/* According to:
* https://bugzilla.mozilla.org/show_bug.cgi?id=715472#c17
*/
.theme-body {
background: #131c26;
color: #8fa1b2
}
.theme-twisty {
cursor: pointer;
margin-right: 5px;
}
.theme-twisty:-moz-focusring {
outline-style: none;
}
.theme-twisty:not([open]) {
width: 0;
height: 0;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-left: 5px solid rgba(255,255,255,0.5);
margin-left: 5px;
}
.theme-twisty[open] {
width: 10px;
height: 10px;
background-image: linear-gradient(to bottom right, transparent 68%, rgba(255,255,255,0.5) 68%);
}
.theme-checkbox {
display: inline-block;
border: 1px solid rgba(160,160,160,0.4);
width: 6px;
height: 6px;
padding: 2px;
background-color: transparent;
background-repeat: no-repeat;
outline: none;
}
.theme-checkbox[checked] {
background-clip: content-box;
background-image: linear-gradient(to bottom right, transparent 48%, rgba(160,160,160,1) 48%, rgba(160,160,160,1) 52%, transparent 52%),
linear-gradient(to bottom left, transparent 48%, rgba(160,160,160,1) 48%, rgba(160,160,160,1) 52%, transparent 52%);
}
.theme-selected {
background: #26384E;
}
.theme-bg-darker {
background-color: rgba(0,0,0,0.1);
}
.theme-link { /* blue */
color: #3689b2;
}
.theme-comment { /* grey */
color: #5c6773;
}
.theme-gutter {
background-color: #0f171f;
color: #667380;
border-color: #303b47;
}
.theme-separator { /* grey */
border-color: #303b47;
}
.theme-fg-color1 { /* green */
color: #5c9966;
}
.theme-fg-color2 { /* blue */
color: #3689b2;
}
.theme-fg-color3 { /* pink/lavender */
color: #a673bf;
}
.theme-fg-color4 { /* purple/violet */
color: #6270b2;
}
.theme-fg-color5 { /* Yellow */
color: #a18650;
}
.theme-fg-color6 { /* Orange */
color: #b26b47;
}
.theme-fg-color7 { /* Red */
color: #bf5656;
}

View File

@ -0,0 +1,10 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* 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/. */
@import url("floating-scrollbars.css");
scrollbar thumb {
background-color: rgba(170,170,170,0.2) !important;
}

View File

@ -10,21 +10,21 @@ scrollbar {
}
scrollbar[orient="vertical"] {
-moz-margin-start: -8px;
min-width: 8px;
max-width: 8px;
-moz-margin-start: -10px;
min-width: 10px;
max-width: 10px;
}
scrollbar[orient="horizontal"] {
margin-top: -8px;
min-height: 8px;
max-height: 8px;
margin-top: -10px;
min-height: 10px;
max-height: 10px;
}
scrollbar thumb {
-moz-appearance: none !important;
border-width: 0px !important;
background-color: rgba(0,0,0,0.2) !important;
background-color: rgba(170,170,170,0.2) !important;
border-radius: 3px !important;
}

View File

@ -3,7 +3,6 @@
}
body {
background: #F9F9F9;
margin: 0;
padding-bottom: 20px;
}
@ -24,16 +23,23 @@ body {
}
.font {
border-bottom: 1px solid #DDD;
padding: 10px 5px;
font-size: 0;
}
.theme-dark .font {
border-bottom: 1px solid #444;
}
.theme-light .font {
border-bottom: 1px solid #DDD;
}
.font:last-of-type {
border-bottom: 0;
}
.font:nth-child(even) {
.theme-light .font:nth-child(even) {
background: #F4F4F4;
}
@ -57,23 +63,18 @@ body {
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 {
.theme-light .font-css-code,
.theme-light .font-url {
border: 1px solid #CCC;
color: #888;
background: white;
}
.font-url:focus {
color: black;
.theme-dark .font-css-code,
.theme-dark .font-url {
border: 1px solid #333;
background: black;
color: white;
}

View File

@ -2,14 +2,17 @@
* 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/. */
body {
background: url(layout-background-grid.png), -moz-radial-gradient(50% 70%, circle cover, hsl(210,53%,45%) 0%, hsl(210,54%,33%) 100%);
color: hsl(210,100%,85%);
-moz-box-sizing: border-box;
.theme-dark .theme-body {
background-image: url(layout-background-grid.png);
}
#element-size {
color: hsl(210,100%,95%);
.theme-light .theme-body {
background-image: url(layout-background-grid.png), -moz-radial-gradient(50% 70%, circle cover, hsl(210,53%,45%) 0%, hsl(210,54%,33%) 100%);
}
.theme-body {
color: hsl(210,100%,85%);
-moz-box-sizing: border-box;
}
#main {

View File

@ -0,0 +1,107 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* 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/. */
/* According to:
* https://bugzilla.mozilla.org/show_bug.cgi?id=715472#c17
*/
.theme-body {
background: white;
color: black;
}
.theme-twisty {
cursor: pointer;
margin-right: 5px;
}
.theme-twisty:-moz-focusring {
outline-style: none;
}
.theme-twisty:not([open]) {
width: 0;
height: 0;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-left: 5px solid rgba(0,0,0,0.5);
margin-left: 5px;
}
.theme-twisty[open] {
width: 10px;
height: 10px;
background-image: linear-gradient(to bottom right, transparent 68%, rgba(0,0,0,0.5) 68%);
}
.theme-checkbox {
display: inline-block;
border: 1px solid rgba(160,160,160,0.4);
width: 6px;
height: 6px;
padding: 2px;
background-color: transparent;
background-repeat: no-repeat;
outline: none;
}
.theme-checkbox[checked] {
background-clip: content-box;
background-image: linear-gradient(to bottom right, transparent 48%, rgba(160,160,160,1) 48%, rgba(160,160,160,1) 52%, transparent 52%),
linear-gradient(to bottom left, transparent 48%, rgba(160,160,160,1) 48%, rgba(160,160,160,1) 52%, transparent 52%);
}
.theme-selected {
background-color: hsl(0,0%,90%);
}
.theme-bg-darker {
background: #F9F9F9;
}
.theme-link { /* blue */
color: hsl(208,56%,40%);
}
.theme-comment { /* grey */
color: hsl(90,2%,46%);
}
.theme-gutter {
background-color: hsl(0,0%,90%);
color: #667380;
border-color: hsl(0,0%,65%);
}
.theme-separator { /* grey */
border-color: #cddae5;
}
.theme-fg-color1 { /* green */
color: hsl(72,100%,27%);
}
.theme-fg-color2 { /* blue */
color: hsl(208,56%,40%);
}
.theme-fg-color3 { /* dark blue */
color: hsl(208,81%,21%)
}
.theme-fg-color4 { /* Orange */
color: hsl(24,85%,39%);
}
.theme-fg-color5 { /* Yellow */
color: #a18650;
}
.theme-fg-color6 { /* Orange */
color: hsl(24,85%,39%);
}
.theme-fg-color7 { /* Red */
color: #bf5656;
}

View File

@ -7,14 +7,6 @@
margin: 0;
}
body {
color: hsl(0,0%,50%);
}
.text {
color: black;
}
.newattr {
cursor: pointer;
}
@ -41,17 +33,6 @@ li.container {
.expander {
position: absolute;
top: 5px;
left: 0;
width: 14px;
height: 14px;
background-repeat: no-repeat;
background-position: center;
background-image: url("chrome://global/skin/tree/twisty-clsd.png");
}
.expander[expanded] {
background-image: url("chrome://global/skin/tree/twisty-open.png");
}
.more-nodes {

View File

@ -0,0 +1,125 @@
/* 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/. */
.ruleview {
height: 100%;
}
.ruleview-rule-source {
-moz-padding-start: 5px;
cursor: pointer;
text-align: right;
float: right;
-moz-user-select: none;
}
.ruleview-rule-inheritance {
border-top-width: 1px;
border-bottom-width: 1px;
border-top-style: solid;
border-bottom-style: solid;
padding: 1px 4px;
margin-top: 4px;
-moz-user-select: none;
}
.ruleview-rule-source:hover {
text-decoration: underline;
}
.ruleview-rule {
padding: 2px 4px;
}
.ruleview-rule + .ruleview-rule {
border-top-width: 1px;
border-top-style: dotted;
}
.ruleview-warning {
background: url("chrome://browser/skin/devtools/alerticon-warning.png");
-moz-margin-start: 5px;
vertical-align: middle;
width: 13px;
height: 12px;
}
.ruleview-ruleopen {
-moz-padding-end: 5px;
}
.ruleview-ruleclose {
cursor: text;
padding-right: 20px;
}
.ruleview-propertylist {
list-style: none;
padding: 0;
margin: 0;
}
.ruleview-rule:not(:hover) .ruleview-enableproperty {
visibility: hidden;
}
.ruleview-expander {
display: inline-block;
}
.ruleview-newproperty {
/* (enable checkbox width: 12px) + (expander width: 15px) */
-moz-margin-start: 27px;
}
.ruleview-namecontainer,
.ruleview-propertycontainer,
.ruleview-propertyname,
.ruleview-propertyvalue {
text-decoration: inherit;
}
.ruleview-computedlist {
list-style: none;
padding: 0;
}
.ruleview-computed {
-moz-margin-start: 35px;
}
.ruleview-overridden {
text-decoration: line-through;
}
.styleinspector-propertyeditor {
border: 1px solid #CCC;
padding: 0;
}
.ruleview-property {
border-left: 2px solid transparent;
}
.ruleview-property > * {
vertical-align: middle;
}
.ruleview-property[dirty] {
border-left-color: #68E268;
}
.ruleview-namecontainer > .ruleview-propertyname,
.ruleview-propertycontainer > .ruleview-propertyvalue {
border-bottom: 1px dashed transparent;
}
.ruleview-namecontainer:hover > .ruleview-propertyname,
.ruleview-propertycontainer:hover > .ruleview-propertyvalue {
border-bottom-color: hsl(0,0%,50%);
}
.ruleview-selector-separator, .ruleview-selector-unmatched {
color: #888;
}

View File

@ -141,12 +141,14 @@ browser.jar:
skin/classic/browser/tabview/tabview-inverted.png (tabview/tabview-inverted.png)
skin/classic/browser/tabview/tabview.css (tabview/tabview.css)
* skin/classic/browser/devtools/common.css (devtools/common.css)
skin/classic/browser/devtools/dark-theme.css (devtools/dark-theme.css)
skin/classic/browser/devtools/light-theme.css (devtools/light-theme.css)
skin/classic/browser/devtools/widgets.css (devtools/widgets.css)
skin/classic/browser/devtools/arrows.png (devtools/arrows.png)
skin/classic/browser/devtools/commandline.png (devtools/commandline.png)
skin/classic/browser/devtools/alerticon-warning.png (devtools/alerticon-warning.png)
skin/classic/browser/devtools/goto-mdn.png (devtools/goto-mdn.png)
skin/classic/browser/devtools/csshtmltree.css (devtools/csshtmltree.css)
skin/classic/browser/devtools/ruleview.css (devtools/ruleview.css)
skin/classic/browser/devtools/commandline.css (devtools/commandline.css)
skin/classic/browser/devtools/command-paintflashing.png (devtools/command-paintflashing.png)
skin/classic/browser/devtools/command-responsivemode.png (devtools/command-responsivemode.png)
@ -214,6 +216,7 @@ browser.jar:
skin/classic/browser/devtools/dock-bottom.png (devtools/dock-bottom.png)
skin/classic/browser/devtools/dock-side.png (devtools/dock-side.png)
skin/classic/browser/devtools/floating-scrollbars.css (devtools/floating-scrollbars.css)
skin/classic/browser/devtools/floating-scrollbars-light.css (devtools/floating-scrollbars-light.css)
skin/classic/browser/devtools/inspector.css (devtools/inspector.css)
skin/classic/browser/devtools/toolbox.css (devtools/toolbox.css)
skin/classic/browser/devtools/tool-webconsole.png (devtools/tool-webconsole.png)
@ -224,6 +227,8 @@ browser.jar:
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)
skin/classic/browser/devtools/computedview.css (devtools/computedview.css)
skin/classic/browser/devtools/arrow-e.png (devtools/arrow-e.png)
#ifdef MOZ_SERVICES_SYNC
skin/classic/browser/sync-throbber.png
skin/classic/browser/sync-16.png
@ -376,6 +381,8 @@ browser.jar:
skin/classic/aero/browser/tabview/tabview-inverted.png (tabview/tabview-inverted.png)
skin/classic/aero/browser/tabview/tabview.css (tabview/tabview.css)
* skin/classic/aero/browser/devtools/common.css (devtools/common.css)
skin/classic/aero/browser/devtools/dark-theme.css (devtools/dark-theme.css)
skin/classic/aero/browser/devtools/light-theme.css (devtools/light-theme.css)
skin/classic/aero/browser/devtools/widgets.css (devtools/widgets.css)
skin/classic/aero/browser/devtools/arrows.png (devtools/arrows.png)
skin/classic/aero/browser/devtools/commandline.png (devtools/commandline.png)
@ -385,7 +392,7 @@ browser.jar:
skin/classic/aero/browser/devtools/command-tilt.png (devtools/command-tilt.png)
skin/classic/aero/browser/devtools/alerticon-warning.png (devtools/alerticon-warning.png)
skin/classic/aero/browser/devtools/goto-mdn.png (devtools/goto-mdn.png)
skin/classic/aero/browser/devtools/csshtmltree.css (devtools/csshtmltree.css)
skin/classic/aero/browser/devtools/ruleview.css (devtools/ruleview.css)
skin/classic/aero/browser/devtools/commandline.css (devtools/commandline.css)
skin/classic/aero/browser/devtools/markup-view.css (devtools/markup-view.css)
skin/classic/aero/browser/devtools/orion.css (devtools/orion.css)
@ -449,6 +456,7 @@ browser.jar:
skin/classic/aero/browser/devtools/dock-bottom.png (devtools/dock-bottom.png)
skin/classic/aero/browser/devtools/dock-side.png (devtools/dock-side.png)
skin/classic/aero/browser/devtools/floating-scrollbars.css (devtools/floating-scrollbars.css)
skin/classic/aero/browser/devtools/floating-scrollbars-light.css (devtools/floating-scrollbars-light.css)
skin/classic/aero/browser/devtools/inspector.css (devtools/inspector.css)
skin/classic/aero/browser/devtools/toolbox.css (devtools/toolbox.css)
skin/classic/aero/browser/devtools/tool-webconsole.png (devtools/tool-webconsole.png)
@ -459,6 +467,8 @@ browser.jar:
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)
skin/classic/aero/browser/devtools/computedview.css (devtools/computedview.css)
skin/classic/aero/browser/devtools/arrow-e.png (devtools/arrow-e.png)
#ifdef MOZ_SERVICES_SYNC
skin/classic/aero/browser/sync-throbber.png
skin/classic/aero/browser/sync-16.png

View File

@ -7811,20 +7811,22 @@ dnl =========================================================
dnl = Chrome format
dnl =========================================================
MOZ_ARG_ENABLE_STRING([chrome-format],
[ --enable-chrome-format=jar|flat|both|symlink|omni
Select FORMAT of chrome files (default=jar)],
[ --enable-chrome-format=jar|flat|omni
Select FORMAT of chrome files during packaging],
MOZ_CHROME_FILE_FORMAT=`echo $enableval | tr A-Z a-z`)
if test -z "$MOZ_CHROME_FILE_FORMAT"; then
MOZ_CHROME_FILE_FORMAT=jar
fi
if test "$MOZ_CHROME_FILE_FORMAT" = "symlink"; then
AC_MSG_ERROR([--enable-chrome-format=symlink has been deprecated. It is now used by default in $DIST/bin on platforms that support it])
fi
if test "$MOZ_CHROME_FILE_FORMAT" != "jar" &&
test "$MOZ_CHROME_FILE_FORMAT" != "flat" &&
test "$MOZ_CHROME_FILE_FORMAT" != "symlink" &&
test "$MOZ_CHROME_FILE_FORMAT" != "both" &&
test "$MOZ_CHROME_FILE_FORMAT" != "omni"; then
AC_MSG_ERROR([--enable-chrome-format must be set to either jar, flat, both, symlink, or omni])
AC_MSG_ERROR([--enable-chrome-format must be set to either jar, flat, or omni])
fi
dnl =========================================================

View File

@ -27,7 +27,10 @@ const THUMBNAIL_DIRECTORY = "thumbnails";
*/
const THUMBNAIL_BG_COLOR = "#fff";
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
Cu.import("resource://gre/modules/osfile/_PromiseWorker.jsm", this);
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", this);
Cu.import("resource://gre/modules/osfile.jsm", this);
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
@ -55,6 +58,70 @@ XPCOMUtils.defineLazyGetter(this, "gUnicodeConverter", function () {
return converter;
});
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
/**
* Utilities for dealing with promises and Task.jsm
*/
const TaskUtils = {
/**
* Add logging to a promise.
*
* @param {Promise} promise
* @return {Promise} A promise behaving as |promise|, but with additional
* logging in case of uncaught error.
*/
captureErrors: function captureErrors(promise) {
return promise.then(
null,
function onError(reason) {
Cu.reportError("Uncaught asynchronous error: " + reason + " at\n"
+ reason.stack + "\n");
throw reason;
}
);
},
/**
* Spawn a new Task from a generator.
*
* This function behaves as |Task.spawn|, with the exception that it
* adds logging in case of uncaught error. For more information, see
* the documentation of |Task.jsm|.
*
* @param {generator} gen Some generator.
* @return {Promise} A promise built from |gen|, with the same semantics
* as |Task.spawn(gen)|.
*/
spawn: function spawn(gen) {
return this.captureErrors(Task.spawn(gen));
},
/**
* Read the bytes from a blob, asynchronously.
*
* @return {Promise}
* @resolve {ArrayBuffer} In case of success, the bytes contained in the blob.
* @reject {DOMError} In case of error, the underlying DOMError.
*/
readBlob: function readBlob(blob) {
let deferred = Promise.defer();
let reader = Cc["@mozilla.org/files/filereader;1"].createInstance(Ci.nsIDOMFileReader);
reader.onloadend = function onloadend() {
if (reader.readyState != Ci.nsIDOMFileReader.DONE) {
deferred.reject(reader.error);
} else {
deferred.resolve(reader.result);
}
};
reader.readAsArrayBuffer(blob);
return deferred.promise;
}
};
/**
* Singleton providing functionality for capturing web page thumbnails and for
* accessing them if already cached.
@ -134,6 +201,33 @@ this.PageThumbs = {
}.bind(this), Ci.nsIThread.DISPATCH_NORMAL);
},
/**
* Captures a thumbnail for the given window.
*
* @param aWindow The DOM window to capture a thumbnail from.
* @return {Promise}
* @resolve {Blob} The thumbnail, as a Blob.
*/
captureToBlob: function PageThumbs_captureToBlob(aWindow) {
if (!this._prefEnabled()) {
return null;
}
let canvas = this._createCanvas();
this.captureToCanvas(aWindow, canvas);
let deferred = Promise.defer();
let type = this.contentType;
// Fetch the canvas data on the next event loop tick so that we allow
// some event processing in between drawing to the canvas and encoding
// its data. We want to block the UI as short as possible. See bug 744100.
canvas.toBlob(function asBlob(blob) {
deferred.resolve(blob, type);
});
return deferred.promise;
},
/**
* Captures a thumbnail from a given window and draws it to the given canvas.
* @param aWindow The DOM window to capture a thumbnail from.
@ -177,35 +271,39 @@ this.PageThumbs = {
let channel = aBrowser.docShell.currentDocumentChannel;
let originalURL = channel.originalURI.spec;
this.capture(aBrowser.contentWindow, function (aInputStream) {
let telemetryStoreTime = new Date();
TaskUtils.spawn((function task() {
let isSuccess = true;
try {
let blob = yield this.captureToBlob(aBrowser.contentWindow);
let buffer = yield TaskUtils.readBlob(blob);
function finish(aSuccessful) {
if (aSuccessful) {
Services.telemetry.getHistogramById("FX_THUMBNAILS_STORE_TIME_MS")
.add(new Date() - telemetryStoreTime);
let telemetryStoreTime = new Date();
yield PageThumbsStorage.writeData(url, new Uint8Array(buffer));
// We've been redirected. Create a copy of the current thumbnail for
// the redirect source. We need to do this because:
//
// 1) Users can drag any kind of links onto the newtab page. If those
// links redirect to a different URL then we want to be able to
// provide thumbnails for both of them.
//
// 2) The newtab page should actually display redirect targets, only.
// Because of bug 559175 this information can get lost when using
// Sync and therefore also redirect sources appear on the newtab
// page. We also want thumbnails for those.
if (url != originalURL)
PageThumbsStorage.copy(url, originalURL);
Services.telemetry.getHistogramById("FX_THUMBNAILS_STORE_TIME_MS")
.add(new Date() - telemetryStoreTime);
// We've been redirected. Create a copy of the current thumbnail for
// the redirect source. We need to do this because:
//
// 1) Users can drag any kind of links onto the newtab page. If those
// links redirect to a different URL then we want to be able to
// provide thumbnails for both of them.
//
// 2) The newtab page should actually display redirect targets, only.
// Because of bug 559175 this information can get lost when using
// Sync and therefore also redirect sources appear on the newtab
// page. We also want thumbnails for those.
if (url != originalURL) {
yield PageThumbsStorage.copy(url, originalURL);
}
if (aCallback)
aCallback(aSuccessful);
} catch (_) {
isSuccess = false;
}
PageThumbsStorage.write(url, aInputStream, finish);
});
if (aCallback) {
aCallback(isSuccess);
}
}).bind(this));
},
/**
@ -314,55 +412,99 @@ this.PageThumbs = {
};
this.PageThumbsStorage = {
getDirectory: function Storage_getDirectory(aCreate = true) {
return FileUtils.getDir("ProfLD", [THUMBNAIL_DIRECTORY], aCreate);
// The path for the storage
_path: null,
get path() {
if (!this._path) {
this._path = OS.Path.join(OS.Constants.Path.localProfileDir, THUMBNAIL_DIRECTORY);
}
return this._path;
},
ensurePath: function Storage_ensurePath() {
// Create the directory (ignore any error if the directory
// already exists). As all writes are done from the PageThumbsWorker
// thread, which serializes its operations, this ensures that
// future operations can proceed without having to check whether
// the directory exists.
return PageThumbsWorker.post("makeDir",
[this.path, {ignoreExisting: true}]).then(
null,
function onError(aReason) {
Components.utils.reportError("Could not create thumbnails directory" + aReason);
});
},
getLeafNameForURL: function Storage_getLeafNameForURL(aURL) {
if (typeof aURL != "string") {
throw new TypeError("Expecting a string");
}
let hash = this._calculateMD5Hash(aURL);
return hash + ".png";
},
getFileForURL: function Storage_getFileForURL(aURL) {
let file = this.getDirectory();
file.append(this.getLeafNameForURL(aURL));
return file;
getFilePathForURL: function Storage_getFilePathForURL(aURL) {
return OS.Path.join(this.path, this.getLeafNameForURL(aURL));
},
write: function Storage_write(aURL, aDataStream, aCallback) {
let file = this.getFileForURL(aURL);
let fos = FileUtils.openSafeFileOutputStream(file);
NetUtil.asyncCopy(aDataStream, fos, function (aResult) {
FileUtils.closeSafeFileOutputStream(fos);
aCallback(Components.isSuccessCode(aResult));
});
/**
* Write the contents of a thumbnail, off the main thread.
*
* @param {string} aURL The url for which to store a thumbnail.
* @param {string} aData The data to store in the thumbnail, as
* an ArrayBuffer. This array buffer is neutered and cannot be
* reused after the copy.
*
* @return {Promise}
*/
writeData: function Storage_write(aURL, aData) {
let path = this.getFilePathForURL(aURL);
this.ensurePath();
let msg = [
path,
aData,
{
tmpPath: path + ".tmp",
bytes: aData.byteLength,
flush: false /*thumbnails do not require the level of guarantee provided by flush*/
}];
return PageThumbsWorker.post("writeAtomic", msg,
msg /*we don't want that message garbage-collected,
as OS.Shared.Type.void_t.in_ptr.toMsg uses C-level
memory tricks to enforce zero-copy*/);
},
/**
* Copy a thumbnail, off the main thread.
*
* @param {string} aSourceURL The url of the thumbnail to copy.
* @param {string} aTargetURL The url of the target thumbnail.
*
* @return {Promise}
*/
copy: function Storage_copy(aSourceURL, aTargetURL) {
let sourceFile = this.getFileForURL(aSourceURL);
let targetFile = this.getFileForURL(aTargetURL);
try {
sourceFile.copyTo(targetFile.parent, targetFile.leafName);
} catch (e) {
/* We might not be permitted to write to the file. */
}
this.ensurePath();
let sourceFile = this.getFilePathForURL(aSourceURL);
let targetFile = this.getFilePathForURL(aTargetURL);
return PageThumbsWorker.post("copy", [sourceFile, targetFile]);
},
/**
* Remove a single thumbnail, off the main thread.
*
* @return {Promise}
*/
remove: function Storage_remove(aURL) {
let file = this.getFileForURL(aURL);
PageThumbsWorker.postMessage({type: "removeFile", path: file.path});
return PageThumbsWorker.post("remove", [this.getFilePathForURL(aURL)]);
},
/**
* Remove all thumbnails, off the main thread.
*
* @return {Promise}
*/
wipe: function Storage_wipe() {
let dir = this.getDirectory(false);
dir.followLinks = false;
try {
dir.remove(true);
} catch (e) {
/* The directory might not exist or we're not permitted to remove it. */
}
return PageThumbsWorker.post("wipe", [this.path]);
},
_calculateMD5Hash: function Storage_calculateMD5Hash(aValue) {
@ -423,18 +565,20 @@ let PageThumbsStorageMigrator = {
* try to move the old thumbnails to their new location. If that's not
* possible (because ProfD might be on a different file system than
* ProfLD) we'll just discard them.
*
* @param {string*} local The path to the local profile directory.
* Used for testing. Default argument is good for all non-testing uses.
* @param {string*} roaming The path to the roaming profile directory.
* Used for testing. Default argument is good for all non-testing uses.
*/
migrateToVersion3: function Migrator_migrateToVersion3() {
let local = FileUtils.getDir("ProfLD", [THUMBNAIL_DIRECTORY], true);
let roaming = FileUtils.getDir("ProfD", [THUMBNAIL_DIRECTORY]);
if (!roaming.equals(local)) {
PageThumbsWorker.postMessage({
type: "moveOrDeleteAllThumbnails",
from: roaming.path,
to: local.path
});
}
migrateToVersion3: function Migrator_migrateToVersion3(
local = OS.Constants.Path.localProfileDir,
roaming = OS.Constants.Path.profileDir) {
PageThumbsWorker.post(
"moveOrDeleteAllThumbnails",
[OS.Path.join(roaming, THUMBNAIL_DIRECTORY),
OS.Path.join(local, THUMBNAIL_DIRECTORY)]
);
}
};
@ -484,60 +628,46 @@ let PageThumbsExpiration = {
}
},
expireThumbnails: function Expiration_expireThumbnails(aURLsToKeep, aCallback) {
PageThumbsWorker.postMessage({
type: "expireFilesInDirectory",
minChunkSize: EXPIRATION_MIN_CHUNK_SIZE,
path: PageThumbsStorage.getDirectory().path,
filesToKeep: [PageThumbsStorage.getLeafNameForURL(url) for (url of aURLsToKeep)]
}, aCallback);
expireThumbnails: function Expiration_expireThumbnails(aURLsToKeep) {
let path = this.path;
let keep = [PageThumbsStorage.getLeafNameForURL(url) for (url of aURLsToKeep)];
let msg = [
PageThumbsStorage.path,
keep,
EXPIRATION_MIN_CHUNK_SIZE
];
return PageThumbsWorker.post(
"expireFilesInDirectory",
msg
);
}
};
/**
* Interface to a dedicated thread handling I/O
*/
let PageThumbsWorker = {
/**
* A (fifo) queue of callbacks registered for execution
* upon completion of calls to the worker.
*/
_callbacks: [],
/**
* Get the worker, spawning it if necessary.
* Code of the worker is in companion file PageThumbsWorker.js
*/
get _worker() {
delete this._worker;
this._worker = new ChromeWorker("resource://gre/modules/PageThumbsWorker.js");
this._worker.addEventListener("message", this);
return this._worker;
},
/**
* Post a message to the dedicated thread, registering a callback
* to be executed once the reply has been received.
*
* See PageThumbsWorker.js for the format of messages and replies.
*
* @param {*} message A JSON message.
* @param {Function=} callback An optional callback.
*/
postMessage: function Worker_postMessage(message, callback) {
this._callbacks.push(callback);
this._worker.postMessage(message);
},
/**
* Handle a message from the dedicated thread.
*/
handleEvent: function Worker_handleEvent(aEvent) {
let callback = this._callbacks.shift();
if (callback)
callback(aEvent.data);
}
};
let PageThumbsWorker = (function() {
let worker = new PromiseWorker("resource://gre/modules/PageThumbsWorker.js",
OS.Shared.LOG.bind("PageThumbs"));
return {
post: function post(...args) {
let promise = worker.post.apply(worker, args);
return promise.then(
null,
function onError(error) {
// Decode any serialized error
if (error instanceof PromiseWorker.WorkerError) {
throw OS.File.Error.fromMsg(error.data);
} else {
throw error;
}
}
);
}
};
})();
let PageThumbsHistoryObserver = {
onDeleteURI: function Thumbnails_onDeleteURI(aURI, aGUID) {

View File

@ -27,6 +27,8 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
"resource://gre/modules/FileUtils.jsm");
/**
* Implements the thumbnail protocol handler responsible for moz-page-thumb: URIs.
@ -73,8 +75,8 @@ Protocol.prototype = {
*/
newChannel: function Proto_newChannel(aURI) {
let {url} = parseURI(aURI);
let file = PageThumbsStorage.getFileForURL(url);
let fileuri = Services.io.newFileURI(file);
let file = PageThumbsStorage.getFilePathForURL(url);
let fileuri = Services.io.newFileURI(new FileUtils.File(file));
return Services.io.newChannelFromURI(fileuri);
},

View File

@ -13,45 +13,62 @@
importScripts("resource://gre/modules/osfile.jsm");
let PageThumbsWorker = {
handleMessage: function Worker_handleMessage(aEvent) {
let msg = aEvent.data;
let data = {result: null, data: null};
let File = OS.File;
let Type = OS.Shared.Type;
switch (msg.type) {
case "removeFile":
data.result = this.removeFile(msg);
break;
case "expireFilesInDirectory":
data.result = this.expireFilesInDirectory(msg);
break;
case "moveOrDeleteAllThumbnails":
data.result = this.moveOrDeleteAllThumbnails(msg);
break;
default:
data.result = false;
data.detail = "message not understood";
break;
}
/**
* Communications with the controller.
*
* Accepts messages:
* {fun:function_name, args:array_of_arguments_or_null}
*
* Sends messages:
* {ok: result} / {fail: serialized_form_of_OS.File.Error}
*/
self.onmessage = function onmessage(msg) {
let data = msg.data;
let id = data.id;
let result;
if (!(data.fun in Agent)) {
throw new Error("Cannot find method " + data.fun);
}
try {
result = Agent[data.fun].apply(Agent, data.args);
} catch (ex if ex instanceof StopIteration) {
// StopIteration cannot be serialized automatically
self.postMessage({StopIteration: true, id: id});
return;
} catch (ex if ex instanceof OS.File.Error) {
// Instances of OS.File.Error know how to serialize themselves
// (deserialization ensures that we end up with OS-specific
// instances of |OS.File.Error|)
self.postMessage({fail: OS.File.Error.toMsg(ex), id:id});
return;
}
// Other exceptions do not, and should be propagated through DOM's
// built-in mechanism for uncaught errors, although this mechanism
// may lose interesting information.
self.postMessage({ok: result, id:id});
};
self.postMessage(data);
},
removeFile: function Worker_removeFile(msg) {
let Agent = {
remove: function Agent_removeFile(path) {
try {
OS.File.remove(msg.path);
OS.File.remove(path);
return true;
} catch (e) {
return false;
}
},
expireFilesInDirectory: function Worker_expireFilesInDirectory(msg) {
let entries = this.getFileEntriesInDirectory(msg.path, msg.filesToKeep);
let limit = Math.max(msg.minChunkSize, Math.round(entries.length / 2));
expireFilesInDirectory:
function Agent_expireFilesInDirectory(path, filesToKeep, minChunkSize) {
let entries = this.getFileEntriesInDirectory(path, filesToKeep);
let limit = Math.max(minChunkSize, Math.round(entries.length / 2));
for (let entry of entries) {
this.removeFile(entry);
this.remove(entry.path);
// Check if we reached the limit of files to remove.
if (--limit <= 0) {
@ -63,9 +80,13 @@ let PageThumbsWorker = {
},
getFileEntriesInDirectory:
function Worker_getFileEntriesInDirectory(aPath, aSkipFiles) {
let skip = new Set(aSkipFiles);
let iter = new OS.File.DirectoryIterator(aPath);
function Agent_getFileEntriesInDirectory(path, skipFiles) {
let iter = new OS.File.DirectoryIterator(path);
if (!iter.exists()) {
return [];
}
let skip = new Set(skipFiles);
return [entry
for (entry in iter)
@ -73,36 +94,74 @@ let PageThumbsWorker = {
},
moveOrDeleteAllThumbnails:
function Worker_moveOrDeleteAllThumbnails(msg) {
if (!OS.File.exists(msg.from))
function Agent_moveOrDeleteAllThumbnails(pathFrom, pathTo) {
OS.File.makeDir(pathTo, {ignoreExisting: true});
if (pathFrom == pathTo) {
return true;
}
let iter = new OS.File.DirectoryIterator(pathFrom);
if (iter.exists()) {
for (let entry in iter) {
if (entry.isDir || entry.isSymLink) {
continue;
}
let iter = new OS.File.DirectoryIterator(msg.from);
for (let entry in iter) {
if (entry.isDir || entry.isSymLink) {
continue;
}
let from = OS.Path.join(msg.from, entry.name);
let to = OS.Path.join(msg.to, entry.name);
let from = OS.Path.join(pathFrom, entry.name);
let to = OS.Path.join(pathTo, entry.name);
try {
OS.File.move(from, to, {noOverwrite: true, noCopy: true});
} catch (e) {
OS.File.remove(from);
try {
OS.File.move(from, to, {noOverwrite: true, noCopy: true});
} catch (e) {
OS.File.remove(from);
}
}
}
iter.close();
try {
OS.File.removeEmptyDir(msg.from);
OS.File.removeEmptyDir(pathFrom);
} catch (e) {
// This could fail if there's something in
// the folder we're not permitted to remove.
}
return true;
}
},
writeAtomic: function Agent_writeAtomic(path, buffer, options) {
return File.writeAtomic(path,
buffer,
options);
},
makeDir: function Agent_makeDir(path, options) {
return File.makeDir(path, options);
},
copy: function Agent_copy(source, dest) {
return File.copy(source, dest);
},
wipe: function Agent_wipe(path) {
let iterator = new File.DirectoryIterator(path);
try {
for (let entry in iterator) {
try {
File.remove(entry.path);
} catch (ex) {
// If a file cannot be removed, we should still continue.
// This can happen at least for any of the following reasons:
// - access denied;
// - file has been removed recently during a previous wipe
// and the file system has not flushed that yet (yes, this
// can happen under Windows);
// - file has been removed by the user or another process.
}
}
} finally {
iterator.close();
}
}
};
self.onmessage = PageThumbsWorker.handleMessage.bind(PageThumbsWorker);

View File

@ -6,9 +6,6 @@ const URL1 = URL + "#1";
const URL2 = URL + "#2";
const URL3 = URL + "#3";
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
"resource://gre/modules/FileUtils.jsm");
let tmp = {};
Cc["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Ci.mozIJSSubScriptLoader)
@ -18,13 +15,13 @@ const {EXPIRATION_MIN_CHUNK_SIZE, PageThumbsExpiration} = tmp;
function runTests() {
// Create three thumbnails.
createDummyThumbnail(URL1);
yield createDummyThumbnail(URL1);
ok(thumbnailExists(URL1), "first thumbnail created");
createDummyThumbnail(URL2);
yield createDummyThumbnail(URL2);
ok(thumbnailExists(URL2), "second thumbnail created");
createDummyThumbnail(URL3);
yield createDummyThumbnail(URL3);
ok(thumbnailExists(URL3), "third thumbnail created");
// Remove the third thumbnail.
@ -45,10 +42,11 @@ function runTests() {
// Create some more files than the min chunk size.
let urls = [];
for (let i = 0; i < EXPIRATION_MIN_CHUNK_SIZE + 10; i++) {
urls.push(URL + "#dummy" + i);
let url = URL + "#dummy" + i;
urls.push(url);
yield createDummyThumbnail(url);
}
urls.forEach(createDummyThumbnail);
ok(urls.every(thumbnailExists), "all dummy thumbnails created");
// Make sure our dummy thumbnails aren't expired too early.
@ -71,16 +69,30 @@ function runTests() {
}
function createDummyThumbnail(aURL) {
let file = PageThumbsStorage.getFileForURL(aURL);
let fos = FileUtils.openSafeFileOutputStream(file);
let data = "dummy";
fos.write(data, data.length);
FileUtils.closeSafeFileOutputStream(fos);
info("Creating dummy thumbnail for " + aURL);
let dummy = new Uint8Array(10);
for (let i = 0; i < 10; ++i) {
dummy[i] = i;
}
PageThumbsStorage.writeData(aURL, dummy).then(
function onSuccess() {
info("createDummyThumbnail succeeded");
executeSoon(next);
},
function onFailure(error) {
ok(false, "createDummyThumbnail failed " + error);
}
);
}
function expireThumbnails(aKeep) {
PageThumbsExpiration.expireThumbnails(aKeep, function () {
executeSoon(next);
});
PageThumbsExpiration.expireThumbnails(aKeep).then(
function onSuccess() {
info("expireThumbnails succeeded");
executeSoon(next);
},
function onFailure(error) {
ok(false, "expireThumbnails failed " + error);
}
);
}

View File

@ -22,16 +22,16 @@ function runTests() {
yield createThumbnail();
// Make sure Storage.copy() updates an existing file.
PageThumbsStorage.copy(URL, URL_COPY);
let copy = PageThumbsStorage.getFileForURL(URL_COPY);
yield PageThumbsStorage.copy(URL, URL_COPY);
let copy = new FileUtils.File(PageThumbsStorage.getFilePathForURL(URL_COPY));
let mtime = copy.lastModifiedTime -= 60;
PageThumbsStorage.copy(URL, URL_COPY);
isnot(PageThumbsStorage.getFileForURL(URL_COPY).lastModifiedTime, mtime,
yield PageThumbsStorage.copy(URL, URL_COPY);
isnot(new FileUtils.File(PageThumbsStorage.getFilePathForURL(URL_COPY)).lastModifiedTime, mtime,
"thumbnail file was updated");
let file = PageThumbsStorage.getFileForURL(URL);
let fileCopy = PageThumbsStorage.getFileForURL(URL_COPY);
let file = new FileUtils.File(PageThumbsStorage.getFilePathForURL(URL));
let fileCopy = new FileUtils.File(PageThumbsStorage.getFilePathForURL(URL_COPY));
// Clear the browser history. Retry until the files are gone because Windows
// locks them sometimes.

View File

@ -13,9 +13,6 @@ Cc["@mozilla.org/moz/jssubscript-loader;1"]
.loadSubScript("resource://gre/modules/PageThumbs.jsm", tmp);
let {PageThumbsStorageMigrator} = tmp;
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
"resource://gre/modules/FileUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "gDirSvc",
"@mozilla.org/file/directory_service;1", "nsIProperties");
@ -55,7 +52,7 @@ function runTests() {
writeDummyFile(file, "no-overwrite-plz");
// Kick off thumbnail storage migration.
PageThumbsStorageMigrator.migrateToVersion3();
PageThumbsStorageMigrator.migrateToVersion3(localProfile.path);
ok(true, "migration finished");
// Wait until the first thumbnail was moved to its new location.

View File

@ -4,7 +4,9 @@
let tmp = {};
Cu.import("resource://gre/modules/PageThumbs.jsm", tmp);
Cu.import("resource:///modules/sessionstore/SessionStore.jsm", tmp);
let {PageThumbs, PageThumbsStorage, SessionStore} = tmp;
Cu.import("resource://gre/modules/FileUtils.jsm", tmp);
Cu.import("resource://gre/modules/osfile.jsm", tmp);
let {PageThumbs, PageThumbsStorage, SessionStore, FileUtils, OS} = tmp;
Cu.import("resource://gre/modules/PlacesUtils.jsm");
@ -45,7 +47,9 @@ let TestRunner = {
*/
next: function () {
try {
TestRunner._iter.next();
let value = TestRunner._iter.next();
if (value && typeof value.then == "function")
value.then(next);
} catch (e if e instanceof StopIteration) {
finish();
}
@ -85,10 +89,10 @@ function navigateTo(aURI) {
* @param aElement The DOM element to listen on.
* @param aCallback The function to call when the load event was dispatched.
*/
function whenLoaded(aElement, aCallback) {
function whenLoaded(aElement, aCallback = next) {
aElement.addEventListener("load", function onLoad() {
aElement.removeEventListener("load", onLoad, true);
executeSoon(aCallback || next);
executeSoon(aCallback);
}, true);
}
@ -143,7 +147,7 @@ function retrieveImageDataForURL(aURL, aCallback) {
* @param aURL The url associated to the thumbnail.
*/
function thumbnailExists(aURL) {
let file = PageThumbsStorage.getFileForURL(aURL);
let file = new FileUtils.File(PageThumbsStorage.getFilePathForURL(aURL));
return file.exists() && file.fileSize;
}
@ -211,13 +215,13 @@ function addVisits(aPlaceInfo, aCallback) {
* @param [optional] aCallback
* Function to be invoked on completion.
*/
function whenFileExists(aURL, aCallback) {
function whenFileExists(aURL, aCallback = next) {
let callback = aCallback;
if (!thumbnailExists(aURL)) {
callback = function () whenFileExists(aURL, aCallback);
}
executeSoon(callback || next);
executeSoon(callback);
}
/**

View File

@ -271,7 +271,7 @@ def main():
optimize=args.optimizejars,
non_resources=args.non_resource)
else:
errors.fatal('Unknown format: %s', format)
errors.fatal('Unknown format: %s' % args.format)
# Adjust defines according to the requested format.
if isinstance(formatter, OmniJarFormatter):