diff --git a/browser/devtools/highlighter/inspector.jsm b/browser/devtools/highlighter/inspector.jsm index 4498e60a458..361fd38621e 100644 --- a/browser/devtools/highlighter/inspector.jsm +++ b/browser/devtools/highlighter/inspector.jsm @@ -1011,6 +1011,9 @@ InspectorUI.prototype = { * 1. Open the link in view source (for element style attributes) * 2. Open the link in the style editor * + * Like the style editor, we only view stylesheets contained in + * document.styleSheets. + * * @param aEvent The event containing the style rule to act on */ ruleViewCSSLinkClicked: function(aEvent) @@ -1021,12 +1024,29 @@ InspectorUI.prototype = { let rule = aEvent.detail.rule; let styleSheet = rule.sheet; + let doc = this.chromeWin.content.document; + let styleSheets = doc.styleSheets; + let contentSheet = false; + let line = rule.ruleLine || 0; - if (styleSheet) { - this.chromeWin.StyleEditor.openChrome(styleSheet, rule.ruleLine); + // Array.prototype.indexOf always returns -1 here so we loop through + // the styleSheets object instead. + for each (let sheet in styleSheets) { + if (sheet == styleSheet) { + contentSheet = true; + break; + } + } + + if (contentSheet) { + this.chromeWin.StyleEditor.openChrome(styleSheet, line); } else { - let href = rule.elementStyle.element.ownerDocument.location.href; - this.chromeWin.openUILinkIn("view-source:" + href, "window"); + let href = styleSheet ? styleSheet.href : ""; + if (rule.elementStyle.element) { + href = rule.elementStyle.element.ownerDocument.location.href; + } + let viewSourceUtils = this.chromeWin.gViewSourceUtils; + viewSourceUtils.viewSource(href, null, doc, line); } }, diff --git a/browser/devtools/styleinspector/CssHtmlTree.jsm b/browser/devtools/styleinspector/CssHtmlTree.jsm index 73db08312ae..4b31af15ed1 100644 --- a/browser/devtools/styleinspector/CssHtmlTree.jsm +++ b/browser/devtools/styleinspector/CssHtmlTree.jsm @@ -1211,18 +1211,45 @@ SelectorView.prototype = { * 1. Open the link in view source (for element style attributes). * 2. Open the link in the style editor. * + * Like the style editor, we only view stylesheets contained in + * document.styleSheets inside the style editor. + * * @param aEvent The click event */ openStyleEditor: function(aEvent) { - if (this.selectorInfo.selector._cssRule._cssSheet) { - let styleSheet = this.selectorInfo.selector._cssRule._cssSheet.domSheet; - let line = this.selectorInfo.ruleLine; + let rule = this.selectorInfo.selector._cssRule; + let doc = this.tree.win.content.document; + let line = this.selectorInfo.ruleLine || 0; + let cssSheet = rule._cssSheet; + let contentSheet = false; + let styleSheet; + let styleSheets; + if (cssSheet) { + styleSheet = cssSheet.domSheet; + styleSheets = doc.styleSheets; + + // Array.prototype.indexOf always returns -1 here so we loop through + // the styleSheets array instead. + for each (let sheet in styleSheets) { + if (sheet == styleSheet) { + contentSheet = true; + break; + } + } + } + + if (contentSheet) { this.tree.win.StyleEditor.openChrome(styleSheet, line); } else { - let href = this.selectorInfo.sourceElement.ownerDocument.location.href; - this.tree.win.openUILinkIn("view-source:" + href, "window"); + let href = styleSheet ? styleSheet.href : ""; + let viewSourceUtils = this.tree.win.gViewSourceUtils; + + if (this.selectorInfo.sourceElement) { + href = this.selectorInfo.sourceElement.ownerDocument.location.href; + } + viewSourceUtils.viewSource(href, null, doc, line); } }, }; diff --git a/browser/devtools/styleinspector/test/Makefile.in b/browser/devtools/styleinspector/test/Makefile.in index b4cae20ef6a..b5b7253b0d5 100644 --- a/browser/devtools/styleinspector/test/Makefile.in +++ b/browser/devtools/styleinspector/test/Makefile.in @@ -67,6 +67,8 @@ _BROWSER_TEST_FILES = \ browser_bug_592743_specificity.js \ browser_ruleview_bug_703643_context_menu_copy.js \ browser_computedview_bug_703643_context_menu_copy.js \ + browser_ruleview_734259_style_editor_link.js \ + browser_computedview_734259_style_editor_link.js \ head.js \ $(NULL) diff --git a/browser/devtools/styleinspector/test/browser_computedview_734259_style_editor_link.js b/browser/devtools/styleinspector/test/browser_computedview_734259_style_editor_link.js new file mode 100644 index 00000000000..a35c4ffc469 --- /dev/null +++ b/browser/devtools/styleinspector/test/browser_computedview_734259_style_editor_link.js @@ -0,0 +1,161 @@ +/* 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 win; +let stylePanel; + +function createDocument() +{ + doc.body.innerHTML = '
\n' + + '

Some header text

\n' + + '

hi.

\n' + + '

I am a test-case. This text exists ' + + 'solely to provide some things to ' + + 'highlight and count ' + + '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. ' + + 'some text

\n' + + '

more text

\n' + + '

even more text

' + + '
'; + doc.title = "Rule view style editor link test"; + + let span = doc.querySelector("span"); + ok(span, "captain, we have the span"); + + stylePanel = new StyleInspector(window); + Services.obs.addObserver(testInlineStyle, "StyleInspector-populated", false); + stylePanel.createPanel(false, function() { + stylePanel.open(span); + }); +} + +function testInlineStyle() +{ + Services.obs.removeObserver(testInlineStyle, "StyleInspector-populated", false); + + ok(stylePanel.isOpen(), "style inspector is open"); + + info("expanding property"); + expandProperty(0, function propertyExpanded() { + Services.ww.registerNotification(function onWindow(aSubject, aTopic) { + if (aTopic != "domwindowopened") { + return; + } + info("window opened"); + win = aSubject.QueryInterface(Ci.nsIDOMWindow); + win.addEventListener("load", function windowLoad() { + win.removeEventListener("load", windowLoad); + info("window load completed"); + let windowType = win.document.documentElement.getAttribute("windowtype"); + is(windowType, "navigator:view-source", "view source window is open"); + info("closing window"); + win.close(); + Services.ww.unregisterNotification(onWindow); + testInlineStyleSheet(); + }); + }); + let link = getLinkByIndex(0); + link.click(); + }); +} + +function testInlineStyleSheet() +{ + info("clicking an inline stylesheet"); + + Services.ww.registerNotification(function onWindow(aSubject, aTopic) { + if (aTopic != "domwindowopened") { + return; + } + info("window opened"); + win = aSubject.QueryInterface(Ci.nsIDOMWindow); + win.addEventListener("load", function windowLoad() { + win.removeEventListener("load", windowLoad); + info("window load completed"); + let windowType = win.document.documentElement.getAttribute("windowtype"); + is(windowType, "Tools:StyleEditor", "style editor window is open"); + + win.styleEditorChrome.addChromeListener({ + onEditorAdded: function checkEditor(aChrome, aEditor) { + if (!aEditor.sourceEditor) { + aEditor.addActionListener({ + onAttach: function (aEditor) { + aEditor.removeActionListener(this); + validateStyleEditorSheet(aEditor); + } + }); + } else { + validateStyleEditorSheet(aEditor); + } + } + }); + Services.ww.unregisterNotification(onWindow); + }); + }); + let link = getLinkByIndex(1); + link.click(); +} + +function validateStyleEditorSheet(aEditor) +{ + info("validating style editor stylesheet"); + + let sheet = doc.styleSheets[0]; + is(aEditor.styleSheet, sheet, "loaded stylesheet matches document stylesheet"); + info("closing window"); + win.close(); + + Services.obs.addObserver(finishUp, "StyleInspector-closed", false); + stylePanel.close(); +} + +function expandProperty(aIndex, aCallback) +{ + let iframe = stylePanel.iframe; + let contentDoc = iframe.contentDocument; + let contentWindow = iframe.contentWindow; + let expando = contentDoc.querySelectorAll(".expandable")[aIndex]; + expando.click(); + + // We use executeSoon to give the property time to expand. + executeSoon(aCallback); +} + +function getLinkByIndex(aIndex) +{ + let contentDoc = stylePanel.iframe.contentDocument; + let links = contentDoc.querySelectorAll(".rule-link .link"); + return links[aIndex]; +} + +function finishUp() +{ + Services.obs.removeObserver(finishUp, "StyleInspector-closed", false); + ok(!stylePanel.isOpen(), "style inspector is closed"); + doc = win = stylePanel = 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 style editor link test

"; +} diff --git a/browser/devtools/styleinspector/test/browser_ruleview_734259_style_editor_link.js b/browser/devtools/styleinspector/test/browser_ruleview_734259_style_editor_link.js new file mode 100644 index 00000000000..9ca43c8202b --- /dev/null +++ b/browser/devtools/styleinspector/test/browser_ruleview_734259_style_editor_link.js @@ -0,0 +1,181 @@ +/* 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 win; +let doc; +let contentWindow; + +let tempScope = {}; +Cu.import("resource:///modules/Services.jsm", tempScope); +let Services = tempScope.Services; + +function createDocument() +{ + doc.body.innerHTML = '
\n' + + '

Some header text

\n' + + '

hi.

\n' + + '

I am a test-case. This text exists ' + + 'solely to provide some things to ' + + 'highlight and count ' + + '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. ' + + 'some text

\n' + + '

more text

\n' + + '

even more text

' + + '
'; + doc.title = "Rule view style editor link test"; + + openInspector(); +} + +function openInspector() +{ + ok(window.InspectorUI, "InspectorUI variable exists"); + ok(!InspectorUI.inspecting, "Inspector is not highlighting"); + ok(InspectorUI.store.isEmpty(), "Inspector.store is empty"); + + Services.obs.addObserver(inspectorUIOpen, + InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false); + InspectorUI.openInspectorUI(); +} + +function inspectorUIOpen() +{ + Services.obs.removeObserver(inspectorUIOpen, + InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false); + + // Make sure the inspector is open. + ok(InspectorUI.inspecting, "Inspector is highlighting"); + ok(!InspectorUI.treePanel.isOpen(), "Inspector Tree Panel is not open"); + ok(!InspectorUI.isSidebarOpen, "Inspector Sidebar is not open"); + ok(!InspectorUI.store.isEmpty(), "InspectorUI.store is not empty"); + is(InspectorUI.store.length, 1, "Inspector.store.length = 1"); + + // Highlight a node. + let div = content.document.getElementsByTagName("div")[0]; + InspectorUI.inspectNode(div); + InspectorUI.stopInspecting(); + is(InspectorUI.selection, div, "selection matches the div element"); + + Services.obs.addObserver(testInlineStyle, + InspectorUI.INSPECTOR_NOTIFICATIONS.RULEVIEWREADY, false); + + InspectorUI.showSidebar(); + InspectorUI.openRuleView(); +} + +function testInlineStyle() +{ + Services.obs.removeObserver(testInlineStyle, + InspectorUI.INSPECTOR_NOTIFICATIONS.RULEVIEWREADY, false); + + executeSoon(function() { + info("clicking an inline style"); + + Services.ww.registerNotification(function onWindow(aSubject, aTopic) { + if (aTopic != "domwindowopened") { + return; + } + + win = aSubject.QueryInterface(Ci.nsIDOMWindow); + win.addEventListener("load", function windowLoad() { + win.removeEventListener("load", windowLoad); + let windowType = win.document.documentElement.getAttribute("windowtype"); + is(windowType, "navigator:view-source", "view source window is open"); + win.close(); + Services.ww.unregisterNotification(onWindow); + testInlineStyleSheet(); + }); + }); + EventUtils.synthesizeMouseAtCenter(getLinkByIndex(0), { }, contentWindow); + }); +} + +function testInlineStyleSheet() +{ + info("clicking an inline stylesheet"); + + Services.ww.registerNotification(function onWindow(aSubject, aTopic) { + if (aTopic != "domwindowopened") { + return; + } + + win = aSubject.QueryInterface(Ci.nsIDOMWindow); + win.addEventListener("load", function windowLoad() { + win.removeEventListener("load", windowLoad); + + let windowType = win.document.documentElement.getAttribute("windowtype"); + is(windowType, "Tools:StyleEditor", "style editor window is open"); + + win.styleEditorChrome.addChromeListener({ + onEditorAdded: function checkEditor(aChrome, aEditor) { + if (!aEditor.sourceEditor) { + aEditor.addActionListener({ + onAttach: function (aEditor) { + aEditor.removeActionListener(this); + validateStyleEditorSheet(aEditor); + } + }); + } else { + validateStyleEditorSheet(aEditor); + } + } + }); + + Services.ww.unregisterNotification(onWindow); + }); + }); + + EventUtils.synthesizeMouse(getLinkByIndex(1), 5, 5, { }, contentWindow); +} + +function validateStyleEditorSheet(aEditor) +{ + info("validating style editor stylesheet"); + + let sheet = doc.styleSheets[0]; + + is(aEditor.styleSheet, sheet, "loaded stylesheet matches document stylesheet"); + win.close(); + + finishup(); +} + +function getLinkByIndex(aIndex) +{ + let ruleView = document.querySelector("#devtools-sidebar-iframe-ruleview"); + let contentDoc = ruleView.contentDocument; + let links = contentDoc.querySelectorAll(".ruleview-rule-source"); + contentWindow = ruleView.contentWindow; + return links[aIndex]; +} + +function finishup() +{ + InspectorUI.hideSidebar(); + InspectorUI.closeInspectorUI(); + gBrowser.removeCurrentTab(); + doc = contentWindow = win = 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,

Rule view style editor link test

"; +} diff --git a/browser/devtools/styleinspector/test/browser_ruleview_bug_703643_context_menu_copy.js b/browser/devtools/styleinspector/test/browser_ruleview_bug_703643_context_menu_copy.js index 25e37ffe8bf..9dd38b895bb 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_bug_703643_context_menu_copy.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_bug_703643_context_menu_copy.js @@ -187,6 +187,7 @@ function checkClipboardData(aExpectedPattern) function finishup() { + InspectorUI.hideSidebar(); InspectorUI.closeInspectorUI(); gBrowser.removeCurrentTab(); doc = null; diff --git a/browser/devtools/styleinspector/test/browser_ruleview_focus.js b/browser/devtools/styleinspector/test/browser_ruleview_focus.js index 3500a586013..29f051207a5 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_focus.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_focus.js @@ -77,7 +77,7 @@ function testFocus() // If not, we'll wait here until we time out. waitForEditorFocus(brace.parentNode, function onNewEditor(aEditor) { aEditor.input.blur(); - finishTest(); + finishUp(); }); EventUtils.sendKey("return"); }); @@ -89,6 +89,8 @@ function testFocus() function finishUp() { + InspectorUI.hideSidebar(); + InspectorUI.closeInspectorUI(); doc = stylePanel = null; gBrowser.removeCurrentTab(); finish();