author | Ryan VanderMeulen <ryanvm@gmail.com> |
Wed, 27 Mar 2013 22:22:20 -0400 | |
changeset 126478 | 962f5293f87f652fe3e891a971c4ae0e4177a717 |
parent 126467 | 123017ccf036c2d0bc6f459481420640e8456718 (current diff) |
parent 126477 | 36332ce24dd1fc30911232d52b569e11e38d3117 (diff) |
child 126511 | da133fd0dbb72e9c57cd3e04a6f09761808e8283 |
child 126773 | d68b52ce9322e8d38f8127f3ed209c416d3c8ccd |
child 127453 | 1aaed48de5e5a970b2ee9efc89391b270df4aa09 |
push id | 24484 |
push user | ryanvm@gmail.com |
push date | Thu, 28 Mar 2013 02:22:09 +0000 |
treeherder | mozilla-central@962f5293f87f [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
milestone | 22.0a1 |
first release with | nightly linux32
962f5293f87f
/
22.0a1
/
20130328031013
/
files
nightly linux64
962f5293f87f
/
22.0a1
/
20130328031013
/
files
nightly mac
962f5293f87f
/
22.0a1
/
20130328031013
/
files
nightly win32
962f5293f87f
/
22.0a1
/
20130328031013
/
files
nightly win64
962f5293f87f
/
22.0a1
/
20130328031013
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
22.0a1
/
20130328031013
/
pushlog to previous
nightly linux64
22.0a1
/
20130328031013
/
pushlog to previous
nightly mac
22.0a1
/
20130328031013
/
pushlog to previous
nightly win32
22.0a1
/
20130328031013
/
pushlog to previous
nightly win64
22.0a1
/
20130328031013
/
pushlog to previous
|
browser/app/profile/firefox.js | file | annotate | diff | comparison | revisions | |
browser/devtools/styleinspector/csshtmltree.xul | file | annotate | diff | comparison | revisions | |
browser/devtools/styleinspector/cssruleview.xul | file | annotate | diff | comparison | revisions | |
browser/devtools/styleinspector/styleinspector.css | file | annotate | diff | comparison | revisions | |
browser/devtools/styleinspector/test/browser_computedview_bug_703643_context_menu_copy.js | file | annotate | diff | comparison | revisions | |
browser/devtools/styleinspector/test/browser_ruleview_bug_703643_context_menu_copy.js | file | annotate | diff | comparison | revisions | |
browser/themes/linux/devtools/csshtmltree.css | file | annotate | diff | comparison | revisions | |
browser/themes/osx/devtools/csshtmltree.css | file | annotate | diff | comparison | revisions | |
browser/themes/windows/devtools/csshtmltree.css | file | annotate | diff | comparison | revisions | |
configure.in | file | annotate | diff | comparison | revisions |
--- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1051,16 +1051,18 @@ pref("devtools.layoutview.enabled", true pref("devtools.layoutview.open", false); // Enable the Responsive UI tool 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); pref("devtools.debugger.remote-timeout", 20000); // The default Debugger UI settings pref("devtools.debugger.ui.win-x", 0); pref("devtools.debugger.ui.win-y", 0); @@ -1092,16 +1094,19 @@ pref("devtools.scratchpad.recentFilesMax // Enable the Style Editor. pref("devtools.styleeditor.enabled", true); 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); // How eager are we to show help: never=1, sometimes=2, always=3 pref("devtools.gcli.eagerHelper", 2); // Do we allow the 'pref set' command pref("devtools.gcli.allowSet", false);
--- a/browser/devtools/debugger/DebuggerUI.jsm +++ b/browser/devtools/debugger/DebuggerUI.jsm @@ -6,17 +6,17 @@ "use strict"; const Cc = Components.classes; const Ci = Components.interfaces; 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"); XPCOMUtils.defineLazyModuleGetter(this, "DebuggerServer", "resource://gre/modules/devtools/dbg-server.jsm"); XPCOMUtils.defineLazyModuleGetter(this, @@ -470,17 +470,17 @@ ChromeDebuggerProcess.prototype = { /** * Initializes the debugger server. */ _initServer: function RDP__initServer() { if (!DebuggerServer.initialized) { DebuggerServer.init(); DebuggerServer.addBrowserActors(); } - DebuggerServer.openListener(Prefs.remotePort); + DebuggerServer.openListener(Prefs.chromeDebuggingPort); }, /** * Initializes a profile for the remote debugger process. */ _initProfile: function RDP__initProfile() { let profileService = Cc["@mozilla.org/toolkit/profile-service;1"] .createInstance(Ci.nsIToolkitProfileService); @@ -592,40 +592,26 @@ XPCOMUtils.defineLazyGetter(L10N, "strin }); /** * Shortcuts for accessing various debugger preferences. */ 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"); }); /** * Helper method for debugging. * @param string */ function dumpn(str) { - if (Prefs.wantLogging) { + if (wantLogging) { dump("DBG-FRONTEND: " + str + "\n"); } } + +let wantLogging = Services.prefs.getBoolPref("devtools.debugger.log");
--- a/browser/devtools/debugger/debugger-controller.js +++ b/browser/devtools/debugger/debugger-controller.js @@ -180,17 +180,18 @@ let DebuggerController = { this._startChromeDebugging(client, dbg, callback); } else { this._startDebuggingTab(client, this._target.form, callback); } return; } // 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); client.addListener("tabDetached", this._onTabDetached); client.connect(function(aType, aTraits) { client.listTabs(function(aResponse) { this._startChromeDebugging(client, aResponse.chromeDebugger, callback); @@ -1726,16 +1727,18 @@ let Prefs = { map: function P_map(aType, aPropertyName, aPrefName) { Object.defineProperty(this, aPropertyName, { get: function() this._get(aType, aPrefName), set: function(aValue) this._set(aType, aPrefName, aValue) }); } }; +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"); Prefs.map("Int", "windowHeight", "devtools.debugger.ui.win-height"); Prefs.map("Int", "sourcesWidth", "devtools.debugger.ui.panes-sources-width"); Prefs.map("Int", "instrumentsWidth", "devtools.debugger.ui.panes-instruments-width"); Prefs.map("Bool", "pauseOnExceptions", "devtools.debugger.ui.pause-on-exceptions"); Prefs.map("Bool", "panesVisibleOnStartup", "devtools.debugger.ui.panes-visible-on-startup");
--- a/browser/devtools/debugger/debugger-panes.js +++ b/browser/devtools/debugger/debugger-panes.js @@ -972,35 +972,28 @@ let SourceUtils = { this._groupsCache = new Map(); }, /** * Gets a unique, simplified label from a source url. * * @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; }, /** * Gets as much information as possible about the hostname and directory paths * of an url to create a short url group identifier. * * @param string aUrl
--- a/browser/devtools/debugger/debugger-toolbar.js +++ b/browser/devtools/debugger/debugger-toolbar.js @@ -427,20 +427,21 @@ create({ constructor: StackFramesView, p * The line number to be displayed in the list. * @param number aDepth * The frame depth specified by the debugger. * @return nsIDOMNode * The stack frame view. */ _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"; frameTitleNode.setAttribute("value", aFrameTitle); let frameDetailsNode = document.createElement("label"); frameDetailsNode.className = "plain dbg-stackframe-details breadcrumbs-widget-item-id"; frameDetailsNode.setAttribute("value", frameDetails); @@ -466,20 +467,21 @@ create({ constructor: StackFramesView, p * The line number to be displayed in the list. * @param number aDepth * The frame depth specified by the debugger. * @return object * An object containing the stack frame command and menu item. */ _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"; let menuitemId = prefix + aDepth + "-" + "-menuitem"; let command = document.createElement("command"); command.id = commandId; command.addEventListener("command", this._selectFrame.bind(this, aDepth), false);
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-01.js +++ b/browser/devtools/debugger/test/browser_dbg_propertyview-01.js @@ -76,17 +76,17 @@ function testlabelshortening() { { href: "resource://random/", leaf: "script_t3_3.js&a=1&b=2#id" }, { href: nanana, leaf: "Batman!" + "{trim me, now and forevermore}" } ]; 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 }); }); }); executeSoon(function() { info("Script labels:"); info(vs.labels.toSource()); info("Script locations:");
--- a/browser/devtools/fontinspector/font-inspector.js +++ b/browser/devtools/fontinspector/font-inspector.js @@ -177,27 +177,30 @@ FontInspector.prototype = { * </head> * <style> * p {font-family: {name};} * * {font-size: 40px;line-height:60px;padding:0 10px;margin:0}; * </style> * <p contenteditable>Abc</p> */ let extraCSS = "* {padding:0;margin:0}"; + extraCSS += ".theme-dark {color: white}"; extraCSS += "p {font-family: '" + name + "';}"; extraCSS += "p {font-size: 40px;line-height:60px;padding:0 10px;margin:0;}"; cssCode += extraCSS; let src = "data:text/html;charset=utf-8,<!DOCTYPE HTML><head><base></base></head><style></style><p contenteditable>Abc</p>"; iframe.addEventListener("load", function onload() { iframe.removeEventListener("load", onload, true); let doc = iframe.contentWindow.document; // We could have done that earlier, but we want to avoid any URL-encoding // nightmare. doc.querySelector("base").href = base; doc.querySelector("style").textContent = cssCode; + // Forward theme + doc.documentElement.className = document.documentElement.className; }, true); iframe.src = src; }, /** * Select the <body> to show all the fonts included in the document. */ showAll: function FI_showAll() {
--- a/browser/devtools/fontinspector/font-inspector.xhtml +++ b/browser/devtools/fontinspector/font-inspector.xhtml @@ -9,18 +9,19 @@ <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>&title;</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <link rel="stylesheet" href="font-inspector.css" type="text/css"/> <link rel="stylesheet" href="chrome://browser/skin/devtools/common.css" type="text/css"/> <link rel="stylesheet" href="chrome://browser/skin/devtools/font-inspector.css" type="text/css"/> + <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> <button id="showall" onclick="fontInspector.showAll()">&showAllFonts;</button> </div> <div id="template" style="display:none"> <section class="font"> <iframe sandbox="allow-same-origin" class="font-preview"></iframe>
--- a/browser/devtools/framework/Toolbox.jsm +++ b/browser/devtools/framework/Toolbox.jsm @@ -709,26 +709,34 @@ Toolbox.prototype = { gDevTools.off("tool-unregistered", this._toolUnregistered); let outstanding = []; for (let [id, panel] of this._toolPanels) { 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 // remote protocol connections can be gracefully terminated. if (this._target) { this._target.off("close", this.destroy); outstanding.push(this._target.destroy()); } this._target = null; Promise.all(outstanding).then(function() { this.emit("destroyed"); + // 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)); return this._destroyer; } };
--- a/browser/devtools/framework/gDevTools.jsm +++ b/browser/devtools/framework/gDevTools.jsm @@ -602,17 +602,17 @@ let gDevToolsBrowser = { * @param {XULWindow} win * The window containing the menu entry */ forgetBrowserWindow: function DT_forgetBrowserWindow(win) { gDevToolsBrowser._trackedBrowserWindows.delete(win); // 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(); } } let tabContainer = win.document.getElementById("tabbrowser-tabs") tabContainer.removeEventListener("TabSelect", gDevToolsBrowser._updateMenuCheckbox, false); },
--- a/browser/devtools/inspector/InspectorPanel.jsm +++ b/browser/devtools/inspector/InspectorPanel.jsm @@ -216,21 +216,21 @@ InspectorPanel.prototype = { this._setDefaultSidebar = function(event, toolId) { Services.prefs.setCharPref("devtools.inspector.activeSidebar", toolId); }.bind(this); this.sidebar.on("select", this._setDefaultSidebar); 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")) { this.sidebar.addTab("fontinspector", "chrome://browser/content/devtools/fontinspector/font-inspector.xhtml", "fontinspector" == defaultTab); }
--- a/browser/devtools/inspector/inspector.xul +++ b/browser/devtools/inspector/inspector.xul @@ -82,14 +82,14 @@ timeout="50" class="devtools-searchinput" placeholder="&inspectorSearchHTML.label;"/> </toolbar> <vbox flex="1" id="markup-box"> </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> </hbox> </window>
--- a/browser/devtools/jar.mn +++ b/browser/devtools/jar.mn @@ -7,21 +7,22 @@ browser.jar: content/browser/devtools/markup-view.xhtml (markupview/markup-view.xhtml) content/browser/devtools/markup-view.css (markupview/markup-view.css) content/browser/NetworkPanel.xhtml (webconsole/NetworkPanel.xhtml) content/browser/devtools/webconsole.js (webconsole/webconsole.js) content/browser/devtools/webconsole.xul (webconsole/webconsole.xul) * 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) content/browser/devtools/fontinspector/font-inspector.js (fontinspector/font-inspector.js) content/browser/devtools/fontinspector/font-inspector.xhtml (fontinspector/font-inspector.xhtml) content/browser/devtools/fontinspector/font-inspector.css (fontinspector/font-inspector.css) content/browser/orion.js (sourceeditor/orion/orion.js) * content/browser/source-editor-overlay.xul (sourceeditor/source-editor-overlay.xul)
--- a/browser/devtools/layoutview/view.css +++ b/browser/devtools/layoutview/view.css @@ -42,16 +42,26 @@ body { margin: 0 10px 10px 10px; -moz-box-sizing: border-box; width: calc(100% - 2 * 10px); position: absolute; border-width: 1px; font: 10px/12px monospace; } +@media (min-width: 320px) { + body { + position: absolute; + width: 320px; + left: -160px; + margin-left: 50%; + } +} + + #margins { padding: 28px; } #content { height: 20px; border-width: 1px; }
--- a/browser/devtools/layoutview/view.xhtml +++ b/browser/devtools/layoutview/view.xhtml @@ -7,16 +7,18 @@ %layoutviewDTD; ]> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <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[ let elts; let tooltip; const Ci = Components.interfaces; const Cc = Components.classes; @@ -62,17 +64,17 @@ } ]]> </script> <link rel="stylesheet" href="chrome://browser/skin/devtools/layoutview.css" type="text/css"/> <link rel="stylesheet" href="view.css" type="text/css"/> </head> - <body> + <body class="theme-body"> <p id="header"> <span id="element-size"></span> </p> <div id="main"> <div id="margins" tooltip="&margins.tooltip;">
--- a/browser/devtools/markupview/MarkupView.jsm +++ b/browser/devtools/markupview/MarkupView.jsm @@ -838,23 +838,23 @@ MarkupContainer.prototype = { * True if the node has been visually expanded in the tree. */ get expanded() { return this.children.hasAttribute("expanded"); }, 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"); } } }, /** @@ -872,24 +872,24 @@ MarkupContainer.prototype = { get selected() { return this._selected; }, 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"); } } }, /** * Update the container's editor to the current state of the * viewed node. */ @@ -1173,38 +1173,31 @@ ElementEditor.prototype = { /** * Parse a user-entered attribute string and apply the resulting * attributes to the node. This operation is undoable. * * @param string aValue the user-entered value. * @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(); }, /** * Helper function for _setAttribute and _removeAttribute, * returns a function that puts an attribute back the way it was. @@ -1419,16 +1412,110 @@ DocumentWalker.prototype = { } return this.walker.lastChild(); }, previousSibling: function DW_previousSibling() this.walker.previousSibling(), 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, "<") + .replace(/>/g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); } /** * A tree walker filter for avoiding empty whitespace text nodes. */ function whitespaceTextFilter(aNode) { if (aNode.nodeType == Ci.nsIDOMNode.TEXT_NODE &&
--- a/browser/devtools/markupview/markup-view.xhtml +++ b/browser/devtools/markupview/markup-view.xhtml @@ -5,40 +5,43 @@ <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <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><</span><span save="${tag}" class="tagname devtools-theme-tagname"></span><span save="${attrList}"></span><span save="${newAttr}" class="newattr" tabindex="0"></span>></span> + <span id="template-element" save="${elt}" class="editor"><span><</span><span save="${tag}" class="tagname theme-fg-color3"></span><span save="${attrList}"></span><span save="${newAttr}" class="newattr" tabindex="0"></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 devtools-theme-attrname"></span>="<span save="${val}" class="attrvalue devtools-theme-attrvalue"></span>"</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>="<span save="${val}" class="attrvalue theme-fg-color6"></span>"</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><!--</span><pre save="${value}" style="display:inline-block;" tabindex="0"></pre><span>--></span> </span> <span id="template-elementContentSummary" save="${summaryElt}" class="summary"> … </span> - <span id="template-elementClose" save="${closeElt}"></<span save="${closeTag}" class="tagname devtools-theme-tagname"></span>></span> + <span id="template-elementClose" save="${closeElt}"></<span save="${closeTag}" class="tagname theme-fg-color3"></span>></span> </div> <div id="previewbar" class="disabled"> <div id="preview"/> <div id="viewbox"/> </div> </body> </html>
--- a/browser/devtools/markupview/test/browser_inspector_markup_edit.html +++ b/browser/devtools/markupview/test/browser_inspector_markup_edit.html @@ -34,10 +34,11 @@ </div> </div> <div id="node22" class="unchanged"></div> <div id="node23"></div> <div id="node24"></div> <div id="retag-me"> <div id="retag-me-2"></div> </div> + <div id="node25"></div> </body> </html>
--- a/browser/devtools/markupview/test/browser_inspector_markup_edit.js +++ b/browser/devtools/markupview/test/browser_inspector_markup_edit.js @@ -37,22 +37,37 @@ function test() { { aField.focus(); EventUtils.sendKey("return", inspector.panelWin); let input = inplaceEditor(aField).input; input.value = aValue; 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 & 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."); } } // All the mutation types we want to test. let edits = [ { desc: "Change an attribute", before: function() { @@ -71,33 +86,34 @@ function test() { assertAttributes(doc.querySelector("#node1"), { id: "node1", class: "changednode1" }); } }, { - 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", class: "unchanged" }); }, execute: function(after) { let editor = markup.getContainer(doc.querySelector("#node22")).editor; let attr = editor.attrs["class"].querySelector(".editable"); editField(attr, 'class="""'); executeSoon(after); }, after: function() { assertAttributes(doc.querySelector("#node22"), { id: "node22", - class: "unchanged" + class: "" }); } }, { desc: "Remove an attribute", before: function() { assertAttributes(doc.querySelector("#node4"), { @@ -136,31 +152,35 @@ function test() { id: "node14", class: "newclass", style: "color:green" }); } }, { - 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", }); }, execute: function(after) { let editor = markup.getContainer(doc.querySelector("#node23")).editor; let attr = editor.newAttr; editField(attr, 'class="newclass" style="""'); executeSoon(after); }, after: function() { assertAttributes(doc.querySelector("#node23"), { id: "node23", + class: "newclass", + style: "" }); } }, { desc: "Try add attributes by adding to an existing attribute's entry", before: function() { assertAttributes(doc.querySelector("#node24"), { @@ -171,16 +191,17 @@ function test() { let editor = markup.getContainer(doc.querySelector("#node24")).editor; let attr = editor.attrs["id"].querySelector(".editable"); editField(attr, attr.textContent + ' class="""'); executeSoon(after); }, after: function() { assertAttributes(doc.querySelector("#node24"), { id: "node24", + class: "" }); } }, { desc: "Edit text", before: function() { let node = doc.querySelector('.node6').firstChild; @@ -193,16 +214,37 @@ function test() { let field = editor.elt.querySelector("pre"); editField(field, "New text"); }, after: function() { let node = doc.querySelector('.node6').firstChild; is(node.nodeValue, "New text", "Text should be changed."); }, }, + + { + desc: "Add an attribute value containing < > ü \" & '", + 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>¶m2=ü"bl\'ah"'); + }, + after: function() { + assertAttributes(doc.querySelector("#node25"), { + id: "node25", + src: "somefile.html?param1=<a>¶m2=ü"bl'ah" + }); + } + }, ]; // Create the helper tab for parsing... gBrowser.selectedTab = gBrowser.addTab(); gBrowser.selectedBrowser.addEventListener("load", function onload() { gBrowser.selectedBrowser.removeEventListener("load", onload, true); doc = content.document; waitForFocus(setupTest, content);
--- a/browser/devtools/responsivedesign/test/browser_responsiveuiaddcustompreset.js +++ b/browser/devtools/responsivedesign/test/browser_responsiveuiaddcustompreset.js @@ -1,13 +1,14 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ function test() { let instance, deletedPresetA, deletedPresetB, oldPrompt; + let mgr = ResponsiveUI.ResponsiveUIManager; waitForExplicitFinish(); gBrowser.selectedTab = gBrowser.addTab(); gBrowser.selectedBrowser.addEventListener("load", function onload() { gBrowser.selectedBrowser.removeEventListener("load", onload, true); waitForFocus(startTest, content); }, true); @@ -22,18 +23,18 @@ function test() { returnBool: true, prompt: function(aParent, aDialogTitle, aText, aValue, aCheckMsg, aCheckState) { aValue.value = this.value; return this.returnBool; } }; document.getElementById("Tools:ResponsiveUI").removeAttribute("disabled"); + mgr.once("on", onUIOpen); synthesizeKeyFromKeyTag("key_responsiveUI"); - executeSoon(onUIOpen); } function onUIOpen() { // Is it open? let container = gBrowser.getBrowserContainer(); is(container.getAttribute("responsivemode"), "true", "In responsive mode."); instance = gBrowser.selectedTab.__responsiveUI; @@ -61,29 +62,41 @@ function test() { // Adds the custom preset with "Testing preset" Services.prompt.value = "Testing preset"; Services.prompt.returnBool = true; instance.addbutton.doCommand(); 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."); + + instance = gBrowser.selectedTab.__responsiveUI; - let container = gBrowser.getBrowserContainer(); - is(container.getAttribute("responsivemode"), "true", "In responsive mode."); + testCustomPresetInList(); + }); - instance = gBrowser.selectedTab.__responsiveUI; - - 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() { let customPresetIndex = getPresetIndex("456x123 (Testing preset)"); ok(customPresetIndex >= 0, "is the previously added preset (idx = " + customPresetIndex + ") in the list of items"); instance.menulist.selectedIndex = customPresetIndex;
new file mode 100644 --- /dev/null +++ b/browser/devtools/shared/theme-switching.js @@ -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); +})()
--- a/browser/devtools/styleinspector/CssHtmlTree.jsm +++ b/browser/devtools/styleinspector/CssHtmlTree.jsm @@ -129,37 +129,32 @@ this.CssHtmlTree = function CssHtmlTree( this.propertyViews = []; let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"]. getService(Ci.nsIXULChromeRegistry); this.getRTLAttr = chromeReg.isLocaleRTL("global") ? "rtl" : "ltr"; // 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); // Nodes used in templating this.root = this.styleDocument.getElementById("root"); this.templateRoot = this.styleDocument.getElementById("templateRoot"); this.propertyContainer = this.styleDocument.getElementById("propertyContainer"); // No results text. this.noResults = this.styleDocument.getElementById("noResults"); // The element that we're inspecting, and the document that it comes from. this.viewedElement = null; this.createStyleViews(); - this.createContextMenu(); } /** * Memoized lookup of a l10n string from a string bundle. * @param {string} aName The key to lookup. * @returns A localized version of the given key. */ CssHtmlTree.l10n = function CssHtmlTree_l10n(aName) @@ -201,20 +196,16 @@ CssHtmlTree.processTemplate = function C while (duplicated.firstChild) { aDestination.appendChild(duplicated.firstChild); } }; 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); }); CssHtmlTree.prototype = { // Cache the list of properties that match the selected element. _matchedProperties: null, @@ -434,107 +425,16 @@ CssHtmlTree.prototype = { if (!this._matchedProperties) { this._matchedProperties = this.cssLogic.hasMatchedSelectors(CssHtmlTree.propertyNames); } 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. * * @param aEvent The event object */ focusWindow: function si_focusWindow(aEvent) { let win = this.styleDocument.defaultView; win.focus(); @@ -547,109 +447,28 @@ CssHtmlTree.prototype = { */ computedViewCopy: function si_computedViewCopy(aEvent) { let win = this.styleDocument.defaultView; let text = win.getSelection().toString(); // 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); if (aEvent) { aEvent.preventDefault(); } }, /** - * 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. */ destroy: function CssHtmlTree_destroy() { delete this.viewedElement; // Remove event listeners this.includeBrowserStylesCheckbox.removeEventListener("command", @@ -803,100 +622,84 @@ PropertyView.prototype = { * * @return string */ get propertyHeaderClassName() { 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"; }, /** * Returns the className that should be assigned to the propertyView content * container. * @return string */ get propertyContentClassName() { 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"; }, 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); this.matchedExpander.addEventListener("keydown", function(aEvent) { let keyEvent = Ci.nsIDOMKeyEvent; if (aEvent.keyCode == keyEvent.DOM_VK_F1) { this.mdnLinkClick(); } if (aEvent.keyCode == keyEvent.DOM_VK_RETURN || aEvent.keyCode == keyEvent.DOM_VK_SPACE) { 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; }, 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; }, /** * Refresh the panel's CSS property value. */ @@ -906,25 +709,25 @@ PropertyView.prototype = { this.element.nextElementSibling.className = this.propertyContentClassName; if (this.prevViewedElement != this.tree.viewedElement) { this._matchedSelectorViews = null; this.prevViewedElement = this.tree.viewedElement; } 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"); return; } this.tree.numVisibleProperties++; - this.valueNode.textContent = this.propertyInfo.value; + this.valueNode.textContent = this.valueNode.title = this.propertyInfo.value; this.refreshMatchedSelectors(); }, /** * Refresh the panel matched rules. */ refreshMatchedSelectors: function PropertyView_refreshMatchedSelectors() { @@ -1051,31 +854,22 @@ SelectorView.prototype = { return SelectorView.STATUS_NAMES[this.selectorInfo.status]; }, /** * Get class name for selector depending on status */ 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) { let source = this.selectorInfo.sourceElement; let inspector = this.tree.styleInspector.inspector; if (inspector.selection.node == source) { result = "this";
--- a/browser/devtools/styleinspector/CssRuleView.jsm +++ b/browser/devtools/styleinspector/CssRuleView.jsm @@ -858,31 +858,31 @@ TextProperty.prototype = { * property will be available with the user interface. * * @param {Document} aDoc * The document that will contain the rule view. * @param {object} aStore * 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(); } CssRuleView.prototype = { // The element that we're inspecting. _viewedElement: null, /** @@ -892,35 +892,18 @@ CssRuleView.prototype = { return this.element.querySelectorAll(".styleinspector-propertyeditor").length > 0; }, destroy: function CssRuleView_destroy() { 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); } }, /** * Update the highlighted element. * @@ -1031,137 +1014,40 @@ CssRuleView.prototype = { // Run through the current list of rules, attaching // their editors in order. Create editors if needed. let lastInheritedSource = ""; for each (let rule in this._elementStyle.rules) { 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); } if (!rule.editor) { new RuleEditor(this, rule); } this.element.appendChild(rule.editor.element); } }, /** - * 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. * * @param {Event} aEvent * The event object. */ _onCopy: function CssRuleView_onCopy(aEvent) { - let target = this.doc.popupNode || aEvent.target; + let target = aEvent.target; + let text; if (target.nodeName == "input") { let start = Math.min(target.selectionStart, target.selectionEnd); let end = Math.max(target.selectionStart, target.selectionEnd); let count = end - start; text = target.value.substr(start, count); } else { @@ -1174,159 +1060,19 @@ CssRuleView.prototype = { // Remove "inline" let inline = _strings.GetStringFromName("rule.sourceInline"); let rx = new RegExp("^" + inline + "\\r?\\n?", "g"); text = text.replace(rx, ""); } clipboardHelper.copyString(text, this.doc); - if (aEvent) { - 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); + aEvent.preventDefault(); }, - /** - * 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); - } - } }; /** * Create a RuleEditor. * * @param {CssRuleView} aRuleView * The CssRuleView containg the document holding this rule editor. * @param {Rule} aRule @@ -1345,26 +1091,26 @@ function RuleEditor(aRuleView, aRule) this._create(); } 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 // span to be placed absolutely against. this.element.style.position = "relative"; // 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() { let rule = this.rule; let evt = this.doc.createEvent("CustomEvent"); evt.initCustomEvent("CssRuleViewCSSLinkClicked", true, false, { rule: rule, }); @@ -1373,17 +1119,17 @@ RuleEditor.prototype = { let code = createChild(this.element, "div", { class: "ruleview-code" }); let header = createChild(code, "div", {}); this.selectorText = createChild(header, "span", { - class: "ruleview-selector" + class: "ruleview-selector theme-fg-color3" }); this.openBrace = createChild(header, "span", { class: "ruleview-ruleopen", textContent: " {" }); code.addEventListener("click", function() { @@ -1594,26 +1340,25 @@ TextPropertyEditor.prototype = { * Create the property editor's DOM. */ _create: function TextPropertyEditor_create() { this.element = this.doc.createElementNS(HTML_NS, "li"); 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); this.nameContainer = createChild(this.element, "span", { class: "ruleview-namecontainer" }); this.nameContainer.addEventListener("click", function(aEvent) { // Clicks within the name shouldn't propagate any further. @@ -1621,17 +1366,17 @@ TextPropertyEditor.prototype = { if (aEvent.target === propertyContainer) { this.nameSpan.click(); } }.bind(this), false); // 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", }); editableField({ start: this._onStartEditing, element: this.nameSpan, done: this._onNameDone, advanceChars: ':' @@ -1652,17 +1397,17 @@ TextPropertyEditor.prototype = { this.valueSpan.click(); } }.bind(this), false); // Property value, editable when focused. Changes to the // 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", }); // Save the initial value as the last committed value, // for restoring after pressing escape. this.committed = { name: this.prop.name, value: this.prop.value, priority: this.prop.priority }; @@ -1763,23 +1508,23 @@ TextPropertyEditor.prototype = { class: "ruleview-computed" }); if (computed.overridden) { li.classList.add("ruleview-overridden"); } 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, ";"); } // Show or hide the expander as needed. if (showExpander) { this.expander.style.visibility = "visible"; @@ -1788,27 +1533,37 @@ TextPropertyEditor.prototype = { } }, /** * Handles clicks on the disabled property. */ _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(); }, /** * Handles clicks on the computed property expander. */ _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(); }, /** * Called when the property name's inplace editor is closed. * Ignores the change if the user pressed escape, otherwise * commits it. * @@ -2041,15 +1796,11 @@ XPCOMUtils.defineLazyGetter(this, "clipb getService(Ci.nsIClipboardHelper); }); XPCOMUtils.defineLazyGetter(this, "_strings", function() { return Services.strings.createBundle( "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); });
--- a/browser/devtools/styleinspector/StyleInspector.jsm +++ b/browser/devtools/styleinspector/StyleInspector.jsm @@ -21,17 +21,17 @@ XPCOMUtils.defineLazyModuleGetter(this, this.EXPORTED_SYMBOLS = ["RuleViewTool", "ComputedViewTool"]; this.RuleViewTool = function RVT_RuleViewTool(aInspector, aWindow, aIFrame) { this.inspector = aInspector; 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() { this.inspector.markDirty(); }.bind(this); this.view.element.addEventListener("CssRuleViewChanged", this._changeHandler)
new file mode 100644 --- /dev/null +++ b/browser/devtools/styleinspector/computedview.xhtml @@ -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>
deleted file mode 100644 --- a/browser/devtools/styleinspector/csshtmltree.xul +++ /dev/null @@ -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>
new file mode 100644 --- /dev/null +++ b/browser/devtools/styleinspector/cssruleview.xhtml @@ -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>
deleted file mode 100644 --- a/browser/devtools/styleinspector/cssruleview.xul +++ /dev/null @@ -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>
new file mode 100644 --- /dev/null +++ b/browser/devtools/styleinspector/ruleview.css @@ -0,0 +1,34 @@ +/* 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 { + display: -moz-box; +} + +.ruleview { + overflow: auto; + -moz-user-select: text; +} + +.ruleview-code { + direction: ltr; +} + +.ruleview-property:not(:hover) > .ruleview-enableproperty { + pointer-events: none; +} + +.ruleview-namecontainer { + cursor: text; +} + +.ruleview-propertycontainer { + cursor: text; + padding-right: 15px; +} + +.ruleview-computedlist:not(.styleinspector-open), +.ruleview-warning[hidden] { + display: none; +}
deleted file mode 100644 --- a/browser/devtools/styleinspector/styleinspector.css +++ /dev/null @@ -1,56 +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 { - 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; -} - -.ruleview-property:not(:hover) > .ruleview-enableproperty { - pointer-events: none; -} - -.ruleview-namecontainer { - cursor: text; -} - -.ruleview-propertycontainer { - cursor: text; - padding-right: 15px; -}
--- a/browser/devtools/styleinspector/test/Makefile.in +++ b/browser/devtools/styleinspector/test/Makefile.in @@ -18,30 +18,30 @@ MOCHITEST_BROWSER_FILES = \ browser_styleinspector_bug_672744_search_filter.js \ $(filter awaiting-promise-based-init, browser_bug589375_keybindings.js) \ browser_styleinspector_bug_689759_no_results_placeholder.js \ browser_bug_692400_element_style.js \ browser_csslogic_inherited.js \ 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 \ browser_ruleview_override.js \ browser_ruleview_ui.js \ browser_ruleview_update.js \ browser_bug705707_is_content_stylesheet.js \ browser_bug722196_property_view_media_queries.js \ browser_bug722196_rule_view_media_queries.js \ 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) MOCHITEST_BROWSER_FILES += \ browser_bug683672.html \ browser_bug705707_is_content_stylesheet.html \ browser_bug705707_is_content_stylesheet_imported.css \ browser_bug705707_is_content_stylesheet_imported2.css \
--- a/browser/devtools/styleinspector/test/browser_bug722691_rule_view_increment.js +++ b/browser/devtools/styleinspector/test/browser_bug722691_rule_view_increment.js @@ -18,17 +18,17 @@ function setUpTests() { doc.body.innerHTML = '<div id="test" style="' + 'margin-top:0px;' + 'padding-top: 0px;' + 'color:#000000;' + '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) { ruleDialog.removeEventListener("load", onLoad, true); let doc = ruleDialog.document; ruleView = new CssRuleView(doc); doc.documentElement.appendChild(ruleView.element); ruleView.highlight(testElement);
--- a/browser/devtools/styleinspector/test/browser_bug_692400_element_style.js +++ b/browser/devtools/styleinspector/test/browser_bug_692400_element_style.js @@ -47,30 +47,22 @@ function SI_checkText() ok(propertyView, "found PropertyView for color"); is(propertyView.hasMatchedSelectors, true, "hasMatchedSelectors is true"); 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(); } function finishUp() { doc = computedView = null; gBrowser.removeCurrentTab(); finish();
deleted file mode 100644 --- a/browser/devtools/styleinspector/test/browser_computedview_bug_703643_context_menu_copy.js +++ /dev/null @@ -1,197 +0,0 @@ -/* vim: set ts=2 et sw=2 tw=80: */ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -// Tests that the style inspector works properly - -let doc; -let win; -let computedView; - -XPCOMUtils.defineLazyGetter(this, "osString", function() { - return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS; -}); - -function createDocument() -{ - doc.body.innerHTML = '<style type="text/css"> ' + - 'span { font-variant: small-caps; color: #000000; } ' + - '.nomatches {color: #ff0000;}</style> <div id="first" style="margin: 10em; ' + - 'font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA">\n' + - '<h1>Some header text</h1>\n' + - '<p id="salutation" style="font-size: 12pt">hi.</p>\n' + - '<p id="body" style="font-size: 12pt">I am a test-case. This text exists ' + - 'solely to provide some things to <span style="color: yellow">' + - 'highlight</span> and <span style="font-weight: bold">count</span> ' + - 'style list-items in the box at right. If you are reading this, ' + - 'you should go do something else instead. Maybe read a book. Or better ' + - 'yet, write some test-cases for another bit of code. ' + - '<span style="font-style: italic">some text</span></p>\n' + - '<p id="closing">more text</p>\n' + - '<p>even more text</p>' + - '</div>'; - doc.title = "Computed view context menu test"; - - openInspector(selectNode) -} - -function selectNode(aInspector) -{ - let span = doc.querySelector("span"); - ok(span, "captain, we have the span"); - - aInspector.selection.setNode(span); - - aInspector.sidebar.once("computedview-ready", function() { - aInspector.sidebar.select("computedview"); - - computedView = getComputedView(aInspector); - win = aInspector.sidebar.getWindowForTab("computedview"); - - Services.obs.addObserver(runStyleInspectorTests, - "StyleInspector-populated", false); - }); -} - - -function runStyleInspectorTests() -{ - Services.obs.removeObserver(runStyleInspectorTests, - "StyleInspector-populated", false); - - let contentDocument = computedView.styleDocument; - 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); - }); -} - -function checkCopySelection() -{ - let contentDocument = computedView.styleDocument; - let props = contentDocument.querySelectorAll(".property-view"); - ok(props, "captain, we have the property-view nodes"); - - let range = document.createRange(); - range.setStart(props[0], 0); - range.setEnd(props[3], 4); - 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]*"; - - SimpleTest.waitForClipboard(function CS_boundCopyCheck() { - return checkClipboardData(expectedPattern); - }, - computedView.siBoundCopy, closeStyleInspector, function() { - failedClipboard(expectedPattern, closeStyleInspector); - }); -} - -function checkClipboardData(aExpectedPattern) -{ - let actual = SpecialPowers.getClipboardData("text/unicode"); - let expectedRegExp = new RegExp(aExpectedPattern, "g"); - return expectedRegExp.test(actual); -} - -function failedClipboard(aExpectedPattern, aCallback) -{ - // Format expected text for comparison - let terminator = osString == "WINNT" ? "\r\n" : "\n"; - aExpectedPattern = aExpectedPattern.replace(/\[\\r\\n\][+*]/g, terminator); - aExpectedPattern = aExpectedPattern.replace(/\\\(/g, "("); - aExpectedPattern = aExpectedPattern.replace(/\\\)/g, ")"); - - let actual = SpecialPowers.getClipboardData("text/unicode"); - - // Trim the right hand side of our strings. This is because expectedPattern - // accounts for windows sometimes adding a newline to our copied data. - aExpectedPattern = aExpectedPattern.trimRight(); - actual = actual.trimRight(); - - dump("TEST-UNEXPECTED-FAIL | Clipboard text does not match expected ... " + - "results (escaped for accurate comparison):\n"); - info("Actual: " + escape(actual)); - info("Expected: " + escape(aExpectedPattern)); - aCallback(); -} - -function closeStyleInspector() -{ - finishUp(); -} - -function finishUp() -{ - computedView = doc = win = null; - gBrowser.removeCurrentTab(); - finish(); -} - -function test() -{ - waitForExplicitFinish(); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true); - doc = content.document; - waitForFocus(createDocument, content); - }, true); - - content.location = "data:text/html,computed view context menu test"; -}
new file mode 100644 --- /dev/null +++ b/browser/devtools/styleinspector/test/browser_computedview_copy.js @@ -0,0 +1,148 @@ +/* vim: set ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Tests that the style inspector works properly + +let doc; +let win; +let computedView; + +XPCOMUtils.defineLazyGetter(this, "osString", function() { + return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS; +}); + +function createDocument() +{ + doc.body.innerHTML = '<style type="text/css"> ' + + 'span { font-variant: small-caps; color: #000000; } ' + + '.nomatches {color: #ff0000;}</style> <div id="first" style="margin: 10em; ' + + 'font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA">\n' + + '<h1>Some header text</h1>\n' + + '<p id="salutation" style="font-size: 12pt">hi.</p>\n' + + '<p id="body" style="font-size: 12pt">I am a test-case. This text exists ' + + 'solely to provide some things to <span style="color: yellow">' + + 'highlight</span> and <span style="font-weight: bold">count</span> ' + + 'style list-items in the box at right. If you are reading this, ' + + 'you should go do something else instead. Maybe read a book. Or better ' + + 'yet, write some test-cases for another bit of code. ' + + '<span style="font-style: italic">some text</span></p>\n' + + '<p id="closing">more text</p>\n' + + '<p>even more text</p>' + + '</div>'; + doc.title = "Computed view context menu test"; + + openInspector(selectNode) +} + +function selectNode(aInspector) +{ + let span = doc.querySelector("span"); + ok(span, "captain, we have the span"); + + aInspector.selection.setNode(span); + + aInspector.sidebar.once("computedview-ready", function() { + aInspector.sidebar.select("computedview"); + + computedView = getComputedView(aInspector); + win = aInspector.sidebar.getWindowForTab("computedview"); + + Services.obs.addObserver(runStyleInspectorTests, + "StyleInspector-populated", false); + }); +} + + +function runStyleInspectorTests() +{ + Services.obs.removeObserver(runStyleInspectorTests, + "StyleInspector-populated", false); + + let contentDocument = computedView.styleDocument; + let prop = contentDocument.querySelector(".property-view"); + ok(prop, "captain, we have the property-view node"); + + checkCopySelection(); +} + +function checkCopySelection() +{ + let contentDocument = computedView.styleDocument; + let props = contentDocument.querySelectorAll(".property-view"); + ok(props, "captain, we have the property-view nodes"); + + let range = document.createRange(); + range.setStart(props[0], 0); + 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]*"; + + SimpleTest.waitForClipboard(function CS_boundCopyCheck() { + return checkClipboardData(expectedPattern); + }, + function() {fireCopyEvent(props[0])}, closeStyleInspector, function() { + failedClipboard(expectedPattern, closeStyleInspector); + }); +} + +function checkClipboardData(aExpectedPattern) +{ + let actual = SpecialPowers.getClipboardData("text/unicode"); + let expectedRegExp = new RegExp(aExpectedPattern, "g"); + return expectedRegExp.test(actual); +} + +function failedClipboard(aExpectedPattern, aCallback) +{ + // Format expected text for comparison + let terminator = osString == "WINNT" ? "\r\n" : "\n"; + aExpectedPattern = aExpectedPattern.replace(/\[\\r\\n\][+*]/g, terminator); + aExpectedPattern = aExpectedPattern.replace(/\\\(/g, "("); + aExpectedPattern = aExpectedPattern.replace(/\\\)/g, ")"); + + let actual = SpecialPowers.getClipboardData("text/unicode"); + + // Trim the right hand side of our strings. This is because expectedPattern + // accounts for windows sometimes adding a newline to our copied data. + aExpectedPattern = aExpectedPattern.trimRight(); + actual = actual.trimRight(); + + dump("TEST-UNEXPECTED-FAIL | Clipboard text does not match expected ... " + + "results (escaped for accurate comparison):\n"); + info("Actual: " + escape(actual)); + info("Expected: " + escape(aExpectedPattern)); + aCallback(); +} + +function closeStyleInspector() +{ + finishUp(); +} + +function finishUp() +{ + computedView = doc = win = null; + gBrowser.removeCurrentTab(); + finish(); +} + +function test() +{ + waitForExplicitFinish(); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.selectedBrowser.addEventListener("load", function(evt) { + gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true); + doc = content.document; + waitForFocus(createDocument, content); + }, true); + + content.location = "data:text/html,computed view context menu test"; +}
deleted file mode 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_bug_703643_context_menu_copy.js +++ /dev/null @@ -1,282 +0,0 @@ -/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -let doc; -let inspector; -let win; - -XPCOMUtils.defineLazyGetter(this, "osString", function() { - return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS; -}); - -function createDocument() -{ - doc.body.innerHTML = '<style type="text/css"> ' + - 'html { color: #000000; } ' + - 'span { font-variant: small-caps; color: #000000; } ' + - '.nomatches {color: #ff0000;}</style> <div id="first" style="margin: 10em; ' + - 'font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA">\n' + - '<h1>Some header text</h1>\n' + - '<p id="salutation" style="font-size: 12pt">hi.</p>\n' + - '<p id="body" style="font-size: 12pt">I am a test-case. This text exists ' + - 'solely to provide some things to <span style="color: yellow">' + - 'highlight</span> and <span style="font-weight: bold">count</span> ' + - 'style list-items in the box at right. If you are reading this, ' + - 'you should go do something else instead. Maybe read a book. Or better ' + - 'yet, write some test-cases for another bit of code. ' + - '<span style="font-style: italic">some text</span></p>\n' + - '<p id="closing">more text</p>\n' + - '<p>even more text</p>' + - '</div>'; - doc.title = "Rule view context menu test"; - - let target = TargetFactory.forTab(gBrowser.selectedTab); - gDevTools.showToolbox(target, "inspector").then(function(toolbox) { - inspector = toolbox.getCurrentPanel(); - inspector.sidebar.select("ruleview"); - win = inspector.sidebar.getWindowForTab("ruleview"); - highlightNode(); - }); -} - -function highlightNode() -{ - // Highlight a node. - let div = content.document.getElementsByTagName("div")[0]; - - inspector.selection.once("new-node", function() { - is(inspector.selection.node, div, "selection matches the div element"); - testClip(); - }); - 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; - let props = contentDoc.querySelectorAll(".ruleview-property"); - let values = contentDoc.querySelectorAll(".ruleview-propertycontainer"); - - let range = document.createRange(); - range.setStart(props[0], 0); - range.setEnd(values[4], 2); - - let selection = win.getSelection(); - selection.addRange(range); - - info("Checking that _boundCopy() returns the correct " + - "clipboard value"); - let expectedPattern = " 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]+" + - "html {[\\r\\n]+" + - " color: rgb\\(0, 0, 0\\);[\\r\\n]*"; - - SimpleTest.waitForClipboard(function IUI_boundCopyCheck() { - return checkClipboardData(expectedPattern); - },ruleView()._boundCopy, testSimpleCopy, function() { - failedClipboard(expectedPattern, testSimpleCopy); - }); -} - -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; - let range = doc.createRange(); - - range.selectNode(aNode); - win.getSelection().addRange(range); -} - -function checkClipboardData(aExpectedPattern) -{ - let actual = SpecialPowers.getClipboardData("text/unicode"); - let expectedRegExp = new RegExp(aExpectedPattern, "g"); - return expectedRegExp.test(actual); -} - -function failedClipboard(aExpectedPattern, aCallback) -{ - // Format expected text for comparison - let terminator = osString == "WINNT" ? "\r\n" : "\n"; - aExpectedPattern = aExpectedPattern.replace(/\[\\r\\n\][+*]/g, terminator); - aExpectedPattern = aExpectedPattern.replace(/\\\(/g, "("); - aExpectedPattern = aExpectedPattern.replace(/\\\)/g, ")"); - - let actual = SpecialPowers.getClipboardData("text/unicode"); - - // Trim the right hand side of our strings. This is because expectedPattern - // accounts for windows sometimes adding a newline to our copied data. - aExpectedPattern = aExpectedPattern.trimRight(); - actual = actual.trimRight(); - - dump("TEST-UNEXPECTED-FAIL | Clipboard text does not match expected ... " + - "results (escaped for accurate comparison):\n"); - info("Actual: " + escape(actual)); - info("Expected: " + escape(aExpectedPattern)); - aCallback(); -} - -function finishup() -{ - gBrowser.removeCurrentTab(); - doc = inspector = null; - finish(); -} - -function test() -{ - waitForExplicitFinish(); - - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, - true); - doc = content.document; - waitForFocus(createDocument, content); - }, true); - - content.location = "data:text/html,<p>rule view context menu test</p>"; -}
new file mode 100644 --- /dev/null +++ b/browser/devtools/styleinspector/test/browser_ruleview_copy.js @@ -0,0 +1,145 @@ +/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +let doc; +let inspector; +let win; + +XPCOMUtils.defineLazyGetter(this, "osString", function() { + return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS; +}); + +function createDocument() +{ + doc.body.innerHTML = '<style type="text/css"> ' + + 'html { color: #000000; } ' + + 'span { font-variant: small-caps; color: #000000; } ' + + '.nomatches {color: #ff0000;}</style> <div id="first" style="margin: 10em; ' + + 'font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA">\n' + + '<h1>Some header text</h1>\n' + + '<p id="salutation" style="font-size: 12pt">hi.</p>\n' + + '<p id="body" style="font-size: 12pt">I am a test-case. This text exists ' + + 'solely to provide some things to <span style="color: yellow">' + + 'highlight</span> and <span style="font-weight: bold">count</span> ' + + 'style list-items in the box at right. If you are reading this, ' + + 'you should go do something else instead. Maybe read a book. Or better ' + + 'yet, write some test-cases for another bit of code. ' + + '<span style="font-style: italic">some text</span></p>\n' + + '<p id="closing">more text</p>\n' + + '<p>even more text</p>' + + '</div>'; + doc.title = "Rule view context menu test"; + + let target = TargetFactory.forTab(gBrowser.selectedTab); + gDevTools.showToolbox(target, "inspector").then(function(toolbox) { + inspector = toolbox.getCurrentPanel(); + inspector.sidebar.select("ruleview"); + win = inspector.sidebar.getWindowForTab("ruleview"); + highlightNode(); + }); +} + +function highlightNode() +{ + // Highlight a node. + let div = content.document.getElementsByTagName("div")[0]; + + inspector.selection.once("new-node", function() { + is(inspector.selection.node, div, "selection matches the div element"); + executeSoon(checkCopySelection); + }); + executeSoon(function() { + inspector.selection.setNode(div); + }); +} + +function checkCopySelection() +{ + let contentDoc = win.document; + let props = contentDoc.querySelectorAll(".ruleview-property"); + let values = contentDoc.querySelectorAll(".ruleview-propertycontainer"); + + let range = document.createRange(); + range.setStart(props[0], 0); + range.setEnd(values[4], 2); + + let selection = win.getSelection(); + selection.addRange(range); + + info("Checking that _boundCopy() returns the correct " + + "clipboard value"); + let expectedPattern = " 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]+" + + "html {[\\r\\n]+" + + " color: rgb\\(0, 0, 0\\);[\\r\\n]*"; + + SimpleTest.waitForClipboard(function IUI_boundCopyCheck() { + return checkClipboardData(expectedPattern); + },function() {fireCopyEvent(props[0])}, finishup, function() { + failedClipboard(expectedPattern, finishup); + }); +} + +function selectNode(aNode) { + let doc = aNode.ownerDocument; + let win = doc.defaultView; + let range = doc.createRange(); + + range.selectNode(aNode); + win.getSelection().addRange(range); +} + +function checkClipboardData(aExpectedPattern) +{ + let actual = SpecialPowers.getClipboardData("text/unicode"); + let expectedRegExp = new RegExp(aExpectedPattern, "g"); + return expectedRegExp.test(actual); +} + +function failedClipboard(aExpectedPattern, aCallback) +{ + // Format expected text for comparison + let terminator = osString == "WINNT" ? "\r\n" : "\n"; + aExpectedPattern = aExpectedPattern.replace(/\[\\r\\n\][+*]/g, terminator); + aExpectedPattern = aExpectedPattern.replace(/\\\(/g, "("); + aExpectedPattern = aExpectedPattern.replace(/\\\)/g, ")"); + + let actual = SpecialPowers.getClipboardData("text/unicode"); + + // Trim the right hand side of our strings. This is because expectedPattern + // accounts for windows sometimes adding a newline to our copied data. + aExpectedPattern = aExpectedPattern.trimRight(); + actual = actual.trimRight(); + + dump("TEST-UNEXPECTED-FAIL | Clipboard text does not match expected ... " + + "results (escaped for accurate comparison):\n"); + info("Actual: " + escape(actual)); + info("Expected: " + escape(aExpectedPattern)); + aCallback(); +} + +function finishup() +{ + gBrowser.removeCurrentTab(); + doc = inspector = null; + finish(); +} + +function test() +{ + waitForExplicitFinish(); + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.selectedBrowser.addEventListener("load", function(evt) { + gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, + true); + doc = content.document; + waitForFocus(createDocument, content); + }, true); + + content.location = "data:text/html,<p>rule view context menu test</p>"; +}
--- a/browser/devtools/styleinspector/test/browser_ruleview_editor_changedvalues.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_editor_changedvalues.js @@ -32,17 +32,17 @@ function startTest() '.testclass {' + ' background-color: green;' + '}'; let styleNode = addStyle(doc, style); 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) { ruleDialog.removeEventListener("load", onLoad, true); let doc = ruleDialog.document; ruleView = new CssRuleView(doc); doc.documentElement.appendChild(ruleView.element); ruleView.element.addEventListener("CssRuleViewChanged", ruleViewChanged, false);
--- a/browser/devtools/styleinspector/test/browser_ruleview_ui.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_ui.js @@ -32,17 +32,17 @@ function startTest() '.testclass, .unmatched {' + ' background-color: green;' + '}'; let styleNode = addStyle(doc, style); 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) { ruleDialog.removeEventListener("load", onLoad); let doc = ruleDialog.document; ruleView = new CssRuleView(doc); doc.documentElement.appendChild(ruleView.element); ruleView.element.addEventListener("CssRuleViewChanged", ruleViewChanged, false);
--- a/browser/devtools/styleinspector/test/browser_ruleview_update.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_update.js @@ -24,17 +24,17 @@ function startTest() let styleNode = addStyle(doc, style); doc.body.innerHTML = '<div id="testid" class="testclass">Styled Node</div>'; testElement = doc.getElementById("testid"); 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) { ruleDialog.removeEventListener("load", onLoad); let doc = ruleDialog.document; ruleView = new CssRuleView(doc); doc.documentElement.appendChild(ruleView.element); ruleView.highlight(testElement);
--- a/browser/devtools/styleinspector/test/browser_styleinspector_bug_672744_search_filter.js +++ b/browser/devtools/styleinspector/test/browser_styleinspector_bug_672744_search_filter.js @@ -62,17 +62,17 @@ function SI_toggleDefaultStyles() checkbox.click(); } 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(); let win =computedView.styleWindow; EventUtils.synthesizeKey("c", {}, win); EventUtils.synthesizeKey("o", {}, win); EventUtils.synthesizeKey("l", {}, win);
--- a/browser/devtools/styleinspector/test/head.js +++ b/browser/devtools/styleinspector/test/head.js @@ -94,16 +94,22 @@ function waitForEditorBlur(aEditor, aCal input.addEventListener("blur", function onBlur() { input.removeEventListener("blur", onBlur, false); executeSoon(function() { 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'); var button = 2; // right click evt.initMouseEvent('contextmenu', true, true, element.ownerDocument.defaultView, 1, 0, 0, 0, 0, false, false, false, false, button, null);
--- a/browser/locales/en-US/chrome/browser/devtools/styleinspector.dtd +++ b/browser/locales/en-US/chrome/browser/devtools/styleinspector.dtd @@ -22,19 +22,11 @@ - tree. --> <!ENTITY selectedElementLabel "Selected element:"> <!-- LOCALIZATION NOTE (noPropertiesFound): In the case where there are no CSS - properties to display e.g. due to search criteria this message is - 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">
--- a/browser/locales/en-US/chrome/browser/devtools/styleinspector.properties +++ b/browser/locales/en-US/chrome/browser/devtools/styleinspector.properties @@ -41,83 +41,11 @@ rule.inheritedFrom=Inherited from %S # This is the link title shown in the hover tooltip. helpLinkTitle=Read the documentation for this property # LOCALIZATION NOTE (rule.warning.title): When an invalid property value is # entered into the rule view a warning icon is displayed. This text is used for # 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.
new file mode 100644 index 0000000000000000000000000000000000000000..09691bc5e540079d8b83efbd4aa78f2b71e03d95 GIT binary patch literal 177 zc%17D@N?(olHy`uVBq!ia0vp^tU%1c!3HD^Kbl$tsR~aQ#}JO_<QXREoZJG>84N%F z|NmdoVMgMiHL8}{+htBLUKCE#OJm{IySrmLYe%uej`UxLWHu;tL~JM%2Wn_2IR2#4 zGU4Df&f<vlwRh$*ALjXLyE#JoSK4!**j=JM2XAHXN_*lHu|u#;QS9rP=<_^BEES}l bsW2G6i@Q8)Zo@918yGxY{an^LB{Ts5rvyQk
--- a/browser/themes/linux/devtools/common.css +++ b/browser/themes/linux/devtools/common.css @@ -134,16 +134,17 @@ } /* Text input */ .devtools-textinput, .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; background-image: -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35)); padding: 3px; box-shadow: 0 1px 1px hsla(210,8%,5%,.3) inset, 0 0 0 1px hsla(210,16%,76%,.1) inset, 0 1px 0 hsla(210,16%,76%,.15); @@ -330,39 +331,9 @@ 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; } .devtools-sidebar-tabs > tabs > tab[selected=true]:hover:active { background-image: linear-gradient(#1f3e4f, #1b3243), @solidSeparator@; 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
new file mode 100644 --- /dev/null +++ b/browser/themes/linux/devtools/computedview.css @@ -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; +}
deleted file mode 100644 --- a/browser/themes/linux/devtools/csshtmltree.css +++ /dev/null @@ -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; -}
new file mode 100644 --- /dev/null +++ b/browser/themes/linux/devtools/dark-theme.css @@ -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; +}
new file mode 100644 --- /dev/null +++ b/browser/themes/linux/devtools/floating-scrollbars-light.css @@ -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; +}
--- a/browser/themes/linux/devtools/floating-scrollbars.css +++ b/browser/themes/linux/devtools/floating-scrollbars.css @@ -5,29 +5,29 @@ scrollbar { position: relative; background-color: transparent; background-image: none; z-index: 2147483647; padding: 2px; } 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; } scrollbar scrollbarbutton, scrollbar gripper { display: none; }
--- a/browser/themes/linux/devtools/font-inspector.css +++ b/browser/themes/linux/devtools/font-inspector.css @@ -1,14 +1,13 @@ * { -moz-box-sizing: border-box; } body { - background: #F9F9F9; margin: 0; padding-bottom: 20px; } #all-fonts { padding: 0 5px; margin: 0; } @@ -19,26 +18,33 @@ body { margin: 3px; cursor: pointer; position: fixed; bottom: 0; right: 0; } .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; } .font-preview { height: 60px; width: 100%; border: 0; display: block; @@ -52,28 +58,23 @@ body { .font-name { display: inline; } .font-css-code { max-width: 100%; overflow: hidden; text-overflow: ellipsis; - background: white; padding: 5px; - border: 1px dotted #CCC; } -.font-is-local, -.font-is-remote, -.font-format-url, -.font-css { - color: #999 +.theme-light .font-css-code, +.theme-light .font-url { + border: 1px solid #CCC; + background: white; } -.font-url { - border: 1px solid #CCC; - color: #888; +.theme-dark .font-css-code, +.theme-dark .font-url { + border: 1px solid #333; + background: black; + color: white; } - -.font-url:focus { - color: black; -}
--- a/browser/themes/linux/devtools/layoutview.css +++ b/browser/themes/linux/devtools/layoutview.css @@ -1,22 +1,25 @@ /* 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/. */ -body { - background: url(layout-background-grid.png), -moz-radial-gradient(50% 70%, circle cover, hsl(210,53%,45%) 0%, hsl(210,54%,33%) 100%); +.theme-dark .theme-body { + background-image: url(layout-background-grid.png); +} + +.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; } -#element-size { - color: hsl(210,100%,95%); -} - #main { border-color: hsla(210,100%,85%,0.7); border-style: dotted; } #main > .border { color: hsl(210,53%,45%); }
new file mode 100644 --- /dev/null +++ b/browser/themes/linux/devtools/light-theme.css @@ -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; +}
--- a/browser/themes/linux/devtools/markup-view.css +++ b/browser/themes/linux/devtools/markup-view.css @@ -2,24 +2,16 @@ * 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/. */ * { padding: 0; margin: 0; } -body { - color: hsl(0,0%,50%); -} - -.text { - color: black; -} - .newattr { cursor: pointer; } .selected { background-color: hsl(0,0%,90%); } @@ -36,22 +28,16 @@ li.container { } .codebox { padding-left: 14px; } .expander { position: absolute; - -moz-appearance: treetwisty; - padding: 11px 0; -} - -.expander[expanded] { - -moz-appearance: treetwistyopen; } .more-nodes { padding-left: 16px; } .styleinspector-propertyeditor { border: 1px solid #CCC;
new file mode 100644 --- /dev/null +++ b/browser/themes/linux/devtools/ruleview.css @@ -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; +}
--- a/browser/themes/linux/jar.mn +++ b/browser/themes/linux/jar.mn @@ -110,26 +110,28 @@ browser.jar: skin/classic/browser/tabbrowser/tab-overflow-border.png (tabbrowser/tab-overflow-border.png) skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png) skin/classic/browser/tabview/edit-light.png (tabview/edit-light.png) skin/classic/browser/tabview/search.png (tabview/search.png) skin/classic/browser/tabview/stack-expander.png (tabview/stack-expander.png) skin/classic/browser/tabview/tabview.png (tabview/tabview.png) skin/classic/browser/tabview/tabview.css (tabview/tabview.css) * skin/classic/browser/devtools/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) skin/classic/browser/devtools/command-paintflashing.png (devtools/command-paintflashing.png) skin/classic/browser/devtools/command-responsivemode.png (devtools/command-responsivemode.png) skin/classic/browser/devtools/command-scratchpad.png (devtools/command-scratchpad.png) 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) 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) skin/classic/browser/devtools/orion-task.png (devtools/orion-task.png) @@ -182,26 +184,29 @@ browser.jar: skin/classic/browser/devtools/debugger-step-over.png (devtools/debugger-step-over.png) skin/classic/browser/devtools/responsive-se-resizer.png (devtools/responsive-se-resizer.png) skin/classic/browser/devtools/responsive-vertical-resizer.png (devtools/responsive-vertical-resizer.png) skin/classic/browser/devtools/responsive-background.png (devtools/responsive-background.png) skin/classic/browser/devtools/tools-icons-small.png (devtools/tools-icons-small.png) 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) skin/classic/browser/devtools/tool-debugger.png (devtools/tool-debugger.png) skin/classic/browser/devtools/tool-inspector.png (devtools/tool-inspector.png) skin/classic/browser/devtools/tool-styleeditor.png (devtools/tool-styleeditor.png) skin/classic/browser/devtools/tool-profiler.png (devtools/tool-profiler.png) skin/classic/browser/devtools/close.png (devtools/close.png) skin/classic/browser/devtools/undock.png (devtools/undock.png) skin/classic/browser/devtools/font-inspector.css (devtools/font-inspector.css) + 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 skin/classic/browser/sync-24-throbber.png skin/classic/browser/sync-32.png skin/classic/browser/sync-bg.png skin/classic/browser/sync-128.png skin/classic/browser/sync-desktopIcon.png
new file mode 100644 index 0000000000000000000000000000000000000000..09691bc5e540079d8b83efbd4aa78f2b71e03d95 GIT binary patch literal 177 zc%17D@N?(olHy`uVBq!ia0vp^tU%1c!3HD^Kbl$tsR~aQ#}JO_<QXREoZJG>84N%F z|NmdoVMgMiHL8}{+htBLUKCE#OJm{IySrmLYe%uej`UxLWHu;tL~JM%2Wn_2IR2#4 zGU4Df&f<vlwRh$*ALjXLyE#JoSK4!**j=JM2XAHXN_*lHu|u#;QS9rP=<_^BEES}l bsW2G6i@Q8)Zo@918yGxY{an^LB{Ts5rvyQk
--- a/browser/themes/osx/devtools/common.css +++ b/browser/themes/osx/devtools/common.css @@ -139,16 +139,17 @@ } /* Text input */ .devtools-textinput, .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; background-image: -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35)); padding: 3px; box-shadow: 0 1px 1px hsla(210,8%,5%,.3) inset, 0 0 0 1px hsla(210,16%,76%,.1) inset, 0 1px 0 hsla(210,16%,76%,.15); @@ -349,39 +350,9 @@ 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; } .devtools-sidebar-tabs > tabs > tab[selected=true]:hover:active { background-image: linear-gradient(#1f3e4f, #1b3243), @solidSeparator@; 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
new file mode 100644 --- /dev/null +++ b/browser/themes/osx/devtools/computedview.css @@ -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; +}
deleted file mode 100644 --- a/browser/themes/osx/devtools/csshtmltree.css +++ /dev/null @@ -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; -} -
new file mode 100644 --- /dev/null +++ b/browser/themes/osx/devtools/dark-theme.css @@ -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; +}
new file mode 100644 --- /dev/null +++ b/browser/themes/osx/devtools/floating-scrollbars-light.css @@ -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; +}
--- a/browser/themes/osx/devtools/font-inspector.css +++ b/browser/themes/osx/devtools/font-inspector.css @@ -1,14 +1,13 @@ * { -moz-box-sizing: border-box; } body { - background: #F9F9F9; margin: 0; padding-bottom: 20px; } #all-fonts { padding: 0 5px; margin: 0; } @@ -19,26 +18,33 @@ body { margin: 3px; cursor: pointer; position: fixed; bottom: 0; right: 0; } .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; } .font-preview { height: 60px; width: 100%; border: 0; display: block; @@ -52,28 +58,23 @@ body { .font-name { display: inline; } .font-css-code { max-width: 100%; overflow: hidden; text-overflow: ellipsis; - background: white; padding: 5px; - border: 1px dotted #CCC; } -.font-is-local, -.font-is-remote, -.font-format-url, -.font-css { - color: #999 +.theme-light .font-css-code, +.theme-light .font-url { + border: 1px solid #CCC; + background: white; } -.font-url { - border: 1px solid #CCC; - color: #888; +.theme-dark .font-css-code, +.theme-dark .font-url { + border: 1px solid #333; + background: black; + color: white; } - -.font-url:focus { - color: black; -}
--- a/browser/themes/osx/devtools/layoutview.css +++ b/browser/themes/osx/devtools/layoutview.css @@ -1,22 +1,25 @@ /* 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/. */ -body { - background: url(layout-background-grid.png), -moz-radial-gradient(50% 70%, circle cover, hsl(210,53%,45%) 0%, hsl(210,54%,33%) 100%); +.theme-dark .theme-body { + background-image: url(layout-background-grid.png); +} + +.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; } -#element-size { - color: hsl(210,100%,95%); -} - #main { border-color: hsla(210,100%,85%,0.7); border-style: dotted; } #main > .border { color: hsl(210,53%,45%); }
new file mode 100644 --- /dev/null +++ b/browser/themes/osx/devtools/light-theme.css @@ -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; +}
--- a/browser/themes/osx/devtools/markup-view.css +++ b/browser/themes/osx/devtools/markup-view.css @@ -2,24 +2,16 @@ * 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/. */ * { padding: 0; margin: 0; } -body { - color: hsl(0,0%,50%); -} - -.text { - color: black; -} - .newattr { cursor: pointer; } .selected { background-color: hsl(0,0%,90%); } @@ -36,25 +28,16 @@ li.container { } .codebox { padding-left: 14px; } .expander { position: absolute; - -moz-appearance: treetwisty; - top: 0; - left: 0; - width: 14px; - height: 14px; -} - -.expander[expanded] { - -moz-appearance: treetwistyopen; } .more-nodes { padding-left: 16px; } .styleinspector-propertyeditor { border: 1px solid #CCC;
new file mode 100644 --- /dev/null +++ b/browser/themes/osx/devtools/ruleview.css @@ -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; +} +
--- a/browser/themes/osx/jar.mn +++ b/browser/themes/osx/jar.mn @@ -194,27 +194,29 @@ browser.jar: skin/classic/browser/tabbrowser/tabDragIndicator@2x.png (tabbrowser/tabDragIndicator.png) skin/classic/browser/tabview/close.png (tabview/close.png) skin/classic/browser/tabview/edit-light.png (tabview/edit-light.png) skin/classic/browser/tabview/search.png (tabview/search.png) skin/classic/browser/tabview/stack-expander.png (tabview/stack-expander.png) skin/classic/browser/tabview/tabview.png (tabview/tabview.png) skin/classic/browser/tabview/tabview.css (tabview/tabview.css) * skin/classic/browser/devtools/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/command-paintflashing.png (devtools/command-paintflashing.png) skin/classic/browser/devtools/command-responsivemode.png (devtools/command-responsivemode.png) skin/classic/browser/devtools/command-scratchpad.png (devtools/command-scratchpad.png) 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) skin/classic/browser/devtools/orion-task.png (devtools/orion-task.png) skin/classic/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png) skin/classic/browser/devtools/orion-debug-location.png (devtools/orion-debug-location.png) skin/classic/browser/devtools/toolbarbutton-close.png (devtools/toolbarbutton-close.png) * skin/classic/browser/devtools/webconsole.css (devtools/webconsole.css) @@ -267,26 +269,29 @@ browser.jar: skin/classic/browser/devtools/debugger-step-over.png (devtools/debugger-step-over.png) skin/classic/browser/devtools/responsive-se-resizer.png (devtools/responsive-se-resizer.png) skin/classic/browser/devtools/responsive-vertical-resizer.png (devtools/responsive-vertical-resizer.png) skin/classic/browser/devtools/responsive-background.png (devtools/responsive-background.png) skin/classic/browser/devtools/tools-icons-small.png (devtools/tools-icons-small.png) 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) skin/classic/browser/devtools/tool-debugger.png (devtools/tool-debugger.png) skin/classic/browser/devtools/tool-inspector.png (devtools/tool-inspector.png) skin/classic/browser/devtools/tool-styleeditor.png (devtools/tool-styleeditor.png) skin/classic/browser/devtools/tool-profiler.png (devtools/tool-profiler.png) skin/classic/browser/devtools/close.png (devtools/close.png) skin/classic/browser/devtools/undock.png (devtools/undock.png) skin/classic/browser/devtools/font-inspector.css (devtools/font-inspector.css) + 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 skin/classic/browser/sync-32.png skin/classic/browser/sync-bg.png skin/classic/browser/sync-128.png skin/classic/browser/sync-desktopIcon.png skin/classic/browser/sync-mobileIcon.png
new file mode 100644 index 0000000000000000000000000000000000000000..09691bc5e540079d8b83efbd4aa78f2b71e03d95 GIT binary patch literal 177 zc%17D@N?(olHy`uVBq!ia0vp^tU%1c!3HD^Kbl$tsR~aQ#}JO_<QXREoZJG>84N%F z|NmdoVMgMiHL8}{+htBLUKCE#OJm{IySrmLYe%uej`UxLWHu;tL~JM%2Wn_2IR2#4 zGU4Df&f<vlwRh$*ALjXLyE#JoSK4!**j=JM2XAHXN_*lHu|u#;QS9rP=<_^BEES}l bsW2G6i@Q8)Zo@918yGxY{an^LB{Ts5rvyQk
--- a/browser/themes/windows/devtools/common.css +++ b/browser/themes/windows/devtools/common.css @@ -137,16 +137,17 @@ } /* Text input */ .devtools-textinput, .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; background-color: transparent; background-image: -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35)); padding: 3px; transition-property: background-color, border-color, box-shadow; transition-duration: 150ms; @@ -358,39 +359,9 @@ 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; } .devtools-sidebar-tabs > tabs > tab[selected=true]:hover:active { background-image: linear-gradient(#1f3e4f, #1b3243), @solidSeparator@; 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
new file mode 100644 --- /dev/null +++ b/browser/themes/windows/devtools/computedview.css @@ -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; +}
deleted file mode 100644 --- a/browser/themes/windows/devtools/csshtmltree.css +++ /dev/null @@ -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; -}
new file mode 100644 --- /dev/null +++ b/browser/themes/windows/devtools/dark-theme.css @@ -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; +}
new file mode 100644 --- /dev/null +++ b/browser/themes/windows/devtools/floating-scrollbars-light.css @@ -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; +}
--- a/browser/themes/windows/devtools/floating-scrollbars.css +++ b/browser/themes/windows/devtools/floating-scrollbars.css @@ -5,29 +5,29 @@ scrollbar { position: relative; background-color: transparent; background-image: none; z-index: 2147483647; padding: 2px; } 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; } scrollbar scrollbarbutton, scrollbar gripper { display: none; }
--- a/browser/themes/windows/devtools/font-inspector.css +++ b/browser/themes/windows/devtools/font-inspector.css @@ -1,14 +1,13 @@ * { -moz-box-sizing: border-box; } body { - background: #F9F9F9; margin: 0; padding-bottom: 20px; } #all-fonts { padding: 0 5px; margin: 0; } @@ -19,26 +18,33 @@ body { margin: 3px; cursor: pointer; position: fixed; bottom: 0; right: 0; } .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; } .font-preview { height: 60px; width: 100%; border: 0; display: block; @@ -52,28 +58,23 @@ body { .font-name { display: inline; } .font-css-code { max-width: 100%; overflow: hidden; text-overflow: ellipsis; - background: white; padding: 5px; - border: 1px dotted #CCC; } -.font-is-local, -.font-is-remote, -.font-format-url, -.font-css { - color: #999 +.theme-light .font-css-code, +.theme-light .font-url { + border: 1px solid #CCC; + background: white; } -.font-url { - border: 1px solid #CCC; - color: #888; +.theme-dark .font-css-code, +.theme-dark .font-url { + border: 1px solid #333; + background: black; + color: white; } - -.font-url:focus { - color: black; -}
--- a/browser/themes/windows/devtools/layoutview.css +++ b/browser/themes/windows/devtools/layoutview.css @@ -1,22 +1,25 @@ /* 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/. */ -body { - background: url(layout-background-grid.png), -moz-radial-gradient(50% 70%, circle cover, hsl(210,53%,45%) 0%, hsl(210,54%,33%) 100%); +.theme-dark .theme-body { + background-image: url(layout-background-grid.png); +} + +.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; } -#element-size { - color: hsl(210,100%,95%); -} - #main { border-color: hsla(210,100%,85%,0.7); border-style: dotted; } #main > .border { color: hsl(210,53%,45%); }
new file mode 100644 --- /dev/null +++ b/browser/themes/windows/devtools/light-theme.css @@ -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; +}
--- a/browser/themes/windows/devtools/markup-view.css +++ b/browser/themes/windows/devtools/markup-view.css @@ -2,24 +2,16 @@ * 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/. */ * { padding: 0; margin: 0; } -body { - color: hsl(0,0%,50%); -} - -.text { - color: black; -} - .newattr { cursor: pointer; } .selected { background-color: hsl(0,0%,90%); } @@ -36,27 +28,16 @@ li.container { } .codebox { padding-left: 14px; } .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 { padding-left: 16px; } .styleinspector-propertyeditor { border: 1px solid #CCC;
new file mode 100644 --- /dev/null +++ b/browser/themes/windows/devtools/ruleview.css @@ -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; +}
--- a/browser/themes/windows/jar.mn +++ b/browser/themes/windows/jar.mn @@ -136,22 +136,24 @@ browser.jar: skin/classic/browser/tabview/edit-light.png (tabview/edit-light.png) skin/classic/browser/tabview/grain.png (tabview/grain.png) skin/classic/browser/tabview/search.png (tabview/search.png) skin/classic/browser/tabview/stack-expander.png (tabview/stack-expander.png) skin/classic/browser/tabview/tabview.png (tabview/tabview.png) skin/classic/browser/tabview/tabview-inverted.png (tabview/tabview-inverted.png) skin/classic/browser/tabview/tabview.css (tabview/tabview.css) * skin/classic/browser/devtools/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) skin/classic/browser/devtools/command-scratchpad.png (devtools/command-scratchpad.png) skin/classic/browser/devtools/command-tilt.png (devtools/command-tilt.png) 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) @@ -209,26 +211,29 @@ browser.jar: skin/classic/browser/devtools/debugger-step-over.png (devtools/debugger-step-over.png) skin/classic/browser/devtools/responsive-se-resizer.png (devtools/responsive-se-resizer.png) skin/classic/browser/devtools/responsive-vertical-resizer.png (devtools/responsive-vertical-resizer.png) skin/classic/browser/devtools/responsive-background.png (devtools/responsive-background.png) skin/classic/browser/devtools/tools-icons-small.png (devtools/tools-icons-small.png) 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) skin/classic/browser/devtools/tool-debugger.png (devtools/tool-debugger.png) skin/classic/browser/devtools/tool-inspector.png (devtools/tool-inspector.png) skin/classic/browser/devtools/tool-styleeditor.png (devtools/tool-styleeditor.png) skin/classic/browser/devtools/tool-profiler.png (devtools/tool-profiler.png) skin/classic/browser/devtools/close.png (devtools/close.png) skin/classic/browser/devtools/undock.png (devtools/undock.png) skin/classic/browser/devtools/font-inspector.css (devtools/font-inspector.css) + 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 skin/classic/browser/sync-32.png skin/classic/browser/sync-128.png skin/classic/browser/sync-bg.png skin/classic/browser/sync-desktopIcon.png skin/classic/browser/sync-mobileIcon.png @@ -371,26 +376,28 @@ browser.jar: skin/classic/aero/browser/tabview/edit-light.png (tabview/edit-light.png) skin/classic/aero/browser/tabview/grain.png (tabview/grain.png) skin/classic/aero/browser/tabview/search.png (tabview/search.png) skin/classic/aero/browser/tabview/stack-expander.png (tabview/stack-expander.png) skin/classic/aero/browser/tabview/tabview.png (tabview/tabview.png) skin/classic/aero/browser/tabview/tabview-inverted.png (tabview/tabview-inverted.png) skin/classic/aero/browser/tabview/tabview.css (tabview/tabview.css) * skin/classic/aero/browser/devtools/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) skin/classic/aero/browser/devtools/command-paintflashing.png (devtools/command-paintflashing.png) skin/classic/aero/browser/devtools/command-responsivemode.png (devtools/command-responsivemode.png) skin/classic/aero/browser/devtools/command-scratchpad.png (devtools/command-scratchpad.png) 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) skin/classic/aero/browser/devtools/orion-container.css (devtools/orion-container.css) skin/classic/aero/browser/devtools/orion-task.png (devtools/orion-task.png) skin/classic/aero/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png) skin/classic/aero/browser/devtools/orion-debug-location.png (devtools/orion-debug-location.png) skin/classic/aero/browser/devtools/toolbarbutton-close.png (devtools/toolbarbutton-close.png) @@ -444,26 +451,29 @@ browser.jar: skin/classic/aero/browser/devtools/debugger-step-over.png (devtools/debugger-step-over.png) skin/classic/aero/browser/devtools/responsive-se-resizer.png (devtools/responsive-se-resizer.png) skin/classic/aero/browser/devtools/responsive-vertical-resizer.png (devtools/responsive-vertical-resizer.png) skin/classic/aero/browser/devtools/responsive-background.png (devtools/responsive-background.png) skin/classic/aero/browser/devtools/tools-icons-small.png (devtools/tools-icons-small.png) 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) skin/classic/aero/browser/devtools/tool-debugger.png (devtools/tool-debugger.png) skin/classic/aero/browser/devtools/tool-inspector.png (devtools/tool-inspector.png) skin/classic/aero/browser/devtools/tool-styleeditor.png (devtools/tool-styleeditor.png) skin/classic/aero/browser/devtools/tool-profiler.png (devtools/tool-profiler.png) skin/classic/aero/browser/devtools/close.png (devtools/close.png) skin/classic/aero/browser/devtools/undock.png (devtools/undock.png) skin/classic/aero/browser/devtools/font-inspector.css (devtools/font-inspector.css) + 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 skin/classic/aero/browser/sync-32.png skin/classic/aero/browser/sync-128.png skin/classic/aero/browser/sync-bg.png skin/classic/aero/browser/sync-desktopIcon.png skin/classic/aero/browser/sync-mobileIcon.png
--- a/configure.in +++ b/configure.in @@ -7801,30 +7801,32 @@ MOZ_ARG_ENABLE_BOOL(xterm-updates, [ --enable-xterm-updates Update XTERM titles with current command.], MOZ_UPDATE_XTERM=1, MOZ_UPDATE_XTERM= ) 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 ========================================================= dnl Omnijar packaging (bug 552121) dnl ========================================================= dnl Omnijar packaging is compatible with flat packaging. dnl In unpackaged builds, omnijar looks for files as if dnl things were flat packaged. After packaging, all files
--- a/toolkit/components/thumbnails/PageThumbs.jsm +++ b/toolkit/components/thumbnails/PageThumbs.jsm @@ -22,17 +22,20 @@ const EXPIRATION_INTERVAL_SECS = 3600; */ const THUMBNAIL_DIRECTORY = "thumbnails"; /** * The default background color for page 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"); XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", @@ -50,16 +53,80 @@ XPCOMUtils.defineLazyGetter(this, "gCryp XPCOMUtils.defineLazyGetter(this, "gUnicodeConverter", function () { let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"] .createInstance(Ci.nsIScriptableUnicodeConverter); converter.charset = 'utf8'; 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. */ this.PageThumbs = { _initialized: false, /** @@ -129,16 +196,43 @@ this.PageThumbs = { // 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. Services.tm.currentThread.dispatch(function () { canvas.mozFetchAsStream(aCallback, this.contentType); }.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. * @param aCanvas The canvas to draw to. */ captureToCanvas: function PageThumbs_captureToCanvas(aWindow, aCanvas) { let telemetryCaptureTime = new Date(); let [sw, sh, scale] = this._determineCropSize(aWindow, aCanvas); @@ -172,45 +266,49 @@ this.PageThumbs = { if (!this._prefEnabled()) { return; } let url = aBrowser.currentURI.spec; 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)); + + 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) - PageThumbsStorage.copy(url, originalURL); + // 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)); }, /** * Register an expiration filter. * * When thumbnails are going to expire, each registered filter is asked for a * list of thumbnails to keep. * @@ -309,65 +407,109 @@ this.PageThumbs = { } catch (e) { return true; } }, }; 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) { let hash = gCryptoHash; let value = gUnicodeConverter.convertToByteArray(aValue); hash.init(hash.MD5); hash.update(value, value.length); @@ -418,28 +560,30 @@ let PageThumbsStorageMigrator = { }, /** * Bug 239254 added support for having the disk cache and thumbnail * directories on a local path (i.e. ~/.cache/) under Linux. We'll first * 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)] + ); } }; let PageThumbsExpiration = { _filters: [], init: function Expiration_init() { gUpdateTimerManager.registerTimer("browser-cleanup-thumbnails", this, @@ -479,70 +623,56 @@ let PageThumbsExpiration = { for (let filter of this._filters) { if (typeof filter == "function") filter(filterCallback) else filter.filterForThumbnailExpiration(filterCallback); } }, - 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) { PageThumbsStorage.remove(aURI.spec); }, onClearHistory: function Thumbnails_onClearHistory() { PageThumbsStorage.wipe();
--- a/toolkit/components/thumbnails/PageThumbsProtocol.js +++ b/toolkit/components/thumbnails/PageThumbsProtocol.js @@ -22,16 +22,18 @@ const Cc = Components.classes; const Cr = Components.results; const Ci = Components.interfaces; Cu.import("resource://gre/modules/PageThumbs.jsm"); 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. */ function Protocol() { } Protocol.prototype = { @@ -68,18 +70,18 @@ Protocol.prototype = { /** * Constructs a new channel from the given URI for this protocol handler. * @param aURI The URI for which to construct a channel. * @return The newly created channel. */ 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); }, /** * Decides whether to allow a blacklisted port. * @return Always false, we'll never allow ports. */ allowPort: function () false,
--- a/toolkit/components/thumbnails/PageThumbsWorker.js +++ b/toolkit/components/thumbnails/PageThumbsWorker.js @@ -8,101 +8,160 @@ * Do not rely on the API of this worker. In a future version, it might be * fully replaced by a OS.File global I/O worker. */ "use strict"; 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) { break; } } return true; }, 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) if (!entry.isDir && !entry.isSymLink && !skip.has(entry.name))]; }, 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(pathFrom, entry.name); + let to = OS.Path.join(pathTo, entry.name); - let from = OS.Path.join(msg.from, entry.name); - let to = OS.Path.join(msg.to, 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);
--- a/toolkit/components/thumbnails/test/browser_thumbnails_expiration.js +++ b/toolkit/components/thumbnails/test/browser_thumbnails_expiration.js @@ -1,35 +1,32 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ const URL = "http://mochi.test:8888/?t=" + Date.now(); 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) .loadSubScript("resource://gre/modules/PageThumbs.jsm", tmp); 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. yield expireThumbnails([URL1, URL2]); ok(thumbnailExists(URL1), "first thumbnail still exists"); ok(thumbnailExists(URL2), "second thumbnail still exists"); ok(!thumbnailExists(URL3), "third thumbnail has been removed"); @@ -40,20 +37,21 @@ function runTests() { // Remove all thumbnails. yield expireThumbnails([]); ok(!thumbnailExists(URL1), "all thumbnails have been removed"); // 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. let dontExpireDummyURLs = function (cb) cb(urls); PageThumbs.addExpirationFilter(dontExpireDummyURLs); registerCleanupFunction(function () { PageThumbs.removeExpirationFilter(dontExpireDummyURLs); @@ -66,21 +64,35 @@ function runTests() { // Expire thumbnails again. All should be gone by now. yield expireThumbnails([]); remainingURLs = [u for (u of remainingURLs) if (thumbnailExists(u))]; is(remainingURLs.length, 0, "no dummy thumbnails remaining"); } 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); + } + ); }
--- a/toolkit/components/thumbnails/test/browser_thumbnails_storage.js +++ b/toolkit/components/thumbnails/test/browser_thumbnails_storage.js @@ -17,26 +17,26 @@ XPCOMUtils.defineLazyGetter(this, "Sanit * Newly captured thumbnails should be saved as files and they should as well * be removed when the user sanitizes their history. */ function runTests() { yield clearHistory(); 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. while (file.exists() || fileCopy.exists()) { yield clearHistory(); } yield createThumbnail();
--- a/toolkit/components/thumbnails/test/browser_thumbnails_storage_migrate3.js +++ b/toolkit/components/thumbnails/test/browser_thumbnails_storage_migrate3.js @@ -8,19 +8,16 @@ const THUMBNAIL_DIRECTORY = "thumbnails" const PREF_STORAGE_VERSION = "browser.pagethumbnails.storage_version"; let tmp = {}; Cc["@mozilla.org/moz/jssubscript-loader;1"] .getService(Ci.mozIJSSubScriptLoader) .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"); /** * This test makes sure we correctly migrate to thumbnail storage version 3. * This means copying existing thumbnails from the roaming to the local profile * directory and should just apply to Linux. */ @@ -50,17 +47,17 @@ function runTests() { // Pretend to have one of the thumbnails // already in place at the new storage site. name = PageThumbsStorage.getLeafNameForURL(URL3); file = FileUtils.getFile("ProfLD", [THUMBNAIL_DIRECTORY, name]); 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. yield whenFileExists(URL); ok(true, "first thumbnail moved"); // Wait for the second thumbnail to be moved as well. yield whenFileExists(URL2);
--- a/toolkit/components/thumbnails/test/head.js +++ b/toolkit/components/thumbnails/test/head.js @@ -1,15 +1,17 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ 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"); registerCleanupFunction(function () { while (gBrowser.tabs.length > 1) gBrowser.removeTab(gBrowser.tabs[1]); }); @@ -40,17 +42,19 @@ let TestRunner = { }.bind(this)); }, /** * Runs the next available test or finishes if there's no test left. */ 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(); } } }; /** * Continues the current test execution. @@ -80,20 +84,20 @@ function navigateTo(aURI) { } /** * Continues the current test execution when a load event for the given element * has been received. * @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); } /** * Captures a screenshot for the currently selected tab, stores it in the cache, * retrieves it from the cache and compares pixel color values. * @param aRed The red component's intensity. * @param aGreen The green component's intensity. @@ -138,17 +142,17 @@ function retrieveImageDataForURL(aURL, a }); } /** * Checks if a thumbnail for the given URL exists. * @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; } /** * Asynchronously adds visits to a page, invoking a callback function when done. * * @param aPlaceInfo * Can be an nsIURI, in such a case a single LINK visit will be added. @@ -206,23 +210,23 @@ function addVisits(aPlaceInfo, aCallback /** * Calls a given callback when the thumbnail for a given URL has been found * on disk. Keeps trying until the thumbnail has been created. * * @param aURL The URL of the thumbnail's page. * @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); } /** * Calls a given callback when the given file has been removed. * Keeps trying until the file is removed. * * @param aFile The file that is being removed * @param [optional] aCallback
--- a/toolkit/mozapps/installer/packager.py +++ b/toolkit/mozapps/installer/packager.py @@ -266,17 +266,17 @@ def main(): elif args.format == 'jar': formatter = JarFormatter(copier, optimize=args.optimizejars) elif args.format == 'omni': formatter = OmniJarFormatter(copier, buildconfig.substs['OMNIJAR_NAME'], 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): defines['MOZ_OMNIJAR'] = 1 elif 'MOZ_OMNIJAR' in defines: del defines['MOZ_OMNIJAR'] binpath = ''