diff --git a/.eslintignore b/.eslintignore index a5a7104e11fe..d1289cf558b6 100644 --- a/.eslintignore +++ b/.eslintignore @@ -113,6 +113,7 @@ devtools/server/** !devtools/server/actors/webbrowser.js !devtools/server/actors/styles.js !devtools/server/actors/string.js +!devtools/server/actors/csscoverage.js devtools/shared/*.js !devtools/shared/css-lexer.js !devtools/shared/defer.js diff --git a/devtools/client/commandline/test/browser_cmd_screenshot.js b/devtools/client/commandline/test/browser_cmd_screenshot.js index 566a9e3faa04..920d03c533ba 100644 --- a/devtools/client/commandline/test/browser_cmd_screenshot.js +++ b/devtools/client/commandline/test/browser_cmd_screenshot.js @@ -99,7 +99,6 @@ function* addTabWithToolbarRunTests(win) { filename: { value: "" + file.path }, fullpage: { value: false }, clipboard: { value: false }, - chrome: { value: false }, }, }, exec: { @@ -123,7 +122,6 @@ function* addTabWithToolbarRunTests(win) { check: { args: { clipboard: { value: true }, - chrome: { value: false }, }, }, exec: { @@ -143,7 +141,6 @@ function* addTabWithToolbarRunTests(win) { args: { fullpage: { value: true }, clipboard: { value: true }, - chrome: { value: false }, }, }, exec: { @@ -166,7 +163,6 @@ function* addTabWithToolbarRunTests(win) { check: { args: { clipboard: { value: true }, - chrome: { value: false }, }, }, exec: { @@ -215,7 +211,6 @@ function* addTabWithToolbarRunTests(win) { check: { args: { clipboard: { value: true }, - chrome: { value: false }, }, }, exec: { @@ -239,7 +234,6 @@ function* addTabWithToolbarRunTests(win) { args: { fullpage: { value: true }, clipboard: { value: true }, - chrome: { value: false }, }, }, exec: { @@ -264,7 +258,6 @@ function* addTabWithToolbarRunTests(win) { check: { args: { clipboard: { value: true }, - chrome: { value: false }, }, }, exec: { diff --git a/devtools/client/inspector/rules/test/browser_rules_add-rule-with-menu.js b/devtools/client/inspector/rules/test/browser_rules_add-rule-with-menu.js index 2e19726ebd8e..8f533e2bd21f 100644 --- a/devtools/client/inspector/rules/test/browser_rules_add-rule-with-menu.js +++ b/devtools/client/inspector/rules/test/browser_rules_add-rule-with-menu.js @@ -19,19 +19,16 @@ add_task(function* () { function* addNewRuleFromContextMenu(inspector, view) { info("Waiting for context menu to be shown"); - let onPopup = once(view._contextmenu._menupopup, "popupshown"); - let win = view.styleWindow; - EventUtils.synthesizeMouseAtCenter(view.element, - {button: 2, type: "contextmenu"}, win); - yield onPopup; + let allMenuItems = openStyleContextMenuAndGetAllItems(view, view.element); + let menuitemAddRule = allMenuItems.find(item => item.label === + _STRINGS.GetStringFromName("styleinspector.contextmenu.addNewRule")); - ok(!view._contextmenu.menuitemAddRule.hidden, "Add rule is visible"); + ok(menuitemAddRule.visible, "Add rule is visible"); info("Adding the new rule and expecting a ruleview-changed event"); let onRuleViewChanged = view.once("ruleview-changed"); - view._contextmenu.menuitemAddRule.click(); - view._contextmenu._menupopup.hidePopup(); + menuitemAddRule.click(); yield onRuleViewChanged; } diff --git a/devtools/client/inspector/rules/test/browser_rules_context-menu-show-mdn-docs-01.js b/devtools/client/inspector/rules/test/browser_rules_context-menu-show-mdn-docs-01.js index 5e3890e17429..e7fefdcc833a 100644 --- a/devtools/client/inspector/rules/test/browser_rules_context-menu-show-mdn-docs-01.js +++ b/devtools/client/inspector/rules/test/browser_rules_context-menu-show-mdn-docs-01.js @@ -58,11 +58,12 @@ function* testMdnContextMenuItemVisibility(view) { let root = rootElement(view); for (let node of iterateNodes(root)) { info("Setting " + node + " as popupNode"); - view.styleDocument.popupNode = node; + info("Creating context menu with " + node + " as popupNode"); + let allMenuItems = openStyleContextMenuAndGetAllItems(view, node); + let menuitemShowMdnDocs = allMenuItems.find(item => item.label === + _STRINGS.GetStringFromName("styleinspector.contextmenu.showMdnDocs")); - info("Updating context menu state"); - view._contextmenu._updateMenuItems(); - let isVisible = !view._contextmenu.menuitemShowMdnDocs.hidden; + let isVisible = menuitemShowMdnDocs.visible; let shouldBeVisible = isPropertyNameNode(node); let message = shouldBeVisible ? "shown" : "hidden"; is(isVisible, shouldBeVisible, diff --git a/devtools/client/inspector/rules/test/browser_rules_context-menu-show-mdn-docs-02.js b/devtools/client/inspector/rules/test/browser_rules_context-menu-show-mdn-docs-02.js index 6963b0dd5e8e..f18e4f674bc6 100644 --- a/devtools/client/inspector/rules/test/browser_rules_context-menu-show-mdn-docs-02.js +++ b/devtools/client/inspector/rules/test/browser_rules_context-menu-show-mdn-docs-02.js @@ -46,14 +46,15 @@ function* testShowMdnTooltip(view) { let {nameSpan} = getRuleViewProperty(view, "element", PROPERTYNAME); - view.styleDocument.popupNode = nameSpan.firstChild; - view._contextmenu._updateMenuItems(); + let allMenuItems = openStyleContextMenuAndGetAllItems(view, nameSpan.firstChild); + let menuitemShowMdnDocs = allMenuItems.find(item => item.label === + _STRINGS.GetStringFromName("styleinspector.contextmenu.showMdnDocs")); let cssDocs = view.tooltips.cssDocs; info("Showing the MDN docs tooltip"); let onShown = cssDocs.tooltip.once("shown"); - view._contextmenu.menuitemShowMdnDocs.click(); + menuitemShowMdnDocs.click(); yield onShown; ok(true, "The MDN docs tooltip was shown"); } diff --git a/devtools/client/inspector/rules/test/browser_rules_context-menu-show-mdn-docs-03.js b/devtools/client/inspector/rules/test/browser_rules_context-menu-show-mdn-docs-03.js index abad1640fd76..a7b24f0c0720 100644 --- a/devtools/client/inspector/rules/test/browser_rules_context-menu-show-mdn-docs-03.js +++ b/devtools/client/inspector/rules/test/browser_rules_context-menu-show-mdn-docs-03.js @@ -103,11 +103,11 @@ function* testMdnContextMenuItemVisibility(view, shouldBeVisible) { info("Set a CSS property name as popupNode"); let root = rootElement(view); let node = root.querySelector("." + PROPERTY_NAME_CLASS).firstChild; - view.styleDocument.popupNode = node; + let allMenuItems = openStyleContextMenuAndGetAllItems(view, node); + let menuitemShowMdnDocs = allMenuItems.find(item => item.label === + _STRINGS.GetStringFromName("styleinspector.contextmenu.showMdnDocs")); - info("Update context menu state"); - view._contextmenu._updateMenuItems(); - let isVisible = !view._contextmenu.menuitemShowMdnDocs.hidden; + let isVisible = menuitemShowMdnDocs.visible; is(isVisible, shouldBeVisible, "The MDN context menu item is " + message); } diff --git a/devtools/client/inspector/rules/test/browser_rules_copy_styles.js b/devtools/client/inspector/rules/test/browser_rules_copy_styles.js index cf491d7c49de..c9e74287ce5a 100644 --- a/devtools/client/inspector/rules/test/browser_rules_copy_styles.js +++ b/devtools/client/inspector/rules/test/browser_rules_copy_styles.js @@ -18,7 +18,6 @@ const TEST_URI = URL_ROOT + "doc_copystyles.html"; add_task(function* () { yield addTab(TEST_URI); let { inspector, view } = yield openRuleView(); - let contextmenu = view._contextmenu; yield selectNode("#testid", inspector); let ruleEditor = getRuleViewRuleEditor(view, 1); @@ -27,77 +26,77 @@ add_task(function* () { { desc: "Test Copy Property Name", node: ruleEditor.rule.textProps[0].editor.nameSpan, - menuItem: contextmenu.menuitemCopyPropertyName, + menuItemLabel: "styleinspector.contextmenu.copyPropertyName", expectedPattern: "color", - hidden: { - copyLocation: true, - copyPropertyDeclaration: false, - copyPropertyName: false, - copyPropertyValue: true, - copySelector: true, - copyRule: false + visible: { + copyLocation: false, + copyPropertyDeclaration: true, + copyPropertyName: true, + copyPropertyValue: false, + copySelector: false, + copyRule: true } }, { desc: "Test Copy Property Value", node: ruleEditor.rule.textProps[2].editor.valueSpan, - menuItem: contextmenu.menuitemCopyPropertyValue, + menuItemLabel: "styleinspector.contextmenu.copyPropertyValue", expectedPattern: "12px", - hidden: { - copyLocation: true, - copyPropertyDeclaration: false, - copyPropertyName: true, - copyPropertyValue: false, - copySelector: true, - copyRule: false + visible: { + copyLocation: false, + copyPropertyDeclaration: true, + copyPropertyName: false, + copyPropertyValue: true, + copySelector: false, + copyRule: true } }, { desc: "Test Copy Property Value with Priority", node: ruleEditor.rule.textProps[3].editor.valueSpan, - menuItem: contextmenu.menuitemCopyPropertyValue, + menuItemLabel: "styleinspector.contextmenu.copyPropertyValue", expectedPattern: "#00F !important", - hidden: { - copyLocation: true, - copyPropertyDeclaration: false, - copyPropertyName: true, - copyPropertyValue: false, - copySelector: true, - copyRule: false + visible: { + copyLocation: false, + copyPropertyDeclaration: true, + copyPropertyName: false, + copyPropertyValue: true, + copySelector: false, + copyRule: true } }, { desc: "Test Copy Property Declaration", node: ruleEditor.rule.textProps[2].editor.nameSpan, - menuItem: contextmenu.menuitemCopyPropertyDeclaration, + menuItemLabel: "styleinspector.contextmenu.copyPropertyDeclaration", expectedPattern: "font-size: 12px;", - hidden: { - copyLocation: true, - copyPropertyDeclaration: false, - copyPropertyName: false, - copyPropertyValue: true, - copySelector: true, - copyRule: false + visible: { + copyLocation: false, + copyPropertyDeclaration: true, + copyPropertyName: true, + copyPropertyValue: false, + copySelector: false, + copyRule: true } }, { desc: "Test Copy Property Declaration with Priority", node: ruleEditor.rule.textProps[3].editor.nameSpan, - menuItem: contextmenu.menuitemCopyPropertyDeclaration, + menuItemLabel: "styleinspector.contextmenu.copyPropertyDeclaration", expectedPattern: "border-color: #00F !important;", - hidden: { - copyLocation: true, - copyPropertyDeclaration: false, - copyPropertyName: false, - copyPropertyValue: true, - copySelector: true, - copyRule: false + visible: { + copyLocation: false, + copyPropertyDeclaration: true, + copyPropertyName: true, + copyPropertyValue: false, + copySelector: false, + copyRule: true } }, { desc: "Test Copy Rule", node: ruleEditor.rule.textProps[2].editor.nameSpan, - menuItem: contextmenu.menuitemCopyRule, + menuItemLabel: "styleinspector.contextmenu.copyRule", expectedPattern: "#testid {[\\r\\n]+" + "\tcolor: #F00;[\\r\\n]+" + "\tbackground-color: #00F;[\\r\\n]+" + @@ -105,42 +104,42 @@ add_task(function* () { "\tborder-color: #00F !important;[\\r\\n]+" + "\t--var: \"\\*/\";[\\r\\n]+" + "}", - hidden: { - copyLocation: true, - copyPropertyDeclaration: false, - copyPropertyName: false, - copyPropertyValue: true, - copySelector: true, - copyRule: false + visible: { + copyLocation: false, + copyPropertyDeclaration: true, + copyPropertyName: true, + copyPropertyValue: false, + copySelector: false, + copyRule: true } }, { desc: "Test Copy Selector", node: ruleEditor.selectorText, - menuItem: contextmenu.menuitemCopySelector, + menuItemLabel: "styleinspector.contextmenu.copySelector", expectedPattern: "html, body, #testid", - hidden: { - copyLocation: true, - copyPropertyDeclaration: true, - copyPropertyName: true, - copyPropertyValue: true, - copySelector: false, - copyRule: false + visible: { + copyLocation: false, + copyPropertyDeclaration: false, + copyPropertyName: false, + copyPropertyValue: false, + copySelector: true, + copyRule: true } }, { desc: "Test Copy Location", node: ruleEditor.source, - menuItem: contextmenu.menuitemCopyLocation, + menuItemLabel: "styleinspector.contextmenu.copyLocation", expectedPattern: "http://example.com/browser/devtools/client/" + "inspector/rules/test/doc_copystyles.css", - hidden: { - copyLocation: false, - copyPropertyDeclaration: true, - copyPropertyName: true, - copyPropertyValue: true, - copySelector: true, - copyRule: false + visible: { + copyLocation: true, + copyPropertyDeclaration: false, + copyPropertyName: false, + copyPropertyValue: false, + copySelector: false, + copyRule: true } }, { @@ -149,7 +148,7 @@ add_task(function* () { }, desc: "Test Copy Rule with Disabled Property", node: ruleEditor.rule.textProps[2].editor.nameSpan, - menuItem: contextmenu.menuitemCopyRule, + menuItemLabel: "styleinspector.contextmenu.copyRule", expectedPattern: "#testid {[\\r\\n]+" + "\t\/\\* color: #F00; \\*\/[\\r\\n]+" + "\tbackground-color: #00F;[\\r\\n]+" + @@ -157,13 +156,13 @@ add_task(function* () { "\tborder-color: #00F !important;[\\r\\n]+" + "\t--var: \"\\*/\";[\\r\\n]+" + "}", - hidden: { - copyLocation: true, - copyPropertyDeclaration: false, - copyPropertyName: false, - copyPropertyValue: true, - copySelector: true, - copyRule: false + visible: { + copyLocation: false, + copyPropertyDeclaration: true, + copyPropertyName: true, + copyPropertyValue: false, + copySelector: false, + copyRule: true } }, { @@ -172,7 +171,7 @@ add_task(function* () { }, desc: "Test Copy Rule with Disabled Property with Comment", node: ruleEditor.rule.textProps[2].editor.nameSpan, - menuItem: contextmenu.menuitemCopyRule, + menuItemLabel: "styleinspector.contextmenu.copyRule", expectedPattern: "#testid {[\\r\\n]+" + "\t\/\\* color: #F00; \\*\/[\\r\\n]+" + "\tbackground-color: #00F;[\\r\\n]+" + @@ -180,81 +179,94 @@ add_task(function* () { "\tborder-color: #00F !important;[\\r\\n]+" + "\t/\\* --var: \"\\*\\\\\/\"; \\*\/[\\r\\n]+" + "}", - hidden: { - copyLocation: true, - copyPropertyDeclaration: false, - copyPropertyName: false, - copyPropertyValue: true, - copySelector: true, - copyRule: false + visible: { + copyLocation: false, + copyPropertyDeclaration: true, + copyPropertyName: true, + copyPropertyValue: false, + copySelector: false, + copyRule: true } }, { desc: "Test Copy Property Declaration with Disabled Property", node: ruleEditor.rule.textProps[0].editor.nameSpan, - menuItem: contextmenu.menuitemCopyPropertyDeclaration, + menuItemLabel: "styleinspector.contextmenu.copyPropertyDeclaration", expectedPattern: "\/\\* color: #F00; \\*\/", - hidden: { - copyLocation: true, - copyPropertyDeclaration: false, - copyPropertyName: false, - copyPropertyValue: true, - copySelector: true, - copyRule: false + visible: { + copyLocation: false, + copyPropertyDeclaration: true, + copyPropertyName: true, + copyPropertyValue: false, + copySelector: false, + copyRule: true } }, ]; - for (let { setup, desc, node, menuItem, expectedPattern, hidden } of data) { + for (let { setup, desc, node, menuItemLabel, expectedPattern, visible } of data) { if (setup) { yield setup(); } info(desc); - yield checkCopyStyle(view, node, menuItem, expectedPattern, hidden); + yield checkCopyStyle(view, node, menuItemLabel, expectedPattern, visible); } }); -function* checkCopyStyle(view, node, menuItem, expectedPattern, hidden) { - let onPopup = once(view._contextmenu._menupopup, "popupshown"); - EventUtils.synthesizeMouseAtCenter(node, - {button: 2, type: "contextmenu"}, view.styleWindow); - yield onPopup; +function* checkCopyStyle(view, node, menuItemLabel, expectedPattern, visible) { + let allMenuItems = openStyleContextMenuAndGetAllItems(view, node); + let menuItem = allMenuItems.find(item => + item.label === _STRINGS.GetStringFromName(menuItemLabel)); + let menuitemCopy = allMenuItems.find(item => item.label === + _STRINGS.GetStringFromName("styleinspector.contextmenu.copy")); + let menuitemCopyLocation = allMenuItems.find(item => item.label === + _STRINGS.GetStringFromName("styleinspector.contextmenu.copyLocation")); + let menuitemCopyPropertyDeclaration = allMenuItems.find(item => item.label === + _STRINGS.GetStringFromName("styleinspector.contextmenu.copyPropertyDeclaration")); + let menuitemCopyPropertyName = allMenuItems.find(item => item.label === + _STRINGS.GetStringFromName("styleinspector.contextmenu.copyPropertyName")); + let menuitemCopyPropertyValue = allMenuItems.find(item => item.label === + _STRINGS.GetStringFromName("styleinspector.contextmenu.copyPropertyValue")); + let menuitemCopySelector = allMenuItems.find(item => item.label === + _STRINGS.GetStringFromName("styleinspector.contextmenu.copySelector")); + let menuitemCopyRule = allMenuItems.find(item => item.label === + _STRINGS.GetStringFromName("styleinspector.contextmenu.copyRule")); - ok(view._contextmenu.menuitemCopy.disabled, + ok(menuitemCopy.disabled, "Copy disabled is as expected: true"); - ok(!view._contextmenu.menuitemCopy.hidden, - "Copy hidden is as expected: false"); + ok(menuitemCopy.visible, + "Copy visible is as expected: true"); - is(view._contextmenu.menuitemCopyLocation.hidden, - hidden.copyLocation, - "Copy Location hidden attribute is as expected: " + - hidden.copyLocation); + is(menuitemCopyLocation.visible, + visible.copyLocation, + "Copy Location visible attribute is as expected: " + + visible.copyLocation); - is(view._contextmenu.menuitemCopyPropertyDeclaration.hidden, - hidden.copyPropertyDeclaration, - "Copy Property Declaration hidden attribute is as expected: " + - hidden.copyPropertyDeclaration); + is(menuitemCopyPropertyDeclaration.visible, + visible.copyPropertyDeclaration, + "Copy Property Declaration visible attribute is as expected: " + + visible.copyPropertyDeclaration); - is(view._contextmenu.menuitemCopyPropertyName.hidden, - hidden.copyPropertyName, - "Copy Property Name hidden attribute is as expected: " + - hidden.copyPropertyName); + is(menuitemCopyPropertyName.visible, + visible.copyPropertyName, + "Copy Property Name visible attribute is as expected: " + + visible.copyPropertyName); - is(view._contextmenu.menuitemCopyPropertyValue.hidden, - hidden.copyPropertyValue, - "Copy Property Value hidden attribute is as expected: " + - hidden.copyPropertyValue); + is(menuitemCopyPropertyValue.visible, + visible.copyPropertyValue, + "Copy Property Value visible attribute is as expected: " + + visible.copyPropertyValue); - is(view._contextmenu.menuitemCopySelector.hidden, - hidden.copySelector, - "Copy Selector hidden attribute is as expected: " + - hidden.copySelector); + is(menuitemCopySelector.visible, + visible.copySelector, + "Copy Selector visible attribute is as expected: " + + visible.copySelector); - is(view._contextmenu.menuitemCopyRule.hidden, - hidden.copyRule, - "Copy Rule hidden attribute is as expected: " + - hidden.copyRule); + is(menuitemCopyRule.visible, + visible.copyRule, + "Copy Rule visible attribute is as expected: " + + visible.copyRule); try { yield waitForClipboard(() => menuItem.click(), @@ -262,8 +274,6 @@ function* checkCopyStyle(view, node, menuItem, expectedPattern, hidden) { } catch (e) { failedClipboard(expectedPattern); } - - view._contextmenu._menupopup.hidePopup(); } function* disableProperty(view, index) { diff --git a/devtools/client/inspector/rules/test/browser_rules_select-and-copy-styles.js b/devtools/client/inspector/rules/test/browser_rules_select-and-copy-styles.js index b00a9a8954b6..bbfc4f477a7e 100644 --- a/devtools/client/inspector/rules/test/browser_rules_select-and-copy-styles.js +++ b/devtools/client/inspector/rules/test/browser_rules_select-and-copy-styles.js @@ -69,29 +69,25 @@ function* checkCopySelection(view) { "html {[\\r\\n]+" + " color: #000000;[\\r\\n]*"; - let onPopup = once(view._contextmenu._menupopup, "popupshown"); - EventUtils.synthesizeMouseAtCenter(prop, - {button: 2, type: "contextmenu"}, win); - yield onPopup; + let allMenuItems = openStyleContextMenuAndGetAllItems(view, prop); + let menuitemCopy = allMenuItems.find(item => item.label === + _STRINGS.GetStringFromName("styleinspector.contextmenu.copy")); - ok(!view._contextmenu.menuitemCopy.hidden, + ok(menuitemCopy.visible, "Copy menu item is displayed as expected"); try { - yield waitForClipboard(() => view._contextmenu.menuitemCopy.click(), + yield waitForClipboard(() => menuitemCopy.click(), () => checkClipboardData(expectedPattern)); } catch (e) { failedClipboard(expectedPattern); } - - view._contextmenu._menupopup.hidePopup(); } function* checkSelectAll(view) { info("Testing select-all copy"); let contentDoc = view.styleDocument; - let win = view.styleWindow; let prop = contentDoc.querySelector(".ruleview-property"); info("Checking that _SelectAll() then copy returns the correct " + @@ -107,28 +103,24 @@ function* checkSelectAll(view) { " color: #000000;[\\r\\n]+" + "}[\\r\\n]*"; - let onPopup = once(view._contextmenu._menupopup, "popupshown"); - EventUtils.synthesizeMouseAtCenter(prop, - {button: 2, type: "contextmenu"}, win); - yield onPopup; + let allMenuItems = openStyleContextMenuAndGetAllItems(view, prop); + let menuitemCopy = allMenuItems.find(item => item.label === + _STRINGS.GetStringFromName("styleinspector.contextmenu.copy")); - ok(!view._contextmenu.menuitemCopy.hidden, + ok(menuitemCopy.visible, "Copy menu item is displayed as expected"); try { - yield waitForClipboard(() => view._contextmenu.menuitemCopy.click(), + yield waitForClipboard(() => menuitemCopy.click(), () => checkClipboardData(expectedPattern)); } catch (e) { failedClipboard(expectedPattern); } - - view._contextmenu._menupopup.hidePopup(); } function* checkCopyEditorValue(view) { info("Testing CSS property editor value copy"); - let win = view.styleWindow; let ruleEditor = getRuleViewRuleEditor(view, 0); let propEditor = ruleEditor.rule.textProps[0].editor; @@ -139,28 +131,19 @@ function* checkCopyEditorValue(view) { let expectedPattern = "10em"; - let onPopup = once(view._contextmenu._menupopup, "popupshown"); - EventUtils.synthesizeMouseAtCenter(editor.input, - {button: 2, type: "contextmenu"}, win); - yield onPopup; + let allMenuItems = openStyleContextMenuAndGetAllItems(view, editor.input); + let menuitemCopy = allMenuItems.find(item => item.label === + _STRINGS.GetStringFromName("styleinspector.contextmenu.copy")); - ok(!view._contextmenu.menuitemCopy.hidden, + ok(menuitemCopy.visible, "Copy menu item is displayed as expected"); try { - yield waitForClipboard(() => view._contextmenu.menuitemCopy.click(), + yield waitForClipboard(() => menuitemCopy.click(), () => checkClipboardData(expectedPattern)); } catch (e) { failedClipboard(expectedPattern); } - - view._contextmenu._menupopup.hidePopup(); - - // The value field is still focused. Blur it now and wait for the - // ruleview-changed event to avoid pending requests. - let onRuleViewChanged = view.once("ruleview-changed"); - EventUtils.synthesizeKey("VK_ESCAPE", {}); - yield onRuleViewChanged; } function checkClipboardData(expectedPattern) { diff --git a/devtools/client/inspector/rules/test/head.js b/devtools/client/inspector/rules/test/head.js index 5658fbed3d1d..a9ef4e405c3e 100644 --- a/devtools/client/inspector/rules/test/head.js +++ b/devtools/client/inspector/rules/test/head.js @@ -19,6 +19,8 @@ var {getInplaceEditorForSpan: inplaceEditor} = const ROOT_TEST_DIR = getRootDirectory(gTestPath); const FRAME_SCRIPT_URL = ROOT_TEST_DIR + "doc_frame_script.js"; +const _STRINGS = Services.strings.createBundle( + "chrome://devtools-shared/locale/styleinspector.properties"); registerCleanupFunction(() => { Services.prefs.clearUserPref("devtools.defaultColorUnit"); @@ -782,3 +784,23 @@ function* sendKeysAndWaitForFocus(view, element, keys) { } yield onFocus; } + +/** + * Open the style editor context menu and return all of it's items in a flat array + * @param {CssRuleView} view + * The instance of the rule-view panel + * @return An array of MenuItems + */ +function openStyleContextMenuAndGetAllItems(view, target) { + let menu = view._contextmenu._openMenu({target: target}); + + // Flatten all menu items into a single array to make searching through it easier + let allItems = [].concat.apply([], menu.items.map(function addItem(item) { + if (item.submenu) { + return addItem(item.submenu.items); + } + return item; + })); + + return allItems; +} diff --git a/devtools/client/inspector/shared/style-inspector-menu.js b/devtools/client/inspector/shared/style-inspector-menu.js index 59bbcf6c18d9..48de1c23f895 100644 --- a/devtools/client/inspector/shared/style-inspector-menu.js +++ b/devtools/client/inspector/shared/style-inspector-menu.js @@ -11,6 +11,9 @@ const {PREF_ORIG_SOURCES} = require("devtools/client/styleeditor/utils"); const Services = require("Services"); const {Task} = require("devtools/shared/task"); +const Menu = require("devtools/client/framework/menu"); +const MenuItem = require("devtools/client/framework/menu-item"); + loader.lazyRequireGetter(this, "overlays", "devtools/client/inspector/shared/style-inspector-overlays"); loader.lazyServiceGetter(this, "clipboardHelper", @@ -20,7 +23,6 @@ loader.lazyGetter(this, "_strings", () => { .createBundle("chrome://devtools-shared/locale/styleinspector.properties"); }); -const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; const PREF_ENABLE_MDN_DOCS_TOOLTIP = "devtools.inspector.mdnDocsTooltip.enabled"; @@ -54,9 +56,6 @@ function StyleInspectorMenu(view, options) { this._onSelectAll = this._onSelectAll.bind(this); this._onShowMdnDocs = this._onShowMdnDocs.bind(this); this._onToggleOrigSources = this._onToggleOrigSources.bind(this); - this._updateMenuItems = this._updateMenuItems.bind(this); - - this._createContextMenu(); } module.exports = StyleInspectorMenu; @@ -67,209 +66,195 @@ StyleInspectorMenu.prototype = { */ show: function (event) { try { - // In the sidebar we do not have this.styleDocument.popupNode - // so we need to save the node ourselves. - this.styleDocument.popupNode = event.explicitOriginalTarget; - this.styleWindow.focus(); - this._menupopup.openPopupAtScreen(event.screenX, event.screenY, true); + this._openMenu({ + target: event.explicitOriginalTarget, + screenX: event.screenX, + screenY: event.screenY, + }); } catch (e) { console.error(e); } }, - _createContextMenu: function () { - this._menupopup = this.styleDocument.createElementNS(XUL_NS, "menupopup"); - this._menupopup.addEventListener("popupshowing", this._updateMenuItems); - this._menupopup.id = "computed-view-context-menu"; + _openMenu: function ({ target, screenX = 0, screenY = 0 } = { }) { + // In the sidebar we do not have this.styleDocument.popupNode + // so we need to save the node ourselves. + this.styleDocument.popupNode = target; + this.styleWindow.focus(); - let parentDocument = this.styleWindow.parent.document; - let popupset = parentDocument.documentElement.querySelector("popupset"); - if (!popupset) { - popupset = parentDocument.createElementNS(XUL_NS, "popupset"); - parentDocument.documentElement.appendChild(popupset); - } - popupset.appendChild(this._menupopup); + let menu = new Menu(); - this._createContextMenuItems(); - }, - /** - * Create all context menu items - */ - _createContextMenuItems: function () { - this.menuitemCopy = this._createContextMenuItem({ - label: "styleinspector.contextmenu.copy", - accesskey: "styleinspector.contextmenu.copy.accessKey", - command: this._onCopy + let menuitemCopy = new MenuItem({ + label: _strings.GetStringFromName("styleinspector.contextmenu.copy"), + accesskey: _strings.GetStringFromName("styleinspector.contextmenu.copy.accessKey"), + click: () => { + this._onCopy(); + }, + disabled: !this._hasTextSelected(), }); - - this.menuitemCopyLocation = this._createContextMenuItem({ - label: "styleinspector.contextmenu.copyLocation", - command: this._onCopyLocation + let menuitemCopyLocation = new MenuItem({ + label: _strings.GetStringFromName("styleinspector.contextmenu.copyLocation"), + click: () => { + this._onCopyLocation(); + }, + visible: false, }); - - this.menuitemCopyRule = this._createContextMenuItem({ - label: "styleinspector.contextmenu.copyRule", - command: this._onCopyRule + let menuitemCopyRule = new MenuItem({ + label: _strings.GetStringFromName("styleinspector.contextmenu.copyRule"), + click: () => { + this._onCopyRule(); + }, + visible: this.isRuleView, }); - - this.menuitemCopyColor = this._createContextMenuItem({ - label: "styleinspector.contextmenu.copyColor", - accesskey: "styleinspector.contextmenu.copyColor.accessKey", - command: this._onCopyColor + let copyColorAccessKey = "styleinspector.contextmenu.copyColor.accessKey"; + let menuitemCopyColor = new MenuItem({ + label: _strings.GetStringFromName("styleinspector.contextmenu.copyColor"), + accesskey: _strings.GetStringFromName(copyColorAccessKey), + click: () => { + this._onCopyColor(); + }, + visible: this._isColorPopup(), }); - - this.menuitemCopyUrl = this._createContextMenuItem({ - label: "styleinspector.contextmenu.copyUrl", - accesskey: "styleinspector.contextmenu.copyUrl.accessKey", - command: this._onCopyUrl + let copyUrlAccessKey = "styleinspector.contextmenu.copyUrl.accessKey"; + let menuitemCopyUrl = new MenuItem({ + label: _strings.GetStringFromName("styleinspector.contextmenu.copyUrl"), + accesskey: _strings.GetStringFromName(copyUrlAccessKey), + click: () => { + this._onCopyUrl(); + }, + visible: this._isImageUrl(), }); - - this.menuitemCopyImageDataUrl = this._createContextMenuItem({ - label: "styleinspector.contextmenu.copyImageDataUrl", - accesskey: "styleinspector.contextmenu.copyImageDataUrl.accessKey", - command: this._onCopyImageDataUrl + let copyImageAccessKey = "styleinspector.contextmenu.copyImageDataUrl.accessKey"; + let menuitemCopyImageDataUrl = new MenuItem({ + label: _strings.GetStringFromName("styleinspector.contextmenu.copyImageDataUrl"), + accesskey: _strings.GetStringFromName(copyImageAccessKey), + click: () => { + this._onCopyImageDataUrl(); + }, + visible: this._isImageUrl(), }); - - this.menuitemCopyPropertyDeclaration = this._createContextMenuItem({ - label: "styleinspector.contextmenu.copyPropertyDeclaration", - command: this._onCopyPropertyDeclaration + let copyPropDeclarationLabel = "styleinspector.contextmenu.copyPropertyDeclaration"; + let menuitemCopyPropertyDeclaration = new MenuItem({ + label: _strings.GetStringFromName(copyPropDeclarationLabel), + click: () => { + this._onCopyPropertyDeclaration(); + }, + visible: false, }); - - this.menuitemCopyPropertyName = this._createContextMenuItem({ - label: "styleinspector.contextmenu.copyPropertyName", - command: this._onCopyPropertyName + let menuitemCopyPropertyName = new MenuItem({ + label: _strings.GetStringFromName("styleinspector.contextmenu.copyPropertyName"), + click: () => { + this._onCopyPropertyName(); + }, + visible: false, }); - - this.menuitemCopyPropertyValue = this._createContextMenuItem({ - label: "styleinspector.contextmenu.copyPropertyValue", - command: this._onCopyPropertyValue + let menuitemCopyPropertyValue = new MenuItem({ + label: _strings.GetStringFromName("styleinspector.contextmenu.copyPropertyValue"), + click: () => { + this._onCopyPropertyValue(); + }, + visible: false, }); - - this.menuitemCopySelector = this._createContextMenuItem({ - label: "styleinspector.contextmenu.copySelector", - command: this._onCopySelector + let menuitemCopySelector = new MenuItem({ + label: _strings.GetStringFromName("styleinspector.contextmenu.copySelector"), + click: () => { + this._onCopySelector(); + }, + visible: false, }); - this._createMenuSeparator(); - - // Select All - this.menuitemSelectAll = this._createContextMenuItem({ - label: "styleinspector.contextmenu.selectAll", - accesskey: "styleinspector.contextmenu.selectAll.accessKey", - command: this._onSelectAll - }); - - this._createMenuSeparator(); - - // Add new rule - this.menuitemAddRule = this._createContextMenuItem({ - label: "styleinspector.contextmenu.addNewRule", - accesskey: "styleinspector.contextmenu.addNewRule.accessKey", - command: this._onAddNewRule - }); - - // Show MDN Docs - this.menuitemShowMdnDocs = this._createContextMenuItem({ - label: "styleinspector.contextmenu.showMdnDocs", - accesskey: "styleinspector.contextmenu.showMdnDocs.accessKey", - command: this._onShowMdnDocs - }); - - // Show Original Sources - this.menuitemSources = this._createContextMenuItem({ - label: "styleinspector.contextmenu.toggleOrigSources", - accesskey: "styleinspector.contextmenu.toggleOrigSources.accessKey", - command: this._onToggleOrigSources, - type: "checkbox" - }); - }, - - /** - * Create a single context menu item based on the provided configuration - * Returns the created menu item element - */ - _createContextMenuItem: function (attributes) { - let ownerDocument = this._menupopup.ownerDocument; - let item = ownerDocument.createElementNS(XUL_NS, "menuitem"); - - item.setAttribute("label", _strings.GetStringFromName(attributes.label)); - if (attributes.accesskey) { - item.setAttribute("accesskey", - _strings.GetStringFromName(attributes.accesskey)); - } - item.addEventListener("command", attributes.command); - - if (attributes.type) { - item.setAttribute("type", attributes.type); - } - - this._menupopup.appendChild(item); - return item; - }, - - _createMenuSeparator: function () { - let ownerDocument = this._menupopup.ownerDocument; - let separator = ownerDocument.createElementNS(XUL_NS, "menuseparator"); - this._menupopup.appendChild(separator); - }, - - /** - * Update the context menu. This means enabling or disabling menuitems as - * appropriate. - */ - _updateMenuItems: function () { - this._updateCopyMenuItems(); - - let showOrig = Services.prefs.getBoolPref(PREF_ORIG_SOURCES); - this.menuitemSources.setAttribute("checked", showOrig); - - let enableMdnDocsTooltip = - Services.prefs.getBoolPref(PREF_ENABLE_MDN_DOCS_TOOLTIP); - this.menuitemShowMdnDocs.hidden = !(enableMdnDocsTooltip && - this._isPropertyName()); - - this.menuitemAddRule.hidden = !this.isRuleView; - this.menuitemAddRule.disabled = !this.isRuleView || - this.inspector.selection.isAnonymousNode(); - }, - - /** - * Display the necessary copy context menu items depending on the clicked - * node and selection in the rule view. - */ - _updateCopyMenuItems: function () { - this.menuitemCopy.disabled = !this._hasTextSelected(); - - this.menuitemCopyColor.hidden = !this._isColorPopup(); - this.menuitemCopyImageDataUrl.hidden = !this._isImageUrl(); - this.menuitemCopyUrl.hidden = !this._isImageUrl(); - this.menuitemCopyRule.hidden = !this.isRuleView; - - this.menuitemCopyLocation.hidden = true; - this.menuitemCopyPropertyDeclaration.hidden = true; - this.menuitemCopyPropertyName.hidden = true; - this.menuitemCopyPropertyValue.hidden = true; - this.menuitemCopySelector.hidden = true; - this._clickedNodeInfo = this._getClickedNodeInfo(); if (this.isRuleView && this._clickedNodeInfo) { switch (this._clickedNodeInfo.type) { case overlays.VIEW_NODE_PROPERTY_TYPE : - this.menuitemCopyPropertyDeclaration.hidden = false; - this.menuitemCopyPropertyName.hidden = false; + menuitemCopyPropertyDeclaration.visible = true; + menuitemCopyPropertyName.visible = true; break; case overlays.VIEW_NODE_VALUE_TYPE : - this.menuitemCopyPropertyDeclaration.hidden = false; - this.menuitemCopyPropertyValue.hidden = false; + menuitemCopyPropertyDeclaration.visible = true; + menuitemCopyPropertyValue.visible = true; break; case overlays.VIEW_NODE_SELECTOR_TYPE : - this.menuitemCopySelector.hidden = false; + menuitemCopySelector.visible = true; break; case overlays.VIEW_NODE_LOCATION_TYPE : - this.menuitemCopyLocation.hidden = false; + menuitemCopyLocation.visible = true; break; } } + + menu.append(menuitemCopy); + menu.append(menuitemCopyLocation); + menu.append(menuitemCopyRule); + menu.append(menuitemCopyColor); + menu.append(menuitemCopyUrl); + menu.append(menuitemCopyImageDataUrl); + menu.append(menuitemCopyPropertyDeclaration); + menu.append(menuitemCopyPropertyName); + menu.append(menuitemCopyPropertyValue); + menu.append(menuitemCopySelector); + + menu.append(new MenuItem({ + type: "separator", + })); + + // Select All + let selectAllAccessKey = "styleinspector.contextmenu.selectAll.accessKey"; + let menuitemSelectAll = new MenuItem({ + label: _strings.GetStringFromName("styleinspector.contextmenu.selectAll"), + accesskey: _strings.GetStringFromName(selectAllAccessKey), + click: () => { + this._onSelectAll(); + }, + }); + menu.append(menuitemSelectAll); + + menu.append(new MenuItem({ + type: "separator", + })); + + // Add new rule + let addRuleAccessKey = "styleinspector.contextmenu.addNewRule.accessKey"; + let menuitemAddRule = new MenuItem({ + label: _strings.GetStringFromName("styleinspector.contextmenu.addNewRule"), + accesskey: _strings.GetStringFromName(addRuleAccessKey), + click: () => { + this._onAddNewRule(); + }, + visible: this.isRuleView, + disabled: !this.isRuleView || + this.inspector.selection.isAnonymousNode(), + }); + menu.append(menuitemAddRule); + + // Show MDN Docs + let mdnDocsAccessKey = "styleinspector.contextmenu.showMdnDocs.accessKey"; + let menuitemShowMdnDocs = new MenuItem({ + label: _strings.GetStringFromName("styleinspector.contextmenu.showMdnDocs"), + accesskey: _strings.GetStringFromName(mdnDocsAccessKey), + click: () => { + this._onShowMdnDocs(); + }, + visible: (Services.prefs.getBoolPref(PREF_ENABLE_MDN_DOCS_TOOLTIP) && + this._isPropertyName()), + }); + menu.append(menuitemShowMdnDocs); + + // Show Original Sources + let sourcesAccessKey = "styleinspector.contextmenu.toggleOrigSources.accessKey"; + let menuitemSources = new MenuItem({ + label: _strings.GetStringFromName("styleinspector.contextmenu.toggleOrigSources"), + accesskey: _strings.GetStringFromName(sourcesAccessKey), + click: () => { + this._onToggleOrigSources(); + }, + type: "checkbox", + checked: Services.prefs.getBoolPref(PREF_ORIG_SOURCES), + }); + menu.append(menuitemSources); + + menu.popup(screenX, screenY, this.inspector._toolbox); + return menu; }, _hasTextSelected: function () { @@ -512,46 +497,11 @@ StyleInspectorMenu.prototype = { }, destroy: function () { - this._removeContextMenuItems(); - - // Destroy the context menu. - this._menupopup.removeEventListener("popupshowing", this._updateMenuItems); - this._menupopup.parentNode.removeChild(this._menupopup); - this._menupopup = null; - this.popupNode = null; this.styleDocument.popupNode = null; this.view = null; this.inspector = null; this.styleDocument = null; this.styleWindow = null; - }, - - _removeContextMenuItems: function () { - this._removeContextMenuItem("menuitemAddRule", this._onAddNewRule); - this._removeContextMenuItem("menuitemCopy", this._onCopy); - this._removeContextMenuItem("menuitemCopyColor", this._onCopyColor); - this._removeContextMenuItem("menuitemCopyImageDataUrl", - this._onCopyImageDataUrl); - this._removeContextMenuItem("menuitemCopyLocation", this._onCopyLocation); - this._removeContextMenuItem("menuitemCopyPropertyDeclaration", - this._onCopyPropertyDeclaration); - this._removeContextMenuItem("menuitemCopyPropertyName", - this._onCopyPropertyName); - this._removeContextMenuItem("menuitemCopyPropertyValue", - this._onCopyPropertyValue); - this._removeContextMenuItem("menuitemCopyRule", this._onCopyRule); - this._removeContextMenuItem("menuitemCopySelector", this._onCopySelector); - this._removeContextMenuItem("menuitemCopyUrl", this._onCopyUrl); - this._removeContextMenuItem("menuitemSelectAll", this._onSelectAll); - this._removeContextMenuItem("menuitemShowMdnDocs", this._onShowMdnDocs); - this._removeContextMenuItem("menuitemSources", this._onToggleOrigSources); - }, - - _removeContextMenuItem: function (itemName, callback) { - if (this[itemName]) { - this[itemName].removeEventListener("command", callback); - this[itemName] = null; - } } }; diff --git a/devtools/client/inspector/shared/test/browser_styleinspector_context-menu-copy-color_02.js b/devtools/client/inspector/shared/test/browser_styleinspector_context-menu-copy-color_02.js index 06ad79f61b43..f1a04ee0df94 100644 --- a/devtools/client/inspector/shared/test/browser_styleinspector_context-menu-copy-color_02.js +++ b/devtools/client/inspector/shared/test/browser_styleinspector_context-menu-copy-color_02.js @@ -30,20 +30,19 @@ function* testCopyToClipboard(inspector, view) { yield selectNode("div", inspector); - let win = view.styleWindow; let element = getRuleViewProperty(view, "div", "color").valueSpan .querySelector(".ruleview-colorswatch"); - let popup = once(view._contextmenu._menupopup, "popupshown"); - EventUtils.synthesizeMouseAtCenter(element, {button: 2, type: "contextmenu"}, - win); - yield popup; + let allMenuItems = openStyleContextMenuAndGetAllItems(view, element); + let menuitemCopyColor = allMenuItems.find(item => item.label === + _STRINGS.GetStringFromName("styleinspector.contextmenu.copyColor")); - ok(!view._contextmenu.menuitemCopyColor.hidden, "Copy color is visible"); + ok(menuitemCopyColor.visible, "Copy color is visible"); - yield waitForClipboard(() => view._contextmenu.menuitemCopyColor.click(), + yield waitForClipboard(() => menuitemCopyColor.click(), "#123ABC"); - view._contextmenu._menupopup.hidePopup(); + + EventUtils.synthesizeKey("VK_ESCAPE", { }); } function* testManualEdit(inspector, view) { diff --git a/devtools/client/inspector/shared/test/browser_styleinspector_context-menu-copy-urls.js b/devtools/client/inspector/shared/test/browser_styleinspector_context-menu-copy-urls.js index 508359801afe..c7c44cd6f726 100644 --- a/devtools/client/inspector/shared/test/browser_styleinspector_context-menu-copy-urls.js +++ b/devtools/client/inspector/shared/test/browser_styleinspector_context-menu-copy-urls.js @@ -77,42 +77,31 @@ function* testCopyUrlToClipboard({view, inspector}, type, selector, expected) { ok(imageLink, "Background-image link element found"); info("Simulate right click on the background-image URL"); - let popup = once(view._contextmenu._menupopup, "popupshown"); - - // Cannot rely on synthesizeMouseAtCenter here. The image URL can be displayed - // on several lines. A click simulated at the exact center may click between - // the lines and miss the target. Instead, using the top-left corner of first - // client rect, with an offset of 2 pixels. - let rect = imageLink.getClientRects()[0]; - let x = rect.left + 2; - let y = rect.top + 2; - - EventUtils.synthesizeMouseAtPoint(x, y, { - button: 2, - type: "contextmenu" - }, getViewWindow(view)); - yield popup; + let allMenuItems = openStyleContextMenuAndGetAllItems(view, imageLink); + let menuitemCopyUrl = allMenuItems.find(item => item.label === + _STRINGS.GetStringFromName("styleinspector.contextmenu.copyUrl")); + let menuitemCopyImageDataUrl = allMenuItems.find(item => item.label === + _STRINGS.GetStringFromName("styleinspector.contextmenu.copyImageDataUrl")); info("Context menu is displayed"); - ok(!view._contextmenu.menuitemCopyUrl.hidden, + ok(menuitemCopyUrl.visible, "\"Copy URL\" menu entry is displayed"); - ok(!view._contextmenu.menuitemCopyImageDataUrl.hidden, + ok(menuitemCopyImageDataUrl.visible, "\"Copy Image Data-URL\" menu entry is displayed"); if (type == "data-uri") { info("Click Copy Data URI and wait for clipboard"); yield waitForClipboard(() => { - return view._contextmenu.menuitemCopyImageDataUrl.click(); + return menuitemCopyImageDataUrl.click(); }, expected); } else { info("Click Copy URL and wait for clipboard"); yield waitForClipboard(() => { - return view._contextmenu.menuitemCopyUrl.click(); + return menuitemCopyUrl.click(); }, expected); } info("Hide context menu"); - view._contextmenu._menupopup.hidePopup(); } function getBackgroundImageProperty(view, selector) { @@ -122,11 +111,3 @@ function getBackgroundImageProperty(view, selector) { } return getComputedViewProperty(view, "background-image"); } - -/** - * Function that returns the window for a given view. - */ -function getViewWindow(view) { - let viewDocument = view.styleDocument ? view.styleDocument : view.doc; - return viewDocument.defaultView; -} diff --git a/devtools/client/inspector/shared/test/head.js b/devtools/client/inspector/shared/test/head.js index d4f6bd606a09..ca99d2bf0c95 100644 --- a/devtools/client/inspector/shared/test/head.js +++ b/devtools/client/inspector/shared/test/head.js @@ -21,6 +21,8 @@ const TEST_URL_ROOT_SSL = "https://example.com/browser/devtools/client/inspector/shared/test/"; const ROOT_TEST_DIR = getRootDirectory(gTestPath); const FRAME_SCRIPT_URL = ROOT_TEST_DIR + "doc_frame_script.js"; +const _STRINGS = Services.strings.createBundle( + "chrome://devtools-shared/locale/styleinspector.properties"); // Clean-up all prefs that might have been changed during a test run // (safer here because if the test fails, then the pref is never reverted) @@ -534,3 +536,23 @@ function getComputedViewPropertyValue(view, name, propertyName) { return getComputedViewProperty(view, name, propertyName) .valueSpan.textContent; } + +/** + * Open the style editor context menu and return all of it's items in a flat array + * @param {CssRuleView} view + * The instance of the rule-view panel + * @return An array of MenuItems + */ +function openStyleContextMenuAndGetAllItems(view, target) { + let menu = view._contextmenu._openMenu({target: target}); + + // Flatten all menu items into a single array to make searching through it easier + let allItems = [].concat.apply([], menu.items.map(function addItem(item) { + if (item.submenu) { + return addItem(item.submenu.items); + } + return item; + })); + + return allItems; +} diff --git a/devtools/client/shared/components/test/mochitest/chrome.ini b/devtools/client/shared/components/test/mochitest/chrome.ini index 57b38c151516..a2179551cdd8 100644 --- a/devtools/client/shared/components/test/mochitest/chrome.ini +++ b/devtools/client/shared/components/test/mochitest/chrome.ini @@ -10,6 +10,8 @@ support-files = [test_reps_date-time.html] [test_reps_function.html] [test_reps_grip.html] +[test_reps_null.html] +[test_reps_object-with-text.html] [test_reps_object-with-url.html] [test_reps_stylesheet.html] [test_reps_undefined.html] diff --git a/devtools/client/shared/components/test/mochitest/test_reps_null.html b/devtools/client/shared/components/test/mochitest/test_reps_null.html new file mode 100644 index 000000000000..a237b9317ee1 --- /dev/null +++ b/devtools/client/shared/components/test/mochitest/test_reps_null.html @@ -0,0 +1,42 @@ + + + + + + + Rep test - Null + + + + +
+
+
+
+ + diff --git a/devtools/client/shared/components/test/mochitest/test_reps_object-with-text.html b/devtools/client/shared/components/test/mochitest/test_reps_object-with-text.html new file mode 100644 index 000000000000..f22402f94108 --- /dev/null +++ b/devtools/client/shared/components/test/mochitest/test_reps_object-with-text.html @@ -0,0 +1,52 @@ + + + + + + + Rep test - ObjectWithText + + + + +
+
+
+
+ + diff --git a/devtools/client/shared/key-shortcuts.js b/devtools/client/shared/key-shortcuts.js index d37f03c2bfd9..a6a457462dd8 100644 --- a/devtools/client/shared/key-shortcuts.js +++ b/devtools/client/shared/key-shortcuts.js @@ -122,7 +122,8 @@ KeyShortcuts.parseElectronKey = function (window, str) { } else if (mod === "Shift") { shortcut.shift = true; } else { - throw new Error("Unsupported modifier: " + mod); + console.error("Unsupported modifier:", mod, "from key:", str); + return null; } } @@ -142,7 +143,8 @@ KeyShortcuts.parseElectronKey = function (window, str) { // Used only to stringify the shortcut shortcut.keyCodeString = key; } else { - throw new Error("Unsupported key: " + key); + console.error("Unsupported key:", key); + return null; } return shortcut; @@ -220,6 +222,10 @@ KeyShortcuts.prototype = { } if (!this.keys.has(key)) { let shortcut = KeyShortcuts.parseElectronKey(this.window, key); + // The key string is wrong and we were unable to compute the key shortcut + if (!shortcut) { + return; + } this.keys.set(key, shortcut); } this.eventEmitter.on(key, listener); diff --git a/devtools/client/shared/test/browser_key_shortcuts.js b/devtools/client/shared/test/browser_key_shortcuts.js index caf63299e53c..975bb9b57e9e 100644 --- a/devtools/client/shared/test/browser_key_shortcuts.js +++ b/devtools/client/shared/test/browser_key_shortcuts.js @@ -18,6 +18,7 @@ add_task(function* () { yield testAltModifier(shortcuts); yield testCommandOrControlModifier(shortcuts); yield testCtrlModifier(shortcuts); + yield testInvalidShortcutString(shortcuts); shortcuts.destroy(); yield testTarget(); @@ -362,3 +363,13 @@ function testTarget() { shortcuts.destroy(); } + +function testInvalidShortcutString(shortcuts) { + info("Test wrong shortcut string"); + + let shortcut = KeyShortcuts.parseElectronKey(window, "Cmmd+F"); + ok(!shortcut, "Passing a invalid shortcut string should return a null object"); + + shortcuts.on("Cmmd+F", function () {}); + ok(true, "on() shouldn't throw when passing invalid shortcut string"); +} diff --git a/devtools/client/shared/widgets/filter-widget.css b/devtools/client/shared/widgets/filter-widget.css index 99dcc3e4d4d0..6d7624f661ac 100644 --- a/devtools/client/shared/widgets/filter-widget.css +++ b/devtools/client/shared/widgets/filter-widget.css @@ -200,7 +200,7 @@ input { .remove-button { width: 16px; height: 16px; - background: url(chrome://devtools/skin/images/close@2x.png); + background: url(chrome://devtools/skin/images/close.svg); background-size: cover; font-size: 0; border: none; diff --git a/devtools/client/styleeditor/StyleEditorUI.jsm b/devtools/client/styleeditor/StyleEditorUI.jsm index 5629a9fc7e17..be6151d1b27e 100644 --- a/devtools/client/styleeditor/StyleEditorUI.jsm +++ b/devtools/client/styleeditor/StyleEditorUI.jsm @@ -616,19 +616,19 @@ StyleEditorUI.prototype = { return; } - let href = csscoverage.sheetToUrl(showEditor.styleSheet); - let reportData = yield usage.createEditorReport(href); + let sheet = showEditor.styleSheet; + let {reports} = yield usage.createEditorReportForSheet(sheet); showEditor.removeAllUnusedRegions(); - if (reportData.reports.length > 0) { + if (reports.length > 0) { // Only apply if this file isn't compressed. We detect a // compressed file if there are more rules than lines. let editorText = showEditor.sourceEditor.getText(); let lineCount = editorText.split("\n").length; let ruleCount = showEditor.styleSheet.ruleCount; if (lineCount >= ruleCount) { - showEditor.addUnusedRegions(reportData.reports); + showEditor.addUnusedRegions(reports); } else { this.emit("error", { key: "error-compressed", level: "info" }); } diff --git a/devtools/client/themes/storage.css b/devtools/client/themes/storage.css index 118b32204279..dcc5a7923708 100644 --- a/devtools/client/themes/storage.css +++ b/devtools/client/themes/storage.css @@ -34,7 +34,8 @@ /* Responsive sidebar */ @media (max-width: 700px) { - #storage-tree { + #storage-tree, + #storage-sidebar { max-width: 100%; } diff --git a/devtools/client/webconsole/jsterm.js b/devtools/client/webconsole/jsterm.js index 8f79d8643860..a507c9c720c4 100644 --- a/devtools/client/webconsole/jsterm.js +++ b/devtools/client/webconsole/jsterm.js @@ -316,7 +316,7 @@ JSTerm.prototype = { errorDocLink = this.hud.document.createElementNS(XHTML_NS, "a"); errorDocLink.className = "learn-more-link webconsole-learn-more-link"; errorDocLink.textContent = `[${l10n.getStr("webConsoleMoreInfoLabel")}]`; - errorDocLink.title = errorDocURL; + errorDocLink.title = errorDocURL.split("?")[0]; errorDocLink.href = "#"; errorDocLink.draggable = false; errorDocLink.addEventListener("click", () => { diff --git a/devtools/client/webconsole/new-console-output/components/message-types/console-api-call.js b/devtools/client/webconsole/new-console-output/components/message-types/console-api-call.js index ecb44f46c88d..f50463e6a01f 100644 --- a/devtools/client/webconsole/new-console-output/components/message-types/console-api-call.js +++ b/devtools/client/webconsole/new-console-output/components/message-types/console-api-call.js @@ -25,7 +25,7 @@ function ConsoleApiCall(props) { const { message } = props; const messageBody = dom.span({className: "message-body devtools-monospace"}, - formatTextContent(message.data.arguments)); + formatTextContent(message.data)); const icon = MessageIcon({severity: message.severity}); const repeat = MessageRepeat({repeat: message.repeat}); const children = [ @@ -53,8 +53,13 @@ function ConsoleApiCall(props) { ); } -function formatTextContent(args) { - return args.map(function (arg, i, arr) { +function formatTextContent(data) { + return data.arguments.map(function (arg, i, arr) { + if (data.counter) { + let {label, count} = data.counter; + arg = `${label}: ${count}`; + } + const str = dom.span({className: "console-string"}, arg); if (i < arr.length - 1) { return [str, " "]; diff --git a/devtools/client/webconsole/new-console-output/test/components/test_console-api-call.html b/devtools/client/webconsole/new-console-output/test/components/test_console-api-call.html index e1db5b5200bd..12f0acc67178 100644 --- a/devtools/client/webconsole/new-console-output/test/components/test_console-api-call.html +++ b/devtools/client/webconsole/new-console-output/test/components/test_console-api-call.html @@ -20,14 +20,42 @@ window.onload = Task.async(function* () { const message = prepareMessage(packet); const rendered = renderComponent(ConsoleApiCall, {message}); - const queryPath = "div.message.cm-s-mozilla span span.message-flex-body span.message-body.devtools-monospace"; - const messageBody = rendered.querySelectorAll(queryPath); - const consoleStringNodes = messageBody[0].querySelectorAll("span.console-string"); + const messageBody = getMessageBody(rendered); + const consoleStringNodes = getConsoleStringNodes(messageBody); is(consoleStringNodes.length, 2, "ConsoleApiCall outputs expected HTML structure"); - is(messageBody[0].textContent, "foobar test", "ConsoleApiCall outputs expected text"); + is(messageBody.textContent, "foobar test", "ConsoleApiCall outputs expected text"); + + for (let i = 0; i < 3; i++) { + const countPacket = yield getPacket("console.count('bar')", "consoleAPICall"); + const countMessage = prepareMessage(countPacket); + const countRendered = renderComponent(ConsoleApiCall, {message: countMessage}); + testConsoleCountRenderedElement(countRendered, `bar: ${i + 1}`); + } SimpleTest.finish() }); + +function getMessageBody(renderedComponent) { + const queryPath = "div.message.cm-s-mozilla span span.message-flex-body " + + "span.message-body.devtools-monospace"; + return renderedComponent.querySelector(queryPath); +} + +function getConsoleStringNodes(messageBody) { + return messageBody.querySelectorAll("span.console-string"); +} + +function testConsoleCountRenderedElement(renderedComponent, expectedTextContent) { + info("Testing console.count rendered element"); + + const messageBody = getMessageBody(renderedComponent); + const consoleStringNodes = getConsoleStringNodes(messageBody); + + is(consoleStringNodes.length, 1, + "console.count rendered element has the expected HTML structure"); + is(messageBody.textContent, expectedTextContent, + "console.count rendered element has the expected text content"); +} diff --git a/devtools/client/webconsole/test/browser_webconsole_allow_mixedcontent_securityerrors.js b/devtools/client/webconsole/test/browser_webconsole_allow_mixedcontent_securityerrors.js index bb49398cf66c..07f6372d0193 100644 --- a/devtools/client/webconsole/test/browser_webconsole_allow_mixedcontent_securityerrors.js +++ b/devtools/client/webconsole/test/browser_webconsole_allow_mixedcontent_securityerrors.js @@ -15,8 +15,8 @@ const TEST_URI = "https://example.com/browser/devtools/client/webconsole/" + "test/test-mixedcontent-securityerrors.html"; -const LEARN_MORE_URI = "https://developer.mozilla.org/docs/Security/" + - "MixedContent"; +const LEARN_MORE_URI = "https://developer.mozilla.org/docs/Web/Security/" + + "Mixed_content" + DOCS_GA_PARAMS; add_task(function* () { yield pushPrefEnv(); diff --git a/devtools/client/webconsole/test/browser_webconsole_block_mixedcontent_securityerrors.js b/devtools/client/webconsole/test/browser_webconsole_block_mixedcontent_securityerrors.js index b402236c5ede..6d9f4e0c0af7 100644 --- a/devtools/client/webconsole/test/browser_webconsole_block_mixedcontent_securityerrors.js +++ b/devtools/client/webconsole/test/browser_webconsole_block_mixedcontent_securityerrors.js @@ -18,8 +18,8 @@ const TEST_URI = "https://example.com/browser/devtools/client/webconsole/" + "test/test-mixedcontent-securityerrors.html"; -const LEARN_MORE_URI = "https://developer.mozilla.org/docs/Security/" + - "MixedContent"; +const LEARN_MORE_URI = "https://developer.mozilla.org/docs/Web/Security/" + + "Mixed_content" + DOCS_GA_PARAMS; add_task(function* () { yield pushPrefEnv(); diff --git a/devtools/client/webconsole/test/browser_webconsole_bug_737873_mixedcontent.js b/devtools/client/webconsole/test/browser_webconsole_bug_737873_mixedcontent.js index 6ebf5d92e3cb..a6ce1d83a041 100644 --- a/devtools/client/webconsole/test/browser_webconsole_bug_737873_mixedcontent.js +++ b/devtools/client/webconsole/test/browser_webconsole_bug_737873_mixedcontent.js @@ -10,8 +10,8 @@ const TEST_URI = "data:text/html;charset=utf8,Web Console mixed content test"; const TEST_HTTPS_URI = "https://example.com/browser/devtools/client/" + "webconsole/test/test-bug-737873-mixedcontent.html"; -const LEARN_MORE_URI = "https://developer.mozilla.org/docs/Security/" + - "MixedContent"; +const LEARN_MORE_URI = "https://developer.mozilla.org/docs/Web/Security/" + + "Mixed_content"; add_task(function* () { Services.prefs.setBoolPref("security.mixed_content.block_display_content", diff --git a/devtools/client/webconsole/test/browser_webconsole_bug_762593_insecure_passwords_web_console_warning.js b/devtools/client/webconsole/test/browser_webconsole_bug_762593_insecure_passwords_web_console_warning.js index 81669e3d71dc..00a620fc8992 100644 --- a/devtools/client/webconsole/test/browser_webconsole_bug_762593_insecure_passwords_web_console_warning.js +++ b/devtools/client/webconsole/test/browser_webconsole_bug_762593_insecure_passwords_web_console_warning.js @@ -19,8 +19,8 @@ const INSECURE_FORM_ACTION_MSG = "Password fields present in a form with an " + const INSECURE_IFRAME_MSG = "Password fields present on an insecure " + "(http://) iframe. This is a security risk that allows " + "user login credentials to be stolen."; -const INSECURE_PASSWORDS_URI = "https://developer.mozilla.org/docs/Security/" + - "InsecurePasswords"; +const INSECURE_PASSWORDS_URI = "https://developer.mozilla.org/docs/Web/" + + "Security/Insecure_passwords" + DOCS_GA_PARAMS; add_task(function* () { yield loadTab(TEST_URI); diff --git a/devtools/client/webconsole/test/browser_webconsole_hpkp_invalid-headers.js b/devtools/client/webconsole/test/browser_webconsole_hpkp_invalid-headers.js index dd77574b345c..3ee33669de4b 100644 --- a/devtools/client/webconsole/test/browser_webconsole_hpkp_invalid-headers.js +++ b/devtools/client/webconsole/test/browser_webconsole_hpkp_invalid-headers.js @@ -13,7 +13,7 @@ const TEST_URI = "data:text/html;charset=utf-8,Web Console HPKP invalid " + const SJS_URL = "https://example.com/browser/devtools/client/webconsole/" + "test/test_hpkp-invalid-headers.sjs"; const LEARN_MORE_URI = "https://developer.mozilla.org/docs/Web/Security/" + - "Public_Key_Pinning"; + "Public_Key_Pinning" + DOCS_GA_PARAMS; const NON_BUILTIN_ROOT_PREF = "security.cert_pinning.process_headers_from_" + "non_builtin_roots"; diff --git a/devtools/client/webconsole/test/browser_webconsole_hsts_invalid-headers.js b/devtools/client/webconsole/test/browser_webconsole_hsts_invalid-headers.js index fb125621bb7a..19cedefdb2c6 100644 --- a/devtools/client/webconsole/test/browser_webconsole_hsts_invalid-headers.js +++ b/devtools/client/webconsole/test/browser_webconsole_hsts_invalid-headers.js @@ -12,8 +12,8 @@ const TEST_URI = "data:text/html;charset=utf-8,Web Console HSTS invalid " + "header test"; const SJS_URL = "https://example.com/browser/devtools/client/webconsole/" + "test/test_hsts-invalid-headers.sjs"; -const LEARN_MORE_URI = "https://developer.mozilla.org/docs/Security/" + - "HTTP_Strict_Transport_Security"; +const LEARN_MORE_URI = "https://developer.mozilla.org/docs/Web/Security/" + + "HTTP_strict_transport_security" + DOCS_GA_PARAMS; add_task(function* () { yield loadTab(TEST_URI); diff --git a/devtools/client/webconsole/test/browser_webconsole_jsterm.js b/devtools/client/webconsole/test/browser_webconsole_jsterm.js index 5afa143d59ad..a299d958f1a1 100644 --- a/devtools/client/webconsole/test/browser_webconsole_jsterm.js +++ b/devtools/client/webconsole/test/browser_webconsole_jsterm.js @@ -180,13 +180,13 @@ function* testJSTerm(hud) { }; for (let errorMessageName of Object.keys(ErrorDocStatements)) { - let url = ErrorDocs.GetURL(errorMessageName); + let title = ErrorDocs.GetURL({ errorMessageName }).split("?")[0]; jsterm.clearOutput(); yield jsterm.execute(ErrorDocStatements[errorMessageName]); yield checkResult((node) => { - return node.parentNode.getElementsByTagName("a")[0].title == url; - }, `error links to ${url}`); + return node.parentNode.getElementsByTagName("a")[0].title == title; + }, `error links to ${title}`); } // Ensure that dom errors, with error numbers outside of the range diff --git a/devtools/client/webconsole/test/browser_webconsole_script_errordoc_urls.js b/devtools/client/webconsole/test/browser_webconsole_script_errordoc_urls.js index a709c37ebeae..779d80376b5d 100644 --- a/devtools/client/webconsole/test/browser_webconsole_script_errordoc_urls.js +++ b/devtools/client/webconsole/test/browser_webconsole_script_errordoc_urls.js @@ -54,7 +54,7 @@ function* testScriptError(hud, testData) { }); // grab the most current error doc URL - let url = ErrorDocs.GetURL(testData.jsmsg); + let url = ErrorDocs.GetURL({ errorMessageName: testData.jsmsg }); let hrefs = {}; for (let link of hud.jsterm.outputNode.querySelectorAll("a")) { diff --git a/devtools/client/webconsole/test/browser_webconsole_trackingprotection_errors.js b/devtools/client/webconsole/test/browser_webconsole_trackingprotection_errors.js index e87c4d10ed9b..eafeee18e3d1 100644 --- a/devtools/client/webconsole/test/browser_webconsole_trackingprotection_errors.js +++ b/devtools/client/webconsole/test/browser_webconsole_trackingprotection_errors.js @@ -8,9 +8,12 @@ "use strict"; -const TEST_URI = "http://tracking.example.org/browser/devtools/client/webconsole/test/test-trackingprotection-securityerrors.html"; -const LEARN_MORE_URI = "https://developer.mozilla.org/Firefox/Privacy/Tracking_Protection"; +const TEST_URI = "http://tracking.example.org/browser/devtools/client/" + + "webconsole/test/test-trackingprotection-securityerrors.html"; +const LEARN_MORE_URI = "https://developer.mozilla.org/Firefox/Privacy/" + + "Tracking_Protection" + DOCS_GA_PARAMS; const PREF = "privacy.trackingprotection.enabled"; + const {UrlClassifierTestUtils} = Cu.import("resource://testing-common/UrlClassifierTestUtils.jsm", {}); registerCleanupFunction(function () { @@ -31,7 +34,8 @@ add_task(function* testMessagesAppear() { messages: [ { name: "Was blocked because tracking protection is enabled", - text: "The resource at \u201chttp://tracking.example.com/\u201d was blocked because tracking protection is enabled", + text: "The resource at \u201chttp://tracking.example.com/\u201d was " + + "blocked because tracking protection is enabled", category: CATEGORY_SECURITY, severity: SEVERITY_WARNING, objects: true, diff --git a/devtools/client/webconsole/test/head.js b/devtools/client/webconsole/test/head.js index e50f8ab8e69b..3c6f17362248 100644 --- a/devtools/client/webconsole/test/head.js +++ b/devtools/client/webconsole/test/head.js @@ -41,6 +41,10 @@ const WEBCONSOLE_STRINGS_URI = "chrome://devtools/locale/" + "webconsole.properties"; var WCUL10n = new WebConsoleUtils.L10n(WEBCONSOLE_STRINGS_URI); +const DOCS_GA_PARAMS = "?utm_source=mozilla" + + "&utm_medium=firefox-console-errors" + + "&utm_campaign=default"; + DevToolsUtils.testing = true; function loadTab(url) { diff --git a/devtools/client/webconsole/webconsole.js b/devtools/client/webconsole/webconsole.js index 872195449c4f..5ca93e58e388 100644 --- a/devtools/client/webconsole/webconsole.js +++ b/devtools/client/webconsole/webconsole.js @@ -44,17 +44,7 @@ var l10n = new WebConsoleUtils.L10n(STRINGS_URI); const XHTML_NS = "http://www.w3.org/1999/xhtml"; -const MIXED_CONTENT_LEARN_MORE = "https://developer.mozilla.org/docs/Security/MixedContent"; - -const TRACKING_PROTECTION_LEARN_MORE = "https://developer.mozilla.org/Firefox/Privacy/Tracking_Protection"; - -const INSECURE_PASSWORDS_LEARN_MORE = "https://developer.mozilla.org/docs/Security/InsecurePasswords"; - -const PUBLIC_KEY_PINS_LEARN_MORE = "https://developer.mozilla.org/docs/Web/Security/Public_Key_Pinning"; - -const STRICT_TRANSPORT_SECURITY_LEARN_MORE = "https://developer.mozilla.org/docs/Security/HTTP_Strict_Transport_Security"; - -const WEAK_SIGNATURE_ALGORITHM_LEARN_MORE = "https://developer.mozilla.org/docs/Security/Weak_Signature_Algorithm"; +const MIXED_CONTENT_LEARN_MORE = "https://developer.mozilla.org/docs/Web/Security/Mixed_content"; const IGNORED_SOURCE_URLS = ["debugger eval code"]; @@ -1487,7 +1477,9 @@ WebConsoleFrame.prototype = { let msgBody = node.getElementsByClassName("message-body")[0]; // Add the more info link node to messages that belong to certain categories - this.addMoreInfoLink(msgBody, scriptError); + if (scriptError.exceptionDocURL) { + this.addLearnMoreWarningNode(msgBody, scriptError.exceptionDocURL); + } // Collect telemetry data regarding JavaScript errors this._telemetry.logKeyed("DEVTOOLS_JAVASCRIPT_ERROR_DISPLAYED", @@ -1667,48 +1659,6 @@ WebConsoleFrame.prototype = { }); }, - /** - * Adds a more info link node to messages based on the nsIScriptError object - * that we need to report to the console - * - * @param node - * The node to which we will be adding the more info link node - * @param scriptError - * The script error object that we are reporting to the console - */ - addMoreInfoLink: function (node, scriptError) { - let url; - switch (scriptError.category) { - case "Insecure Password Field": - url = INSECURE_PASSWORDS_LEARN_MORE; - break; - case "Mixed Content Message": - case "Mixed Content Blocker": - url = MIXED_CONTENT_LEARN_MORE; - break; - case "Invalid HPKP Headers": - url = PUBLIC_KEY_PINS_LEARN_MORE; - break; - case "Invalid HSTS Headers": - url = STRICT_TRANSPORT_SECURITY_LEARN_MORE; - break; - case "SHA-1 Signature": - url = WEAK_SIGNATURE_ALGORITHM_LEARN_MORE; - break; - case "Tracking Protection": - url = TRACKING_PROTECTION_LEARN_MORE; - break; - default: - // If all else fails check for an error doc URL. - url = ErrorDocs.GetURL(scriptError.errorMessageName); - break; - } - - if (url) { - this.addLearnMoreWarningNode(node, url); - } - }, - /* * Appends a clickable warning node to the node passed * as a parameter to the function. When a user clicks on the appended @@ -1725,7 +1675,7 @@ WebConsoleFrame.prototype = { let moreInfoLabel = "[" + l10n.getStr("webConsoleMoreInfoLabel") + "]"; let warningNode = this.document.createElementNS(XHTML_NS, "a"); - warningNode.title = url; + warningNode.title = url.split("?")[0]; warningNode.href = url; warningNode.draggable = false; warningNode.textContent = moreInfoLabel; diff --git a/devtools/server/actors/csscoverage.js b/devtools/server/actors/csscoverage.js index c5a5da21e4d3..2f700656f7e6 100644 --- a/devtools/server/actors/csscoverage.js +++ b/devtools/server/actors/csscoverage.js @@ -4,14 +4,13 @@ "use strict"; -const { Cc, Ci, Cu } = require("chrome"); +const { Cc, Ci } = require("chrome"); const Services = require("Services"); const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm"); const events = require("sdk/event/core"); const protocol = require("devtools/shared/protocol"); -const { custom } = protocol; const { cssUsageSpec } = require("devtools/shared/specs/csscoverage"); loader.lazyGetter(this, "DOMUtils", () => { @@ -137,8 +136,7 @@ var CSSUsageActor = protocol.ActorClassWithSpec(cssUsageSpec, { // If we're not starting by reloading the page, then pretend that onload // has just happened. this._onTabLoad(this._tabActor.window.document); - } - else { + } else { this._tabActor.window.location.reload(); } @@ -295,8 +293,7 @@ var CSSUsageActor = protocol.ActorClassWithSpec(cssUsageSpec, { ruleData.preLoadOn.add(url); } } - } - catch (ex) { + } catch (ex) { ruleData.isError = true; } } @@ -342,6 +339,18 @@ var CSSUsageActor = protocol.ActorClassWithSpec(cssUsageSpec, { return { reports: reports }; }, + /** + * Compute the stylesheet URL and delegate the report creation to createEditorReport. + * See createEditorReport documentation. + * + * @param {StyleSheetActor} stylesheetActor + * the stylesheet actor for which the coverage report should be generated. + */ + createEditorReportForSheet: function (stylesheetActor) { + let url = sheetToUrl(stylesheetActor.rawSheet); + return this.createEditorReport(url); + }, + /** * Returns a JSONable structure designed for the page report which shows * the recommended changes to a page. @@ -416,8 +425,7 @@ var CSSUsageActor = protocol.ActorClassWithSpec(cssUsageSpec, { if (!ruleData.isUsed) { let ruleReport = ruleToRuleReport(rule, ruleData); rules.push(ruleReport); - } - else { + } else { summary.unused++; } } @@ -445,8 +453,7 @@ var CSSUsageActor = protocol.ActorClassWithSpec(cssUsageSpec, { let ruleReport = ruleToRuleReport(rule, ruleData); page.rules.push(ruleReport); summary.preload++; - } - else { + } else { summary.used++; } } @@ -693,13 +700,15 @@ function getTestSelector(selector) { exports.SEL_ALL = [ SEL_EXTERNAL, SEL_FORM, SEL_ELEMENT, SEL_STRUCTURAL, SEL_SEMI, SEL_COMBINING, SEL_MEDIA -].reduce(function (prev, curr) { return prev.concat(curr); }, []); +].reduce(function (prev, curr) { + return prev.concat(curr); +}, []); /** * Find a URL for a given stylesheet - * @param stylesheet {StyleSheet|StyleSheetActor} + * @param {StyleSheet} stylesheet raw stylesheet */ -const sheetToUrl = exports.sheetToUrl = function (stylesheet) { +const sheetToUrl = function (stylesheet) { // For elements if (stylesheet.href) { return stylesheet.href; @@ -713,10 +722,5 @@ const sheetToUrl = exports.sheetToUrl = function (stylesheet) { return getURL(document) + " →