author | Marco Bonardo <mbonardo@mozilla.com> |
Fri, 02 Mar 2012 14:57:10 +0100 | |
changeset 88151 | f3ac2ec81d34e4cd9d870c43f15e3695cdd72d42 |
parent 88150 | 0c183373c89e1871b9f6289949504a42d5fbba92 (current diff) |
parent 88139 | 343ec916dfd526957ecff6b224d00634be856dd9 (diff) |
child 88152 | f0cc27e3731c8ff2ce405652901a15eff240ad5f |
push id | 22173 |
push user | bmo@edmorley.co.uk |
push date | Sat, 03 Mar 2012 13:14:42 +0000 |
treeherder | mozilla-central@ed57abebd328 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
milestone | 13.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
browser/themes/gnomestripe/inspector.css | file | annotate | diff | comparison | revisions | |
browser/themes/pinstripe/inspector.css | file | annotate | diff | comparison | revisions | |
browser/themes/winstripe/inspector.css | file | annotate | diff | comparison | revisions |
--- a/browser/devtools/debugger/debugger-view.js +++ b/browser/devtools/debugger/debugger-view.js @@ -145,45 +145,45 @@ DebuggerView.Stackframes = { /** * Adds a frame to the stackframes container. * If the frame already exists (was previously added), null is returned. * Otherwise, the newly created element is returned. * * @param number aDepth * The frame depth specified by the debugger. - * @param string aFrameIdText - * The id to be displayed in the list. * @param string aFrameNameText * The name to be displayed in the list. + * @param string aFrameDetailsText + * The details to be displayed in the list. * @return object * The newly created html node representing the added frame. */ - addFrame: function DVF_addFrame(aDepth, aFrameIdText, aFrameNameText) { + addFrame: function DVF_addFrame(aDepth, aFrameNameText, aFrameDetailsText) { // make sure we don't duplicate anything if (document.getElementById("stackframe-" + aDepth)) { return null; } let frame = document.createElement("div"); - let frameId = document.createElement("span"); let frameName = document.createElement("span"); + let frameDetails = document.createElement("span"); // create a list item to be added to the stackframes container frame.id = "stackframe-" + aDepth; frame.className = "dbg-stackframe list-item"; - // this list should display the id and name of the frame - frameId.className = "dbg-stackframe-id"; + // this list should display the name and details for the frame frameName.className = "dbg-stackframe-name"; - frameId.appendChild(document.createTextNode(aFrameIdText)); + frameDetails.className = "dbg-stackframe-details"; frameName.appendChild(document.createTextNode(aFrameNameText)); + frameDetails.appendChild(document.createTextNode(aFrameDetailsText)); - frame.appendChild(frameId); frame.appendChild(frameName); + frame.appendChild(frameDetails); this._frames.appendChild(frame); // return the element for later use if necessary return frame; }, /** @@ -1069,25 +1069,41 @@ DebuggerView.Scripts = { }, /** * Checks whether the script with the specified URL is among the scripts * known to the debugger and shown in the list. * * @param string aUrl * The script URL. + * @return boolean */ contains: function DVS_contains(aUrl) { if (this._scripts.getElementsByAttribute("value", aUrl).length > 0) { return true; } return false; }, /** + * Checks whether the script with the specified label is among the scripts + * known to the debugger and shown in the list. + * + * @param string aLabel + * The script label. + * @return boolean + */ + containsLabel: function DVS_containsLabel(aLabel) { + if (this._scripts.getElementsByAttribute("label", aLabel).length > 0) { + return true; + } + return false; + }, + + /** * Checks whether the script with the specified URL is selected in the list. * * @param string aUrl * The script URL. */ isSelected: function DVS_isSelected(aUrl) { if (this._scripts.selectedItem && this._scripts.selectedItem.value == aUrl) { @@ -1104,40 +1120,40 @@ DebuggerView.Scripts = { */ selectScript: function DVS_selectScript(aUrl) { for (let i = 0; i < this._scripts.itemCount; i++) { if (this._scripts.getItemAtIndex(i).value == aUrl) { this._scripts.selectedIndex = i; break; } } - }, + }, /** * Adds a script to the scripts container. * If the script already exists (was previously added), null is returned. * Otherwise, the newly created element is returned. * - * @param string aUrl - * The script url. + * @param string aLabel + * The simplified script location to be shown. * @param string aScript * The source script. - * @param string aScriptNameText - * Optional, title displayed instead of url. * @return object * The newly created html node representing the added script. */ - addScript: function DVS_addScript(aUrl, aSource, aScriptNameText) { + addScript: function DVS_addScript(aLabel, aScript) { // make sure we don't duplicate anything - if (this.contains(aUrl)) { + if (this.containsLabel(aLabel)) { return null; } - let script = this._scripts.appendItem(aScriptNameText || aUrl, aUrl); - script.setUserData("sourceScript", aSource, null); + let script = this._scripts.appendItem(aLabel, aScript.url); + script.setAttribute("tooltiptext", aScript.url); + script.setUserData("sourceScript", aScript, null); + this._scripts.selectedItem = script; return script; }, /** * Returns the list of URIs for scripts in the page. */ scriptLocations: function DVS_scriptLocations() {
--- a/browser/devtools/debugger/debugger.css +++ b/browser/devtools/debugger/debugger.css @@ -62,16 +62,36 @@ #stack { width: 200px; } #stackframes { overflow: auto; } +.dbg-stackframe { + display: block; +} + +.dbg-stackframe-name { + float: left; +} + +.dbg-stackframe-details { + float: right; +} + +.dbg-stackframe-name:-moz-locale-dir(rtl) { + float: right; +} + +.dbg-stackframe-details:-moz-locale-dir(rtl) { + float: left; +} + /** * Properties elements */ #properties { width: 250px; }
--- a/browser/devtools/debugger/debugger.js +++ b/browser/devtools/debugger/debugger.js @@ -365,20 +365,22 @@ var StackFrames = { /** * Adds the specified stack frame to the list. * * @param Debugger.Frame aFrame * The new frame to add. */ _addFramePanel: function SF_addFramePanel(aFrame) { let depth = aFrame.depth; - let idText = "#" + aFrame.depth + " "; - let nameText = this._frameTitle(aFrame); + let label = SourceScripts._getScriptLabel(aFrame.where.url); - let panel = DebuggerView.Stackframes.addFrame(depth, idText, nameText); + let startText = this._frameTitle(aFrame); + let endText = label + ":" + aFrame.where.line; + + let panel = DebuggerView.Stackframes.addFrame(depth, startText, endText); if (panel) { panel.stackFrame = aFrame; } }, /** * Loads more stack frames from the debugger server cache. @@ -392,17 +394,17 @@ var StackFrames = { * Create a textual representation for the stack frame specified, for * displaying in the stack frame list. * * @param Debugger.Frame aFrame * The stack frame to label. */ _frameTitle: function SF_frameTitle(aFrame) { if (aFrame.type == "call") { - return aFrame["calleeName"] ? aFrame["calleeName"] + "()" : "(anonymous)"; + return aFrame["calleeName"] ? aFrame["calleeName"] : "(anonymous)"; } return "(" + aFrame.type + ")"; } }; StackFrames.onPaused = StackFrames.onPaused.bind(StackFrames); StackFrames.onFrames = StackFrames.onFrames.bind(StackFrames); @@ -411,31 +413,33 @@ StackFrames.onClick = StackFrames.onClic /** * Keeps the source script list up-to-date, using the thread client's * source script cache. */ var SourceScripts = { pageSize: 25, activeThread: null, + _labelsCache: null, /** * Watch a given thread client. * @param object aThreadClient * The thread client. * @param function aCallback * The next function in the initialization sequence. */ connect: function SS_connect(aThreadClient, aCallback) { DebuggerView.Scripts.addChangeListener(this.onChange); this.activeThread = aThreadClient; aThreadClient.addListener("paused", this.onPaused); aThreadClient.addListener("scriptsadded", this.onScripts); aThreadClient.addListener("scriptscleared", this.onScriptsCleared); + this.clearLabelsCache(); this.onScriptsCleared(); aCallback && aCallback(); }, /** * Disconnect from the client. */ disconnect: function TS_disconnect() { @@ -504,36 +508,96 @@ var SourceScripts = { if (/javascript/.test(aContentType)) { window.editor.setMode(SourceEditor.MODES.JAVASCRIPT); } else { window.editor.setMode(SourceEditor.MODES.HTML); } return; } - let url = aUrl; - // Trim the query part. - let q = url.indexOf('?'); - if (q > -1) { - url = url.slice(0, q); - } - - if (url.slice(-3) == ".js") { + if (this._trimUrlQuery(aUrl).slice(-3) == ".js") { window.editor.setMode(SourceEditor.MODES.JAVASCRIPT); } else { window.editor.setMode(SourceEditor.MODES.HTML); } }, /** + * Trims the query part of a url string, if necessary. + * + * @param string aUrl + * The script url. + * @return string + */ + _trimUrlQuery: function SS_trimUrlQuery(aUrl) { + let q = aUrl.indexOf('?'); + if (q > -1) { + return aUrl.slice(0, q); + } + return aUrl; + }, + + /** + * Gets a unique, simplified label from a script url. + * ex: a). ici://some.address.com/random/subrandom/ + * b). ni://another.address.org/random/subrandom/page.html + * c). san://interesting.address.gro/random/script.js + * d). si://interesting.address.moc/random/another/script.js + * => + * a). subrandom/ + * b). page.html + * c). script.js + * d). another/script.js + * + * @param string aUrl + * The script url. + * @param string aHref + * The content location href to be used. If unspecified, it will + * defalult to debugged panrent window location. + * @return string + * The simplified label. + */ + _getScriptLabel: function SS_getScriptLabel(aUrl, aHref) { + let url = this._trimUrlQuery(aUrl); + + if (this._labelsCache[url]) { + return this._labelsCache[url]; + } + + let href = aHref || window.parent.content.location.href; + let pathElements = url.split("/"); + let label = pathElements.pop() || (pathElements.pop() + "/"); + + // if the label as a leaf name is alreay present in the scripts list + if (DebuggerView.Scripts.containsLabel(label)) { + label = url.replace(href.substring(0, href.lastIndexOf("/") + 1), ""); + + // if the path/to/script is exactly the same, we're in different domains + if (DebuggerView.Scripts.containsLabel(label)) { + label = url; + } + } + + return this._labelsCache[url] = label; + }, + + /** + * Clears the labels cache, populated by SS_getScriptLabel(). + * This should be done every time the content location changes. + */ + clearLabelsCache: function SS_clearLabelsCache() { + this._labelsCache = {}; + }, + + /** * Add the specified script to the list and display it in the editor if the * editor is empty. */ _addScript: function SS_addScript(aScript) { - DebuggerView.Scripts.addScript(aScript.url, aScript); + DebuggerView.Scripts.addScript(this._getScriptLabel(aScript.url), aScript); if (window.editor.getCharCount() == 0) { this._showScript(aScript); } }, /** * Load the editor with the script text if available, otherwise fire an event
--- a/browser/devtools/debugger/test/browser_dbg_clean-exit.js +++ b/browser/devtools/debugger/test/browser_dbg_clean-exit.js @@ -5,19 +5,17 @@ // Test that closing a tab with the debugger in a paused state exits cleanly. var gPane = null; var gTab = null; var gDebuggee = null; var gDebugger = null; -const DEBUGGER_TAB_URL = "http://example.com/browser/browser/devtools/" + - "debugger/test/" + - "browser_dbg_debuggerstatement.html"; +const DEBUGGER_TAB_URL = EXAMPLE_URL + "browser_dbg_debuggerstatement.html"; function test() { debug_tab_pane(DEBUGGER_TAB_URL, function(aTab, aDebuggee, aPane) { gTab = aTab; gDebuggee = aDebuggee; gPane = aPane; gDebugger = gPane.debuggerWindow;
--- a/browser/devtools/debugger/test/browser_dbg_debuggerstatement.js +++ b/browser/devtools/debugger/test/browser_dbg_debuggerstatement.js @@ -3,19 +3,17 @@ * Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ // Tests the behavior of the debugger statement. var gClient = null; var gTab = null; -const DEBUGGER_TAB_URL = "http://example.com/browser/browser/devtools/" + - "debugger/test/" + - "browser_dbg_debuggerstatement.html"; +const DEBUGGER_TAB_URL = EXAMPLE_URL + "browser_dbg_debuggerstatement.html"; function test() { let transport = DebuggerServer.connectPipe(); gClient = new DebuggerClient(transport); gClient.connect(function(aType, aTraits) { gTab = addTab(DEBUGGER_TAB_URL, function() { attach_tab_actor_for_url(gClient, DEBUGGER_TAB_URL, function(actor, response) {
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-01.js +++ b/browser/devtools/debugger/test/browser_dbg_propertyview-01.js @@ -78,12 +78,65 @@ function testSimpleCall() { }}, 0); }); gDebuggee.simpleCall(); } function resumeAndFinish() { gDebugger.StackFrames.activeThread.resume(function() { - removeTab(gTab); - finish(); + let vs = gDebugger.DebuggerView.Scripts; + let ss = gDebugger.SourceScripts; + + is(ss._trimUrlQuery("a/b/c.d?test=1&random=4"), "a/b/c.d", + "Trimming the url query isn't done properly."); + + let urls = [ + { href: "ici://some.address.com/random/", leaf: "subrandom/" }, + { href: "ni://another.address.org/random/subrandom/", leaf: "page.html" }, + { href: "san://interesting.address.gro/random/", leaf: "script.js" }, + { href: "si://interesting.address.moc/random/", leaf: "script.js" }, + { href: "si://interesting.address.moc/random/", leaf: "x/script.js" }, + { href: "si://interesting.address.moc/random/", leaf: "x/y/script.js?a=1" }, + { href: "si://interesting.address.moc/random/x/", leaf: "y/script.js?a=1&b=2" }, + { href: "si://interesting.address.moc/random/x/y/", leaf: "script.js?a=1&b=2&c=3" } + ]; + + vs._scripts.removeEventListener("select", vs._onScriptsChange, false); + + urls.forEach(function(url) { + executeSoon(function() { + let loc = url.href + url.leaf; + vs.addScript(ss._getScriptLabel(loc, url.href), { url: loc }); + }); + }); + + executeSoon(function() { + for (let i = 0; i < vs._scripts.itemCount; i++) { + let lab = vs._scripts.getItemAtIndex(i).getAttribute("label"); + let loc = urls[i].href + urls[i].leaf; + + info("label: " + i + " " + lab); + ok(vs.contains(loc), "Script url is incorrect: " + loc); + } + + ok(gDebugger.DebuggerView.Scripts.containsLabel("subrandom/"), + "Script (0) label is incorrect."); + ok(gDebugger.DebuggerView.Scripts.containsLabel("page.html"), + "Script (1) label is incorrect."); + ok(gDebugger.DebuggerView.Scripts.containsLabel("script.js"), + "Script (2) label is incorrect."); + ok(gDebugger.DebuggerView.Scripts.containsLabel("si://interesting.address.moc/random/script.js"), + "Script (3) label is incorrect."); + ok(gDebugger.DebuggerView.Scripts.containsLabel("x/script.js"), + "Script (4) label is incorrect."); + ok(gDebugger.DebuggerView.Scripts.containsLabel("x/y/script.js"), + "Script (5) label is incorrect."); + + is(vs._scripts.itemCount, 6, + "Got too many script items in the list!"); + + + removeTab(gTab); + finish(); + }); }); }
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-07.js +++ b/browser/devtools/debugger/test/browser_dbg_propertyview-07.js @@ -1,18 +1,17 @@ /* vim:set ts=2 sw=2 sts=2 et: */ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ /** * Make sure that the property view displays function parameters. */ -const TAB_URL = "http://example.com/browser/browser/devtools/debugger/test/" + - "browser_dbg_frame-parameters.html"; +const TAB_URL = EXAMPLE_URL + "browser_dbg_frame-parameters.html"; var gPane = null; var gTab = null; var gDebuggee = null; var gDebugger = null; function test() {
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-08.js +++ b/browser/devtools/debugger/test/browser_dbg_propertyview-08.js @@ -1,18 +1,17 @@ /* vim:set ts=2 sw=2 sts=2 et: */ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ /** * Make sure that the property view displays the properties of objects. */ -const TAB_URL = "http://example.com/browser/browser/devtools/debugger/test/" + - "browser_dbg_frame-parameters.html"; +const TAB_URL = EXAMPLE_URL + "browser_dbg_frame-parameters.html"; var gPane = null; var gTab = null; var gDebuggee = null; var gDebugger = null; function test() {
--- a/browser/devtools/debugger/test/browser_dbg_script-switching.js +++ b/browser/devtools/debugger/test/browser_dbg_script-switching.js @@ -1,18 +1,18 @@ /* vim:set ts=2 sw=2 sts=2 et: */ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ /** * Make sure that switching the displayed script in the UI works as advertised. */ -const TAB_URL = "http://example.com/browser/browser/devtools/debugger/" + - "test/browser_dbg_script-switching.html"; +const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html"; + let tempScope = {}; Cu.import("resource:///modules/source-editor.jsm", tempScope); let SourceEditor = tempScope.SourceEditor; var gPane = null; var gTab = null; var gDebuggee = null; var gDebugger = null; @@ -35,16 +35,34 @@ function testScriptsDisplay() { Services.tm.currentThread.dispatch({ run: function() { gScripts = gDebugger.DebuggerView.Scripts._scripts; is(gDebugger.StackFrames.activeThread.state, "paused", "Should only be getting stack frames while paused."); is(gScripts.itemCount, 2, "Found the expected number of scripts."); + for (let i = 0; i < gScripts.itemCount; i++) { + info("label: " + i + " " + gScripts.getItemAtIndex(i).getAttribute("label")); + } + + let label1 = "test-script-switching-01.js"; + let label2 = "test-script-switching-02.js"; + + ok(gDebugger.DebuggerView.Scripts.contains(EXAMPLE_URL + + label1), "First script url is incorrect."); + ok(gDebugger.DebuggerView.Scripts.contains(EXAMPLE_URL + + label2), "Second script url is incorrect."); + + ok(gDebugger.DebuggerView.Scripts.containsLabel( + label1), "First script label is incorrect."); + ok(gDebugger.DebuggerView.Scripts.containsLabel( + label2), "Second script label is incorrect."); + + ok(gDebugger.editor.getText().search(/debugger/) != -1, "The correct script was loaded initially."); gDebugger.editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED, function onChange() { gDebugger.editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED, onChange); testSwitchPaused();
--- a/browser/devtools/debugger/test/browser_dbg_select-line.js +++ b/browser/devtools/debugger/test/browser_dbg_select-line.js @@ -1,18 +1,18 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ /** * Make sure that selecting a stack frame loads the right script in the editor * pane and highlights the proper line. */ -const TAB_URL = "http://example.com/browser/browser/devtools/debugger/" + - "test/browser_dbg_script-switching.html"; +const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html"; + let tempScope = {}; Cu.import("resource:///modules/source-editor.jsm", tempScope); let SourceEditor = tempScope.SourceEditor; var gPane = null; var gTab = null; var gDebuggee = null; var gDebugger = null;
--- a/browser/devtools/debugger/test/browser_dbg_update-editor-mode.js +++ b/browser/devtools/debugger/test/browser_dbg_update-editor-mode.js @@ -1,18 +1,18 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ /** * Make sure that updating the editor mode sets the right highlighting engine, * and script URIs with extra query parameters also get the right engine. */ -const TAB_URL = "http://example.com/browser/browser/devtools/debugger/" + - "test/browser_dbg_update-editor-mode.html"; +const TAB_URL = EXAMPLE_URL + "browser_dbg_update-editor-mode.html"; + let tempScope = {}; Cu.import("resource:///modules/source-editor.jsm", tempScope); let SourceEditor = tempScope.SourceEditor; var gPane = null; var gTab = null; var gDebuggee = null; var gDebugger = null;
--- a/browser/devtools/debugger/test/head.js +++ b/browser/devtools/debugger/test/head.js @@ -9,21 +9,21 @@ let tempScope = {}; Cu.import("resource:///modules/devtools/dbg-server.jsm", tempScope); Cu.import("resource:///modules/devtools/dbg-client.jsm", tempScope); Cu.import("resource:///modules/Services.jsm", tempScope); let DebuggerServer = tempScope.DebuggerServer; let DebuggerTransport = tempScope.DebuggerTransport; let DebuggerClient = tempScope.DebuggerClient; let Services = tempScope.Services; -const TAB1_URL = "http://example.com/browser/browser/devtools/debugger/test/browser_dbg_tab1.html"; +const EXAMPLE_URL = "http://example.com/browser/browser/devtools/debugger/test/"; -const TAB2_URL = "http://example.com/browser/browser/devtools/debugger/test/browser_dbg_tab2.html"; - -const STACK_URL = "http://example.com/browser/browser/devtools/debugger/test/browser_dbg_stack.html"; +const TAB1_URL = EXAMPLE_URL + "browser_dbg_tab1.html"; +const TAB2_URL = EXAMPLE_URL + "browser_dbg_tab2.html"; +const STACK_URL = EXAMPLE_URL + "browser_dbg_stack.html"; if (!DebuggerServer.initialized) { DebuggerServer.init(); DebuggerServer.addBrowserActors(); } waitForExplicitFinish();
--- a/browser/devtools/highlighter/inspector.html +++ b/browser/devtools/highlighter/inspector.html @@ -1,14 +1,14 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> - <link rel="stylesheet" href="chrome://browser/skin/inspector.css" type="text/css"/> + <link rel="stylesheet" href="chrome://browser/skin/devtools/htmlpanel.css" type="text/css"/> </head> <body role="application"> <div id="attribute-editor"> <input id="attribute-editor-input" /> </div> </body> </html>
--- a/browser/devtools/highlighter/inspector.jsm +++ b/browser/devtools/highlighter/inspector.jsm @@ -865,17 +865,18 @@ InspectorUI.prototype = { * Delete the selected node. Called via the Inspector:DeleteNode command. */ deleteNode: function IUI_deleteNode() { let selection = this.selection; let parent = this.selection.parentNode; // remove the node from the treepanel - this.treePanel.deleteChildBox(selection); + if (this.treePanel.isOpen()) + this.treePanel.deleteChildBox(selection); // remove the node from content parent.removeChild(selection); this.breadcrumbs.invalidateHierarchy(); // select the parent node in the highlighter, treepanel, breadcrumbs this.inspectNode(parent); }, @@ -1229,16 +1230,17 @@ InspectorUI.prototype = { btn.setAttribute("type", "radio"); btn.setAttribute("group", "sidebar-tools"); this.sidebarToolbar.appendChild(btn); // create tool iframe let iframe = this.chromeDoc.createElement("iframe"); iframe.id = "devtools-sidebar-iframe-" + aRegObj.id; iframe.setAttribute("flex", "1"); + iframe.setAttribute("tooltip", "aHTMLTooltip"); this.sidebarDeck.appendChild(iframe); // wire up button to show the iframe this.bindToolEvent(btn, "click", function showIframe() { this.toolShow(aRegObj); }.bind(this)); },
--- a/browser/devtools/styleinspector/CssLogic.jsm +++ b/browser/devtools/styleinspector/CssLogic.jsm @@ -72,20 +72,28 @@ * - why their expectations may not have been fulfilled * - how browsers process CSS * @constructor */ const Cc = Components.classes; const Ci = Components.interfaces; const Cu = Components.utils; +const RX_UNIVERSAL_SELECTOR = /\s*\*\s*/g; +const RX_NOT = /:not\((.*?)\)/g; +const RX_PSEUDO_CLASS_OR_ELT = /(:[\w-]+\().*?\)/g; +const RX_CONNECTORS = /\s*[\s>+~]\s*/g; +const RX_ID = /\s*#\w+\s*/g; +const RX_CLASS_OR_ATTRIBUTE = /\s*(?:\.\w+|\[.+?\])\s*/g; +const RX_PSEUDO = /\s*:?:([\w-]+)(\(?\)?)\s*/g; + Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -var EXPORTED_SYMBOLS = ["CssLogic"]; +var EXPORTED_SYMBOLS = ["CssLogic", "CssSelector"]; function CssLogic() { // The cache of examined CSS properties. _propertyInfos: {}; } /** @@ -1427,61 +1435,107 @@ CssSelector.prototype = { * stylesheet. */ get ruleLine() { return this._cssRule.line; }, /** + * Retrieve the pseudo-elements that we support. This list should match the + * elements specified in layout/style/nsCSSPseudoElementList.h + */ + get pseudoElements() + { + if (!CssSelector._pseudoElements) { + let pseudos = CssSelector._pseudoElements = new Set(); + pseudos.add("after"); + pseudos.add("before"); + pseudos.add("first-letter"); + pseudos.add("first-line"); + pseudos.add("selection"); + pseudos.add("-moz-focus-inner"); + pseudos.add("-moz-focus-outer"); + pseudos.add("-moz-list-bullet"); + pseudos.add("-moz-list-number"); + pseudos.add("-moz-math-anonymous"); + pseudos.add("-moz-math-stretchy"); + pseudos.add("-moz-progress-bar"); + pseudos.add("-moz-selection"); + } + return CssSelector._pseudoElements; + }, + + /** * Retrieve specificity information for the current selector. * * @see http://www.w3.org/TR/css3-selectors/#specificity * @see http://www.w3.org/TR/CSS2/selector.html * * @return {object} an object holding specificity information for the current * selector. */ get specificity() { if (this._specificity) { return this._specificity; } - let specificity = {}; + let specificity = { + ids: 0, + classes: 0, + tags: 0 + }; - specificity.ids = 0; - specificity.classes = 0; - specificity.tags = 0; + let text = this.text; - // Split on CSS combinators (section 5.2). - // TODO: We need to properly parse the selector. See bug 592743. if (!this.elementStyle) { - this.text.split(/[ >+]/).forEach(function(aSimple) { - // The regex leaves empty nodes combinators like ' > ' - if (!aSimple) { - return; - } - // See http://www.w3.org/TR/css3-selectors/#specificity - // We can count the IDs by counting the '#' marks. - specificity.ids += (aSimple.match(/#/g) || []).length; - // Similar with class names and attribute matchers - specificity.classes += (aSimple.match(/\./g) || []).length; - specificity.classes += (aSimple.match(/\[/g) || []).length; - // Pseudo elements count as elements. - specificity.tags += (aSimple.match(/:/g) || []).length; - // If we have anything of substance before we get into ids/classes/etc - // then it must be a tag if it isn't '*'. - let tag = aSimple.split(/[#.[:]/)[0]; - if (tag && tag != "*") { + // Remove universal selectors as they are not relevant as far as specificity + // is concerned. + text = text.replace(RX_UNIVERSAL_SELECTOR, ""); + + // not() is ignored but any selectors contained by it are counted. Let's + // remove the not() and keep the contents. + text = text.replace(RX_NOT, " $1"); + + // Simplify remaining psuedo classes & elements. + text = text.replace(RX_PSEUDO_CLASS_OR_ELT, " $1)"); + + // Replace connectors with spaces + text = text.replace(RX_CONNECTORS, " "); + + text.split(/\s/).forEach(function(aSimple) { + // Count IDs. + aSimple = aSimple.replace(RX_ID, function() { + specificity.ids++; + return ""; + }); + + // Count class names and attribute matchers. + aSimple = aSimple.replace(RX_CLASS_OR_ATTRIBUTE, function() { + specificity.classes++; + return ""; + }); + + aSimple = aSimple.replace(RX_PSEUDO, function(aDummy, aPseudoName) { + if (this.pseudoElements.has(aPseudoName)) { + // Pseudo elements count as tags. + specificity.tags++; + } else { + // Pseudo classes count as classes. + specificity.classes++; + } + return ""; + }.bind(this)); + + if (aSimple) { specificity.tags++; } }, this); } - this._specificity = specificity; return this._specificity; }, toString: function CssSelector_toString() { return this.text;
--- a/browser/devtools/styleinspector/CssRuleView.jsm +++ b/browser/devtools/styleinspector/CssRuleView.jsm @@ -98,16 +98,23 @@ var EXPORTED_SYMBOLS = ["CssRuleView", * set of disabled properties. * * @constructor */ function ElementStyle(aElement, aStore) { this.element = aElement; this.store = aStore || {}; + + // We don't want to overwrite this.store.userProperties so we only create it + // if it doesn't already exist. + if (!("userProperties" in this.store)) { + this.store.userProperties = new UserProperties(); + } + if (this.store.disabled) { this.store.disabled = aStore.disabled; } else { this.store.disabled = WeakMap(); } let doc = aElement.ownerDocument; @@ -417,31 +424,33 @@ Rule.prototype = { /** * Reapply all the properties in this rule, and update their * computed styles. Store disabled properties in the element * style's store. Will re-mark overridden properties. */ applyProperties: function Rule_applyProperties() { let disabledProps = []; + let store = this.elementStyle.store; for each (let prop in this.textProps) { if (!prop.enabled) { disabledProps.push({ name: prop.name, value: prop.value, priority: prop.priority }); continue; } + store.userProperties.setProperty(this.style, prop.name, prop.value); + this.style.setProperty(prop.name, prop.value, prop.priority); - // Refresh the property's value from the style, to reflect + // Refresh the property's priority from the style, to reflect // any changes made during parsing. - prop.value = this.style.getPropertyValue(prop.name); prop.priority = this.style.getPropertyPriority(prop.name); prop.updateComputed(); } this.elementStyle._changed(); // Store disabled properties in the disabled store. let disabled = this.elementStyle.store.disabled; disabled.set(this.style, disabledProps); @@ -514,41 +523,42 @@ Rule.prototype = { /** * Get the list of TextProperties from the style. Needs * to parse the style's cssText. */ _getTextProperties: function Rule_getTextProperties() { this.textProps = []; + let store = this.elementStyle.store; let lines = this.style.cssText.match(CSS_LINE_RE); for each (let line in lines) { let matches = CSS_PROP_RE.exec(line); if(!matches || !matches[2]) continue; let name = matches[1]; if (this.inherited && !this.elementStyle.domUtils.isInheritedProperty(name)) { continue; } - - let prop = new TextProperty(this, name, matches[2], matches[3] || ""); + let value = store.userProperties.getProperty(this.style, name, matches[2]); + let prop = new TextProperty(this, name, value, matches[3] || ""); this.textProps.push(prop); } // Include properties from the disabled property store, if any. let disabledProps = this.elementStyle.store.disabled.get(this.style); if (!disabledProps) { return; } for each (let prop in disabledProps) { - let textProp = new TextProperty(this, prop.name, - prop.value, prop.priority); + let value = store.userProperties.getProperty(this.style, prop.name, prop.value); + let textProp = new TextProperty(this, prop.name, value, prop.priority); textProp.enabled = false; this.textProps.push(textProp); } }, }; /** * A single property in a rule's cssText. @@ -988,16 +998,22 @@ TextPropertyEditor.prototype = { // 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 }; appendText(this.element, ";"); + this.warning = createChild(this.element, "div", { + hidden: "", + class: "ruleview-warning", + title: CssLogic.l10n("rule.warning.title"), + }); + // Holds the viewers for the computed properties. // will be populated in |_updateComputed|. this.computed = createChild(this.element, "ul", { class: "ruleview-computedlist", }); }, /** @@ -1023,16 +1039,17 @@ TextPropertyEditor.prototype = { // Combine the property's value and priority into one string for // the value. let val = this.prop.value; if (this.prop.priority) { val += " !" + this.prop.priority; } this.valueSpan.textContent = val; + this.warning.hidden = this._validate(); // Populate the computed styles. this._updateComputed(); }, _onStartEditing: function TextPropertyEditor_onStartEditing() { this.element.classList.remove("ruleview-overridden"); @@ -1158,16 +1175,33 @@ TextPropertyEditor.prototype = { let val = this._parseValue(aValue); this.prop.setValue(val.value, val.priority); this.committed.value = this.prop.value; this.committed.priority = this.prop.priority; } else { this.prop.setValue(this.committed.value, this.committed.priority); } }, + + /** + * Validate this property. + * + * @returns {Boolean} + * True if the property value is valid, false otherwise. + */ + _validate: function TextPropertyEditor_validate() + { + let name = this.prop.name; + let value = this.prop.value; + let style = this.doc.createElementNS(HTML_NS, "div").style; + + style.setProperty(name, value, null); + + return !!style.getPropertyValue(name); + }, }; /** * Mark a span editable. |editableField| will listen for the span to * be focused and create an InlineEditor to handle text input. * Changes will be committed when the InlineEditor's input is blurred * or dropped when the user presses escape. * @@ -1377,16 +1411,71 @@ InplaceEditor.prototype = { // Call the user's change handler if available. if (this.change) { this.change(this.input.value.trim()); } } }; /** + * Store of CSSStyleDeclarations mapped to properties that have been changed by + * the user. + */ +function UserProperties() +{ + this.weakMap = new WeakMap(); +} + +UserProperties.prototype = { + /** + * Get a named property for a given CSSStyleDeclaration. + * + * @param {CSSStyleDeclaration} aStyle + * The CSSStyleDeclaration against which the property is mapped. + * @param {String} aName + * The name of the property to get. + * @param {Boolean} aDefault + * Indicates whether the property value is one entered by a user. + * @returns {String} + * The property value if it has previously been set by the user, null + * otherwise. + */ + getProperty: function UP_getProperty(aStyle, aName, aDefault) { + let entry = this.weakMap.get(aStyle, null); + + if (entry && aName in entry) { + return entry[aName]; + } + return typeof aDefault != "undefined" ? aDefault : null; + + }, + + /** + * Set a named property for a given CSSStyleDeclaration. + * + * @param {CSSStyleDeclaration} aStyle + * The CSSStyleDeclaration against which the property is to be mapped. + * @param {String} aName + * The name of the property to set. + * @param {String} aValue + * The value of the property to set. + */ + setProperty: function UP_setProperty(aStyle, aName, aValue) { + let entry = this.weakMap.get(aStyle, null); + if (entry) { + entry[aName] = aValue; + } else { + let props = {}; + props[aName] = aValue; + this.weakMap.set(aStyle, props); + } + }, +}; + +/** * Helper functions */ /** * Create a child element with a set of attributes. * * @param {Element} aParent * The parent node.
--- a/browser/devtools/styleinspector/StyleInspector.jsm +++ b/browser/devtools/styleinspector/StyleInspector.jsm @@ -77,17 +77,17 @@ StyleInspector.prototype = { // Were we invoked from the Highlighter? if (this.IUI) { this.openDocked = true; let isOpen = this.isOpen.bind(this); this.registrationObject = { id: "styleinspector", label: this.l10n("style.highlighter.button.label2"), - tooltiptext: this.l10n("style.highlighter.button.tooltip"), + tooltiptext: this.l10n("style.highlighter.button.tooltip2"), accesskey: this.l10n("style.highlighter.accesskey2"), context: this, get isOpen() isOpen(), onSelect: this.selectNode, onChanged: this.updateNode, show: this.open, hide: this.close, dim: this.dimTool,
--- a/browser/devtools/styleinspector/test/Makefile.in +++ b/browser/devtools/styleinspector/test/Makefile.in @@ -50,21 +50,23 @@ include $(topsrcdir)/config/rules.mk browser_bug683672.js \ browser_styleinspector_bug_672746_default_styles.js \ browser_styleinspector_bug_672744_search_filter.js \ browser_bug589375_keybindings.js \ browser_styleinspector_bug_689759_no_results_placeholder.js \ browser_bug_692400_element_style.js \ browser_csslogic_inherited.js \ browser_ruleview_editor.js \ + browser_ruleview_editor_changedvalues.js \ browser_ruleview_inherit.js \ browser_ruleview_manipulation.js \ browser_ruleview_override.js \ browser_ruleview_ui.js \ browser_bug705707_is_content_stylesheet.js \ + browser_bug_592743_specificity.js \ head.js \ $(NULL) _BROWSER_TEST_PAGES = \ browser_bug683672.html \ browser_bug705707_is_content_stylesheet.html \ browser_bug705707_is_content_stylesheet_imported.css \ browser_bug705707_is_content_stylesheet_imported2.css \
new file mode 100644 --- /dev/null +++ b/browser/devtools/styleinspector/test/browser_bug_592743_specificity.js @@ -0,0 +1,49 @@ +/* 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/ */ + +// Tests that CSS specificity is properly calculated. + +let tempScope = {}; +Cu.import("resource:///modules/devtools/CssLogic.jsm", tempScope); +let CssLogic = tempScope.CssLogic; +let CssSelector = tempScope.CssSelector; + +function test() +{ + let tests = [ + {text: "*", expected: "000"}, + {text: "LI", expected: "001"}, + {text: "UL LI", expected: "002"}, + {text: "UL OL+LI", expected: "003"}, + {text: "H1 + *[REL=up]", expected: "011"}, + {text: "UL OL LI.red", expected: "013"}, + {text: "LI.red.level", expected: "021"}, + {text: ".red .level", expected: "020"}, + {text: "#x34y", expected: "100"}, + {text: "#s12:not(FOO)", expected: "101"}, + {text: "body#home div#warning p.message", expected: "213"}, + {text: "* body#home div#warning p.message", expected: "213"}, + {text: "#footer *:not(nav) li", expected: "102"}, + {text: "bar:nth-child(1n+0)", expected: "011"}, + {text: "li::-moz-list-number", expected: "002"}, + {text: "a:hover", expected: "011"}, + ]; + + tests.forEach(function(aTest) { + let selector = new CssSelector(null, aTest.text); + let specificity = selector.specificity; + + let result = "" + specificity.ids + specificity.classes + specificity.tags; + is(result, aTest.expected, "selector \"" + aTest.text + + "\" produces expected result"); + }); + + finishUp(); +} + +function finishUp() +{ + CssLogic = CssSelector = null; + finish(); +}
new file mode 100644 --- /dev/null +++ b/browser/devtools/styleinspector/test/browser_ruleview_editor_changedvalues.js @@ -0,0 +1,190 @@ +/* vim: set ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +let tempScope = {}; +Cu.import("resource:///modules/devtools/CssRuleView.jsm", tempScope); +let CssRuleView = tempScope.CssRuleView; +let _ElementStyle = tempScope._ElementStyle; +let _editableField = tempScope._editableField; + +let doc; +let ruleDialog; +let ruleView; + +function waitForEditorFocus(aParent, aCallback) +{ + aParent.addEventListener("focus", function onFocus(evt) { + if (evt.target.inplaceEditor) { + aParent.removeEventListener("focus", onFocus, true); + let editor = evt.target.inplaceEditor; + executeSoon(function() { + aCallback(editor); + }); + } + }, true); +} + +function waitForEditorBlur(aEditor, aCallback) +{ + let input = aEditor.input; + input.addEventListener("blur", function onBlur() { + input.removeEventListener("blur", onBlur, false); + executeSoon(function() { + aCallback(); + }); + }, false); +} + +var gRuleViewChanged = false; +function ruleViewChanged() +{ + gRuleViewChanged = true; +} + +function expectChange() +{ + ok(gRuleViewChanged, "Rule view should have fired a change event."); + gRuleViewChanged = false; +} + +function startTest() +{ + let style = '' + + '#testid {' + + ' background-color: blue;' + + '} ' + + '.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", + "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); + ruleView.highlight(testElement); + waitForFocus(testCancelNew, ruleDialog); + }, true); +} + +function testCancelNew() +{ + // Start at the beginning: start to add a rule to the element's style + // declaration, but leave it empty. + + let elementRuleEditor = ruleView.element.children[0]._ruleEditor; + waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) { + is(elementRuleEditor.newPropSpan.inplaceEditor, aEditor, "Next focused editor should be the new property editor."); + let input = aEditor.input; + waitForEditorBlur(aEditor, function () { + ok(!gRuleViewChanged, "Shouldn't get a change event after a cancel."); + is(elementRuleEditor.rule.textProps.length, 0, "Should have canceled creating a new text property."); + ok(!elementRuleEditor.propertyList.hasChildNodes(), "Should not have any properties."); + testCreateNew(); + }); + aEditor.input.blur(); + }); + + EventUtils.synthesizeMouse(elementRuleEditor.closeBrace, 1, 1, + { }, + ruleDialog); +} + +function testCreateNew() +{ + // Create a new property. + let elementRuleEditor = ruleView.element.children[0]._ruleEditor; + waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) { + is(elementRuleEditor.newPropSpan.inplaceEditor, aEditor, "Next focused editor should be the new property editor."); + let input = aEditor.input; + input.value = "background-color"; + + waitForEditorFocus(elementRuleEditor.element, function onNewValue(aEditor) { + expectChange(); + is(elementRuleEditor.rule.textProps.length, 1, "Should have created a new text property."); + is(elementRuleEditor.propertyList.children.length, 1, "Should have created a property editor."); + let textProp = elementRuleEditor.rule.textProps[0]; + is(aEditor, textProp.editor.valueSpan.inplaceEditor, "Should be editing the value span now."); + + aEditor.input.value = "#XYZ"; + waitForEditorBlur(aEditor, function() { + expectChange(); + is(textProp.value, "#XYZ", "Text prop should have been changed."); + is(textProp.editor._validate(), false, "#XYZ should not be a valid entry"); + testEditProperty(); + }); + aEditor.input.blur(); + }); + EventUtils.synthesizeKey("VK_RETURN", {}, ruleDialog); + }); + + EventUtils.synthesizeMouse(elementRuleEditor.closeBrace, 1, 1, + { }, + ruleDialog); +} + +function testEditProperty() +{ + let idRuleEditor = ruleView.element.children[1]._ruleEditor; + let propEditor = idRuleEditor.rule.textProps[0].editor; + waitForEditorFocus(propEditor.element, function onNewElement(aEditor) { + is(propEditor.nameSpan.inplaceEditor, aEditor, "Next focused editor should be the name editor."); + let input = aEditor.input; + waitForEditorFocus(propEditor.element, function onNewName(aEditor) { + expectChange(); + input = aEditor.input; + is(propEditor.valueSpan.inplaceEditor, aEditor, "Focus should have moved to the value."); + + waitForEditorBlur(aEditor, function() { + expectChange(); + let value = idRuleEditor.rule.style.getPropertyValue("border-color"); + is(value, "red", "border-color should have been set."); + is(propEditor._validate(), true, "red should be a valid entry"); + finishTest(); + }); + + for each (let ch in "red;") { + EventUtils.sendChar(ch, ruleDialog); + } + }); + for each (let ch in "border-color:") { + EventUtils.sendChar(ch, ruleDialog); + } + }); + + EventUtils.synthesizeMouse(propEditor.nameSpan, 1, 1, + { }, + ruleDialog);} + +function finishTest() +{ + ruleView.element.removeEventListener("CssRuleViewChanged", ruleViewChanged, false); + ruleView.clear(); + ruleDialog.close(); + ruleDialog = ruleView = null; + doc = null; + gBrowser.removeCurrentTab(); + finish(); +} + +function test() +{ + waitForExplicitFinish(); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.selectedBrowser.addEventListener("load", function changedValues_load(evt) { + gBrowser.selectedBrowser.removeEventListener(evt.type, changedValues_load, true); + doc = content.document; + waitForFocus(startTest, content); + }, true); + + content.location = "data:text/html,test rule view user changes"; +}
--- a/browser/locales/en-US/chrome/browser/devtools/gclicommands.properties +++ b/browser/locales/en-US/chrome/browser/devtools/gclicommands.properties @@ -89,27 +89,27 @@ tiltTranslateManual=Incrementally transl # LOCALIZATION NOTE (tiltTranslateXDesc) A very short string to describe the # 'x' parameter to the 'tilt translate' command, which is displayed in a dialog # when the user is using this command. tiltTranslateXDesc=X (pixels) # LOCALIZATION NOTE (tiltTranslateXManual) A fuller description of the 'x' # parameter to the 'translate' command, displayed when the user asks for help # on what it does. -tiltTranslateXManual=The ammount in pixels to translate the webpage mesh on the X axis +tiltTranslateXManual=The amount in pixels to translate the webpage mesh on the X axis # LOCALIZATION NOTE (tiltTranslateYDesc) A very short string to describe the # 'y' parameter to the 'tilt translate' command, which is displayed in a dialog # when the user is using this command. tiltTranslateYDesc=Y (pixels) # LOCALIZATION NOTE (tiltTranslateYManual) A fuller description of the 'y' # parameter to the 'translate' command, displayed when the user asks for help # on what it does. -tiltTranslateYManual=The ammount in pixels to translate the webpage mesh on the Y axis +tiltTranslateYManual=The amount in pixels to translate the webpage mesh on the Y axis # LOCALIZATION NOTE (tiltRotateDesc) A very short description of the 'tilt rotate' # command. See tiltRotateManual for a fuller description of what it does. This # string is designed to be shown in a menu alongside the command name, which # is why it should be as short as possible. tiltRotateDesc=Spin the webpage mesh # LOCALIZATION NOTE (tiltRotateManual) A fuller description of the 'tilt rotate' @@ -119,37 +119,37 @@ tiltRotateManual=Incrementally rotate th # LOCALIZATION NOTE (tiltRotateXDesc) A very short string to describe the # 'x' parameter to the 'tilt rotate' command, which is displayed in a dialog # when the user is using this command. tiltRotateXDesc=X (degrees) # LOCALIZATION NOTE (tiltRotateXManual) A fuller description of the 'x' # parameter to the 'rotate' command, displayed when the user asks for help # on what it does. -tiltRotateXManual=The ammount in degrees to rotate the webpage mesh along the X axis +tiltRotateXManual=The amount in degrees to rotate the webpage mesh along the X axis # LOCALIZATION NOTE (tiltRotateYDesc) A very short string to describe the # 'y' parameter to the 'tilt rotate' command, which is displayed in a dialog # when the user is using this command. tiltRotateYDesc=Y (degrees) # LOCALIZATION NOTE (tiltRotateYManual) A fuller description of the 'y' # parameter to the 'rotate' command, displayed when the user asks for help # on what it does. -tiltRotateYManual=The ammount in degrees to rotate the webpage mesh along the Y axis +tiltRotateYManual=The amount in degrees to rotate the webpage mesh along the Y axis # LOCALIZATION NOTE (tiltRotateZDesc) A very short string to describe the # 'z' parameter to the 'tilt rotate' command, which is displayed in a dialog # when the user is using this command. tiltRotateZDesc=Z (degrees) # LOCALIZATION NOTE (tiltRotateZManual) A fuller description of the 'z' # parameter to the 'rotate' command, displayed when the user asks for help # on what it does. -tiltRotateZManual=The ammount in degrees to rotate the webpage mesh along the Z axis +tiltRotateZManual=The amount in degrees to rotate the webpage mesh along the Z axis # LOCALIZATION NOTE (tiltZoomDesc) A very short description of the 'tilt zoom' # command. See tiltZoomManual for a fuller description of what it does. This # string is designed to be shown in a menu alongside the command name, which # is why it should be as short as possible. tiltZoomDesc=Move away or towards the webpage mesh # LOCALIZATION NOTE (tiltZoomManual) A fuller description of the 'tilt zoom'
--- a/browser/locales/en-US/chrome/browser/devtools/styleinspector.properties +++ b/browser/locales/en-US/chrome/browser/devtools/styleinspector.properties @@ -32,15 +32,20 @@ rule.sourceElement=element # e.g "Inherited from body#bodyID (styles.css:20)" rule.inheritedSource=Inherited from %S (%S) # LOCALIZATION NOTE (style.highlighter.button): These strings are used inside # sidebar of the Highlighter for the style inspector button. # "Computed" refers to the Computed Style of the element. style.highlighter.button.label2=Computed style.highlighter.accesskey2=C -style.highlighter.button.tooltip=Inspect element computed styles +style.highlighter.button.tooltip2=Inspect element computed styles # LOCALIZATION NOTE (helpLinkTitle): For each style property # the user can hover it and get a help link button which allows one to # quickly jump to the documentation from the Mozilla Developer Network site. # 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
new file mode 100644 index 0000000000000000000000000000000000000000..5c5d0aec58bd073334798117dc955d67edeb0276 GIT binary patch literal 613 zc$@)c0-F7aP)<h;3K|Lk000e1NJLTq000dD000aK1^@s6xwkjj0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!2T4RhRCwA{k;`inQ543{ea+m=BlAdN z0wqyI+9H)!S5<c+T?j%Kii=`hsO_R?p^6JvrQ$|V6!9+*AGi>uf`VFf<6|RA(KdCV z#wePkt!bJx$;{kw5~3s*4%`dh?>pyy2i=+60`1550T_i-x{9YO4w@M{_wt%*b#-W{ z-wp(Y5cJ1wd?}Trd`+lV)(cB%u1B8`D*xBv&Ncw53^R(MK}Fg6i7S$ueS3AfR$fus zWf(QwTNONp!#eEOdxr1z9(sIQnES4awZ&aOKhB=$fc{;C0LjweY{Vi8;c7iFdA|Jp z>kr8-v5jvJ##etWB|D(z=LwvQN7-J(Mi7$S-ub6D@bCFY1Eyty0-5dk#fM{^5I`zo z;N#I4167wnRK6rCf3kz76;5(az&0q<va?4EnfLuoNCZTP!LfLZ?NkDQFb-}po$yv( zT`+8|4+SGoiGjhFH|H1bjybg|X#~-2n|Q*CFd#C5nhQ`P$<MLABkx#zAYJ$T=J?@o zV3wO3E#($=V}+xs#3m`ub=KGsR2{aVZyULp+;R9~v8<dguDV6xiXd4GF~ij|uP>j$ zVU3I$CIcoBKtW%bdZ9{oZqJ+B6WxUm_YYFv*Pyi$F4Mp@Jw(eMy_K)ZBjqB-tsrqJ z_w0aJuMfsjUABXnmoE_qV}u-mJf!!$_$$BwV7{+%n+Ij`00000NkvXXu0mjf*SZsB
--- a/browser/themes/gnomestripe/devtools/csshtmltree.css +++ b/browser/themes/gnomestripe/devtools/csshtmltree.css @@ -212,16 +212,29 @@ .ruleview-rule-source:hover { text-decoration: underline; } .ruleview-code { padding: 2px 5px; } +.ruleview-warning { + background: url("chrome://browser/skin/devtools/alerticon-warning.png"); + display: inline-block; + -moz-margin-start: 5px; + vertical-align: middle; + width: 13px; + height: 12px; +} + +.ruleview-warning[hidden] { + display: none; +} + .ruleview-ruleopen { -moz-padding-end: 5px; } .ruleview-propertylist { list-style: none; padding: 0; margin: 0;
--- a/browser/themes/gnomestripe/devtools/debugger.css +++ b/browser/themes/gnomestripe/devtools/debugger.css @@ -111,18 +111,23 @@ a { /** * Stack frames */ #stackframes { background-color: white; } -.dbg-stackframe-id { - -moz-padding-end: 1em; +.dbg-stackframe { + -moz-padding-start: 4px; + -moz-padding-end: 4px; +} + +.dbg-stackframe-name { + font-weight: 600; } /** * Properties elements */ #variables { background-color: white;
rename from browser/themes/gnomestripe/inspector.css rename to browser/themes/gnomestripe/devtools/htmlpanel.css
--- a/browser/themes/gnomestripe/jar.mn +++ b/browser/themes/gnomestripe/jar.mn @@ -8,17 +8,16 @@ browser.jar: skin/classic/browser/aboutCertError.css (aboutCertError.css) #ifdef MOZ_SERVICES_SYNC skin/classic/browser/aboutSyncTabs.css #endif skin/classic/browser/actionicon-tab.png * skin/classic/browser/browser.css (browser.css) * skin/classic/browser/engineManager.css (engineManager.css) skin/classic/browser/fullscreen-video.css - skin/classic/browser/inspector.css skin/classic/browser/Geolocation-16.png skin/classic/browser/Geolocation-64.png skin/classic/browser/Go-arrow.png skin/classic/browser/identity.png skin/classic/browser/Info.png skin/classic/browser/KUI-close.png skin/classic/browser/monitor.png skin/classic/browser/monitor_16-10.png @@ -83,22 +82,24 @@ browser.jar: 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/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/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/gcli.css (devtools/gcli.css) + skin/classic/browser/devtools/htmlpanel.css (devtools/htmlpanel.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/breadcrumbs/ltr-end-pressed.png (devtools/breadcrumbs/ltr-end-pressed.png) skin/classic/browser/devtools/breadcrumbs/ltr-end-selected-pressed.png (devtools/breadcrumbs/ltr-end-selected-pressed.png) skin/classic/browser/devtools/breadcrumbs/ltr-end-selected.png (devtools/breadcrumbs/ltr-end-selected.png) skin/classic/browser/devtools/breadcrumbs/ltr-end.png (devtools/breadcrumbs/ltr-end.png)
new file mode 100644 index 0000000000000000000000000000000000000000..5c5d0aec58bd073334798117dc955d67edeb0276 GIT binary patch literal 613 zc$@)c0-F7aP)<h;3K|Lk000e1NJLTq000dD000aK1^@s6xwkjj0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!2T4RhRCwA{k;`inQ543{ea+m=BlAdN z0wqyI+9H)!S5<c+T?j%Kii=`hsO_R?p^6JvrQ$|V6!9+*AGi>uf`VFf<6|RA(KdCV z#wePkt!bJx$;{kw5~3s*4%`dh?>pyy2i=+60`1550T_i-x{9YO4w@M{_wt%*b#-W{ z-wp(Y5cJ1wd?}Trd`+lV)(cB%u1B8`D*xBv&Ncw53^R(MK}Fg6i7S$ueS3AfR$fus zWf(QwTNONp!#eEOdxr1z9(sIQnES4awZ&aOKhB=$fc{;C0LjweY{Vi8;c7iFdA|Jp z>kr8-v5jvJ##etWB|D(z=LwvQN7-J(Mi7$S-ub6D@bCFY1Eyty0-5dk#fM{^5I`zo z;N#I4167wnRK6rCf3kz76;5(az&0q<va?4EnfLuoNCZTP!LfLZ?NkDQFb-}po$yv( zT`+8|4+SGoiGjhFH|H1bjybg|X#~-2n|Q*CFd#C5nhQ`P$<MLABkx#zAYJ$T=J?@o zV3wO3E#($=V}+xs#3m`ub=KGsR2{aVZyULp+;R9~v8<dguDV6xiXd4GF~ij|uP>j$ zVU3I$CIcoBKtW%bdZ9{oZqJ+B6WxUm_YYFv*Pyi$F4Mp@Jw(eMy_K)ZBjqB-tsrqJ z_w0aJuMfsjUABXnmoE_qV}u-mJf!!$_$$BwV7{+%n+Ij`00000NkvXXu0mjf*SZsB
--- a/browser/themes/pinstripe/devtools/csshtmltree.css +++ b/browser/themes/pinstripe/devtools/csshtmltree.css @@ -214,16 +214,29 @@ .ruleview-rule-source:hover { text-decoration: underline; } .ruleview-code { padding: 2px 5px; } +.ruleview-warning { + background: url("chrome://browser/skin/devtools/alerticon-warning.png"); + display: inline-block; + -moz-margin-start: 5px; + vertical-align: middle; + width: 13px; + height: 12px; +} + +.ruleview-warning[hidden] { + display: none; +} + .ruleview-ruleopen { -moz-padding-end: 5px; } .ruleview-propertylist { list-style: none; padding: 0; margin: 0;
--- a/browser/themes/pinstripe/devtools/debugger.css +++ b/browser/themes/pinstripe/devtools/debugger.css @@ -115,18 +115,23 @@ a { /** * Stack frames */ #stackframes { background-color: white; } -.dbg-stackframe-id { - -moz-padding-end: 1em; +.dbg-stackframe { + -moz-padding-start: 4px; + -moz-padding-end: 4px; +} + +.dbg-stackframe-name { + font-weight: 600; } /** * Properties elements */ #variables { background-color: white;
rename from browser/themes/pinstripe/inspector.css rename to browser/themes/pinstripe/devtools/htmlpanel.css
--- a/browser/themes/pinstripe/jar.mn +++ b/browser/themes/pinstripe/jar.mn @@ -53,17 +53,16 @@ browser.jar: skin/classic/browser/feeds/videoFeedIcon.png (feeds/feedIcon.png) skin/classic/browser/feeds/videoFeedIcon16.png (feeds/feedIcon16.png) skin/classic/browser/feeds/audioFeedIcon.png (feeds/feedIcon.png) skin/classic/browser/feeds/audioFeedIcon16.png (feeds/feedIcon16.png) skin/classic/browser/newtab/newTab.css (newtab/newTab.css) skin/classic/browser/newtab/strip.png (newtab/strip.png) skin/classic/browser/newtab/toolbar.png (newtab/toolbar.png) skin/classic/browser/setDesktopBackground.css - skin/classic/browser/inspector.css skin/classic/browser/monitor.png skin/classic/browser/monitor_16-10.png skin/classic/browser/places/allBookmarks.png (places/allBookmarks.png) * skin/classic/browser/places/places.css (places/places.css) * skin/classic/browser/places/organizer.css (places/organizer.css) skin/classic/browser/places/query.png (places/query.png) skin/classic/browser/places/bookmarksMenu.png (places/bookmarksMenu.png) skin/classic/browser/places/bookmarksToolbar.png (places/bookmarksToolbar.png) @@ -122,19 +121,21 @@ browser.jar: 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/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/gcli.css (devtools/gcli.css) + skin/classic/browser/devtools/htmlpanel.css (devtools/htmlpanel.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/toolbarbutton-close.png (devtools/toolbarbutton-close.png) * 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) @@ -160,20 +161,20 @@ browser.jar: skin/classic/browser/devtools/breadcrumbs/rtl-middle.png (devtools/breadcrumbs/rtl-middle.png) skin/classic/browser/devtools/breadcrumbs/rtl-start-pressed.png (devtools/breadcrumbs/rtl-start-pressed.png) skin/classic/browser/devtools/breadcrumbs/rtl-start-selected-pressed.png (devtools/breadcrumbs/rtl-start-selected-pressed.png) skin/classic/browser/devtools/breadcrumbs/rtl-start.png (devtools/breadcrumbs/rtl-start.png) skin/classic/browser/devtools/breadcrumbs/rtl-start-selected.png (devtools/breadcrumbs/rtl-start-selected.png) skin/classic/browser/devtools/splitview.css (devtools/splitview.css) skin/classic/browser/devtools/styleeditor.css (devtools/styleeditor.css) skin/classic/browser/devtools/debugger.css (devtools/debugger.css) - skin/classic/browser/devtools/magnifying-glass.png (devtools/magnifying-glass.png) - skin/classic/browser/devtools/itemToggle.png (devtools/itemToggle.png) - skin/classic/browser/devtools/itemArrow-rtl.png (devtools/itemArrow-rtl.png) - skin/classic/browser/devtools/itemArrow-ltr.png (devtools/itemArrow-ltr.png) + skin/classic/browser/devtools/magnifying-glass.png (devtools/magnifying-glass.png) + skin/classic/browser/devtools/itemToggle.png (devtools/itemToggle.png) + skin/classic/browser/devtools/itemArrow-rtl.png (devtools/itemArrow-rtl.png) + skin/classic/browser/devtools/itemArrow-ltr.png (devtools/itemArrow-ltr.png) skin/classic/browser/devtools/background-noise-toolbar.png (devtools/background-noise-toolbar.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
new file mode 100644 index 0000000000000000000000000000000000000000..5c5d0aec58bd073334798117dc955d67edeb0276 GIT binary patch literal 613 zc$@)c0-F7aP)<h;3K|Lk000e1NJLTq000dD000aK1^@s6xwkjj0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!2T4RhRCwA{k;`inQ543{ea+m=BlAdN z0wqyI+9H)!S5<c+T?j%Kii=`hsO_R?p^6JvrQ$|V6!9+*AGi>uf`VFf<6|RA(KdCV z#wePkt!bJx$;{kw5~3s*4%`dh?>pyy2i=+60`1550T_i-x{9YO4w@M{_wt%*b#-W{ z-wp(Y5cJ1wd?}Trd`+lV)(cB%u1B8`D*xBv&Ncw53^R(MK}Fg6i7S$ueS3AfR$fus zWf(QwTNONp!#eEOdxr1z9(sIQnES4awZ&aOKhB=$fc{;C0LjweY{Vi8;c7iFdA|Jp z>kr8-v5jvJ##etWB|D(z=LwvQN7-J(Mi7$S-ub6D@bCFY1Eyty0-5dk#fM{^5I`zo z;N#I4167wnRK6rCf3kz76;5(az&0q<va?4EnfLuoNCZTP!LfLZ?NkDQFb-}po$yv( zT`+8|4+SGoiGjhFH|H1bjybg|X#~-2n|Q*CFd#C5nhQ`P$<MLABkx#zAYJ$T=J?@o zV3wO3E#($=V}+xs#3m`ub=KGsR2{aVZyULp+;R9~v8<dguDV6xiXd4GF~ij|uP>j$ zVU3I$CIcoBKtW%bdZ9{oZqJ+B6WxUm_YYFv*Pyi$F4Mp@Jw(eMy_K)ZBjqB-tsrqJ z_w0aJuMfsjUABXnmoE_qV}u-mJf!!$_$$BwV7{+%n+Ij`00000NkvXXu0mjf*SZsB
--- a/browser/themes/winstripe/devtools/csshtmltree.css +++ b/browser/themes/winstripe/devtools/csshtmltree.css @@ -212,16 +212,29 @@ .ruleview-rule-source:hover { text-decoration: underline; } .ruleview-code { padding: 2px 5px; } +.ruleview-warning { + background: url("chrome://browser/skin/devtools/alerticon-warning.png"); + display: inline-block; + -moz-margin-start: 5px; + vertical-align: middle; + width: 13px; + height: 12px; +} + +.ruleview-warning[hidden] { + display: none; +} + .ruleview-ruleopen { -moz-padding-end: 5px; } .ruleview-propertylist { list-style: none; padding: 0; margin: 0;
--- a/browser/themes/winstripe/devtools/debugger.css +++ b/browser/themes/winstripe/devtools/debugger.css @@ -111,18 +111,23 @@ a { /** * Stack frames */ #stackframes { background-color: white; } -.dbg-stackframe-id { - -moz-padding-end: 1em; +.dbg-stackframe { + -moz-padding-start: 4px; + -moz-padding-end: 4px; +} + +.dbg-stackframe-name { + font-weight: 600; } /** * Properties elements */ #variables { background-color: white;
rename from browser/themes/winstripe/inspector.css rename to browser/themes/winstripe/devtools/htmlpanel.css
--- a/browser/themes/winstripe/jar.mn +++ b/browser/themes/winstripe/jar.mn @@ -55,17 +55,16 @@ browser.jar: skin/classic/browser/feeds/audioFeedIcon16.png (feeds/feedIcon16.png) skin/classic/browser/feeds/videoFeedIcon.png (feeds/feedIcon.png) skin/classic/browser/feeds/videoFeedIcon16.png (feeds/feedIcon16.png) skin/classic/browser/feeds/subscribe.css (feeds/subscribe.css) skin/classic/browser/feeds/subscribe-ui.css (feeds/subscribe-ui.css) skin/classic/browser/newtab/newTab.css (newtab/newTab.css) skin/classic/browser/newtab/strip.png (newtab/strip.png) skin/classic/browser/newtab/toolbar.png (newtab/toolbar.png) - skin/classic/browser/inspector.css skin/classic/browser/places/places.css (places/places.css) * skin/classic/browser/places/organizer.css (places/organizer.css) skin/classic/browser/places/bookmark.png (places/bookmark.png) skin/classic/browser/places/editBookmark.png (places/editBookmark.png) skin/classic/browser/places/query.png (places/query.png) skin/classic/browser/places/bookmarksMenu.png (places/bookmarksMenu.png) skin/classic/browser/places/bookmarksToolbar.png (places/bookmarksToolbar.png) skin/classic/browser/places/calendar.png (places/calendar.png) @@ -107,19 +106,21 @@ browser.jar: 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/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/gcli.css (devtools/gcli.css) + skin/classic/browser/devtools/htmlpanel.css (devtools/htmlpanel.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/toolbarbutton-close.png (devtools/toolbarbutton-close.png) 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) @@ -224,17 +225,16 @@ browser.jar: skin/classic/aero/browser/feeds/audioFeedIcon16.png (feeds/feedIcon16-aero.png) skin/classic/aero/browser/feeds/videoFeedIcon.png (feeds/feedIcon-aero.png) skin/classic/aero/browser/feeds/videoFeedIcon16.png (feeds/feedIcon16-aero.png) skin/classic/aero/browser/feeds/subscribe.css (feeds/subscribe.css) skin/classic/aero/browser/feeds/subscribe-ui.css (feeds/subscribe-ui.css) skin/classic/aero/browser/newtab/newTab.css (newtab/newTab.css) skin/classic/aero/browser/newtab/strip.png (newtab/strip.png) skin/classic/aero/browser/newtab/toolbar.png (newtab/toolbar.png) - skin/classic/aero/browser/inspector.css * skin/classic/aero/browser/places/places.css (places/places-aero.css) * skin/classic/aero/browser/places/organizer.css (places/organizer-aero.css) skin/classic/aero/browser/places/bookmark.png (places/bookmark.png) skin/classic/aero/browser/places/editBookmark.png (places/editBookmark.png) skin/classic/aero/browser/places/query.png (places/query-aero.png) skin/classic/aero/browser/places/bookmarksMenu.png (places/bookmarksMenu-aero.png) skin/classic/aero/browser/places/bookmarksToolbar.png (places/bookmarksToolbar-aero.png) skin/classic/aero/browser/places/calendar.png (places/calendar-aero.png) @@ -276,19 +276,21 @@ browser.jar: 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/arrows.png (devtools/arrows.png) skin/classic/aero/browser/devtools/commandline.png (devtools/commandline.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/gcli.css (devtools/gcli.css) + skin/classic/aero/browser/devtools/htmlpanel.css (devtools/htmlpanel.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/toolbarbutton-close.png (devtools/toolbarbutton-close.png) skin/classic/aero/browser/devtools/webconsole.css (devtools/webconsole.css) skin/classic/aero/browser/devtools/webconsole_networkpanel.css (devtools/webconsole_networkpanel.css) skin/classic/aero/browser/devtools/webconsole.png (devtools/webconsole.png)