diff --git a/devtools/client/inspector/rules/test/browser_rules_colorpicker-and-image-tooltip_02.js b/devtools/client/inspector/rules/test/browser_rules_colorpicker-and-image-tooltip_02.js index 684c8be33115..7414056b40b7 100644 --- a/devtools/client/inspector/rules/test/browser_rules_colorpicker-and-image-tooltip_02.js +++ b/devtools/client/inspector/rules/test/browser_rules_colorpicker-and-image-tooltip_02.js @@ -43,7 +43,8 @@ function* testColorChangeIsntRevertedWhenOtherTooltipIsShown(ruleView) { }); let spectrum = yield picker.spectrum; - let onModifications = ruleView.once("ruleview-changed"); + + let onModifications = waitForNEvents(ruleView, "ruleview-changed", 2); let onHidden = picker.tooltip.once("hidden"); EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView); yield onHidden; @@ -53,8 +54,7 @@ function* testColorChangeIsntRevertedWhenOtherTooltipIsShown(ruleView) { let value = getRuleViewProperty(ruleView, "body", "background").valueSpan; let url = value.querySelector(".theme-link"); onShown = ruleView.tooltips.previewTooltip.once("shown"); - let anchor = yield isHoverTooltipTarget(ruleView.tooltips.previewTooltip, - url); + let anchor = yield isHoverTooltipTarget(ruleView.tooltips.previewTooltip, url); ruleView.tooltips.previewTooltip.show(anchor); yield onShown; diff --git a/devtools/client/inspector/shared/style-inspector-overlays.js b/devtools/client/inspector/shared/style-inspector-overlays.js index 98fc8f6f009e..d1c0a48111bc 100644 --- a/devtools/client/inspector/shared/style-inspector-overlays.js +++ b/devtools/client/inspector/shared/style-inspector-overlays.js @@ -12,8 +12,14 @@ // - in-content highlighters that appear when hovering over property values // - etc. +const {getTheme} = require("devtools/client/shared/theme"); +const {HTMLTooltip} = require("devtools/client/shared/widgets/HTMLTooltip"); +const { + getImageDimensions, + setImageTooltip, + setBrokenImageTooltip, +} = require("devtools/client/shared/widgets/tooltip/ImageTooltipHelper"); const { - Tooltip, SwatchColorPickerTooltip, SwatchCubicBezierTooltip, CssDocsTooltip, @@ -273,7 +279,9 @@ TooltipsOverlay.prototype = { let panelDoc = this.view.inspector.panelDoc; // Image, fonts, ... preview tooltip - this.previewTooltip = new Tooltip(panelDoc); + this.previewTooltip = new HTMLTooltip(this.view.inspector.toolbox, { + type: "arrow" + }); this.previewTooltip.startTogglingOnHover(this.view.element, this._onPreviewTooltipTargetHover.bind(this)); @@ -395,23 +403,85 @@ TooltipsOverlay.prototype = { let inspector = this.view.inspector; if (type === TOOLTIP_IMAGE_TYPE) { - let dim = Services.prefs.getIntPref(PREF_IMAGE_TOOLTIP_SIZE); - // nodeInfo contains an absolute uri - let uri = nodeInfo.value.url; - yield this.previewTooltip.setRelativeImageContent(uri, - inspector.inspector, dim); + try { + yield this._setImagePreviewTooltip(nodeInfo.value.url); + } catch (e) { + yield setBrokenImageTooltip(this.previewTooltip, this.view.inspector.panelDoc); + } return true; } if (type === TOOLTIP_FONTFAMILY_TYPE) { - yield this.previewTooltip.setFontFamilyContent(nodeInfo.value.value, - inspector.selection.nodeFront); + let font = nodeInfo.value.value; + let nodeFront = inspector.selection.nodeFront; + yield this._setFontPreviewTooltip(font, nodeFront); return true; } return false; }), + /** + * Set the content of the preview tooltip to display an image preview. The image URL can + * be relative, a call will be made to the debuggee to retrieve the image content as an + * imageData URI. + * + * @param {String} imageUrl + * The image url value (may be relative or absolute). + * @return {Promise} A promise that resolves when the preview tooltip content is ready + */ + _setImagePreviewTooltip: Task.async(function* (imageUrl) { + let doc = this.view.inspector.panelDoc; + let maxDim = Services.prefs.getIntPref(PREF_IMAGE_TOOLTIP_SIZE); + + let naturalWidth, naturalHeight; + if (imageUrl.startsWith("data:")) { + // If the imageUrl already is a data-url, save ourselves a round-trip + let size = yield getImageDimensions(doc, imageUrl); + naturalWidth = size.naturalWidth; + naturalHeight = size.naturalHeight; + } else { + let inspectorFront = this.view.inspector.inspector; + let {data, size} = yield inspectorFront.getImageDataFromURL(imageUrl, maxDim); + imageUrl = yield data.string(); + naturalWidth = size.naturalWidth; + naturalHeight = size.naturalHeight; + } + + yield setImageTooltip(this.previewTooltip, doc, imageUrl, + {maxDim, naturalWidth, naturalHeight}); + }), + + /** + * Set the content of the preview tooltip to display a font family preview. + * + * @param {String} font + * The font family value. + * @param {object} nodeFront + * The NodeActor that will used to retrieve the dataURL for the font + * family tooltip contents. + * @return {Promise} A promise that resolves when the preview tooltip content is ready + */ + _setFontPreviewTooltip: Task.async(function* (font, nodeFront) { + if (!font || !nodeFront || typeof nodeFront.getFontFamilyDataURL !== "function") { + throw new Error("Unable to create font preview tooltip content."); + } + + font = font.replace(/"/g, "'"); + font = font.replace("!important", ""); + font = font.trim(); + + let fillStyle = getTheme() === "light" ? "black" : "white"; + let {data, size: maxDim} = yield nodeFront.getFontFamilyDataURL(font, fillStyle); + + let imageUrl = yield data.string(); + let doc = this.view.inspector.panelDoc; + let {naturalWidth, naturalHeight} = yield getImageDimensions(doc, imageUrl); + + yield setImageTooltip(this.previewTooltip, doc, imageUrl, + {hideDimensionLabel: true, maxDim, naturalWidth, naturalHeight}); + }), + _onNewSelection: function () { if (this.previewTooltip) { this.previewTooltip.hide(); diff --git a/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-background-image.js b/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-background-image.js index 0a830e1cccf4..bd467b800f0e 100644 --- a/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-background-image.js +++ b/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-background-image.js @@ -65,7 +65,7 @@ function* testBodyRuleView(view) { yield assertHoverTooltipOn(view.tooltips.previewTooltip, uriSpan); - let images = panel.getElementsByTagName("image"); + let images = panel.getElementsByTagName("img"); is(images.length, 1, "Tooltip contains an image"); ok(images[0].getAttribute("src") .indexOf("iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHe") !== -1, @@ -81,7 +81,7 @@ function* testDivRuleView(view) { yield assertHoverTooltipOn(view.tooltips.previewTooltip, uriSpan); - let images = panel.getElementsByTagName("image"); + let images = panel.getElementsByTagName("img"); is(images.length, 1, "Tooltip contains an image"); ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri image as expected"); @@ -117,7 +117,7 @@ function* testComputedView(view) { yield assertHoverTooltipOn(view.tooltips.previewTooltip, uriSpan); - let images = panel.getElementsByTagName("image"); + let images = panel.getElementsByTagName("img"); is(images.length, 1, "Tooltip contains an image"); ok(images[0].getAttribute("src").startsWith("data:"), diff --git a/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-closes-on-new-selection.js b/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-closes-on-new-selection.js index 8ee55df11a8b..8b68ab700762 100644 --- a/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-closes-on-new-selection.js +++ b/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-closes-on-new-selection.js @@ -7,6 +7,7 @@ // Test that if a tooltip is visible when a new selection is made, it closes const TEST_URI = "
el 1
el 2
"; +const XHTML_NS = "http://www.w3.org/1999/xhtml"; add_task(function* () { yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); @@ -25,7 +26,9 @@ function* testRuleView(ruleView, inspector) { info("Showing the tooltip"); let tooltip = ruleView.tooltips.previewTooltip; - tooltip.setTextContent({messages: ["rule-view tooltip"]}); + let tooltipContent = ruleView.styleDocument.createElementNS(XHTML_NS, "div"); + yield tooltip.setContent(tooltipContent, 100, 30); + // Stop listening for mouse movements because it's not needed for this test, // and causes intermittent failures on Linux. When this test runs in the suite // sometimes a mouseleave event is dispatched at the start, which causes the @@ -48,7 +51,8 @@ function* testComputedView(computedView, inspector) { info("Showing the tooltip"); let tooltip = computedView.tooltips.previewTooltip; - tooltip.setTextContent({messages: ["computed-view tooltip"]}); + let tooltipContent = computedView.styleDocument.createElementNS(XHTML_NS, "div"); + yield tooltip.setContent(tooltipContent, 100, 30); // Stop listening for mouse movements because it's not needed for this test, // and causes intermittent failures on Linux. When this test runs in the suite // sometimes a mouseleave event is dispatched at the start, which causes the diff --git a/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-longhand-fontfamily.js b/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-longhand-fontfamily.js index 62d3b3a68b49..6bce367aef9c 100644 --- a/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-longhand-fontfamily.js +++ b/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-longhand-fontfamily.js @@ -51,7 +51,7 @@ function* testRuleView(ruleView, nodeFront) { // And verify that the tooltip gets shown on this property yield assertHoverTooltipOn(tooltip, valueSpan); - let images = panel.getElementsByTagName("image"); + let images = panel.getElementsByTagName("img"); is(images.length, 1, "Tooltip contains an image"); ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri image as expected"); @@ -70,7 +70,7 @@ function* testComputedView(computedView, nodeFront) { yield assertHoverTooltipOn(tooltip, valueSpan); - let images = panel.getElementsByTagName("image"); + let images = panel.getElementsByTagName("img"); is(images.length, 1, "Tooltip contains an image"); ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri image as expected"); @@ -97,7 +97,7 @@ function* testExpandedComputedViewProperty(computedView, nodeFront) { yield assertHoverTooltipOn(tooltip, valueSpan); - let images = panel.getElementsByTagName("image"); + let images = panel.getElementsByTagName("img"); is(images.length, 1, "Tooltip contains an image"); ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri image as expected"); diff --git a/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-multiple-background-images.js b/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-multiple-background-images.js index 64dfe4c8bb78..60d747a459c2 100644 --- a/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-multiple-background-images.js +++ b/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-multiple-background-images.js @@ -45,7 +45,7 @@ function* testComputedViewUrls(inspector) { */ function* performChecks(view, propertyValue) { function checkTooltip(panel, imageSrc) { - let images = panel.getElementsByTagName("image"); + let images = panel.getElementsByTagName("img"); is(images.length, 1, "Tooltip contains an image"); is(images[0].getAttribute("src"), imageSrc, "The image URL is correct"); } diff --git a/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-shorthand-fontfamily.js b/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-shorthand-fontfamily.js index 4824c7b299f6..bb851ec92a1c 100644 --- a/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-shorthand-fontfamily.js +++ b/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-shorthand-fontfamily.js @@ -47,7 +47,7 @@ function* testRuleView(ruleView, nodeFront) { // And verify that the tooltip gets shown on this property yield assertHoverTooltipOn(tooltip, valueSpan); - let images = panel.getElementsByTagName("image"); + let images = panel.getElementsByTagName("img"); is(images.length, 1, "Tooltip contains an image"); ok(images[0].getAttribute("src") .startsWith("data:"), "Tooltip contains a data-uri image as expected"); diff --git a/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-size.js b/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-size.js index 63df85a8a3fc..14b50c91677c 100644 --- a/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-size.js +++ b/devtools/client/inspector/shared/test/browser_styleinspector_tooltip-size.js @@ -39,12 +39,12 @@ function* testImageDimension(ruleView) { info("Showing the tooltip"); let onShown = tooltip.once("shown"); - tooltip.show(); + tooltip.show(uriSpan); yield onShown; // Let's not test for a specific size, but instead let's make sure it's at // least as big as the image - let imageRect = panel.querySelector("image").getBoundingClientRect(); + let imageRect = panel.querySelector("img").getBoundingClientRect(); let panelRect = panel.getBoundingClientRect(); ok(panelRect.width >= imageRect.width, diff --git a/devtools/client/shared/widgets/Tooltip.js b/devtools/client/shared/widgets/Tooltip.js index f3ea36506049..49876a9f4757 100644 --- a/devtools/client/shared/widgets/Tooltip.js +++ b/devtools/client/shared/widgets/Tooltip.js @@ -18,7 +18,6 @@ const Heritage = require("sdk/core/heritage"); const {Eyedropper} = require("devtools/client/eyedropper/eyedropper"); const Editor = require("devtools/client/sourceeditor/editor"); const Services = require("Services"); -const {Task} = require("devtools/shared/task"); loader.lazyRequireGetter(this, "beautify", "devtools/shared/jsbeautify/beautify"); loader.lazyRequireGetter(this, "setNamedTimeout", "devtools/client/shared/widgets/view-helpers", true); @@ -520,31 +519,6 @@ Tooltip.prototype = { this.panel.setAttribute("clamped-dimensions", ""); }, - /** - * Uses the provided inspectorFront's getImageDataFromURL method to resolve - * the relative URL on the server-side, in the page context, and then sets the - * tooltip content with the resulting image just like |setImageContent| does. - * @return a promise that resolves when the image is shown in the tooltip or - * resolves when the broken image tooltip content is ready, but never rejects. - */ - setRelativeImageContent: Task.async(function* (imageUrl, inspectorFront, - maxDim) { - if (imageUrl.startsWith("data:")) { - // If the imageUrl already is a data-url, save ourselves a round-trip - this.setImageContent(imageUrl, {maxDim: maxDim}); - } else if (inspectorFront) { - try { - let {data, size} = yield inspectorFront.getImageDataFromURL(imageUrl, - maxDim); - size.maxDim = maxDim; - let str = yield data.string(); - this.setImageContent(str, size); - } catch (e) { - this.setBrokenImageContent(); - } - } - }), - /** * Fill the tooltip with a message explaining the the image is missing */ @@ -560,7 +534,7 @@ Tooltip.prototype = { * Fill the tooltip with an image and add the image dimension at the bottom. * * Only use this for absolute URLs that can be queried from the devtools - * client-side. For relative URLs, use |setRelativeImageContent|. + * client-side. * * @param {string} imageUrl * The url to load the image from @@ -768,38 +742,6 @@ Tooltip.prototype = { } }, - /** - * Set the content of the tooltip to display a font family preview. - * This is based on Lea Verou's Dablet. - * See https://github.com/LeaVerou/dabblet - * for more info. - * @param {String} font The font family value. - * @param {object} nodeFront - * The NodeActor that will used to retrieve the dataURL for the font - * family tooltip contents. - * @return A promise that resolves when the font tooltip content is ready, or - * rejects if no font is provided - */ - setFontFamilyContent: Task.async(function* (font, nodeFront) { - if (!font || !nodeFront) { - throw new Error("Missing font"); - } - - if (typeof nodeFront.getFontFamilyDataURL === "function") { - font = font.replace(/"/g, "'"); - font = font.replace("!important", ""); - font = font.trim(); - - let fillStyle = - (Services.prefs.getCharPref("devtools.theme") === "light") ? - "black" : "white"; - - let {data, size} = yield nodeFront.getFontFamilyDataURL(font, fillStyle); - let str = yield data.string(); - this.setImageContent(str, { hideDimensionLabel: true, maxDim: size }); - } - }), - /** * Set the content of this tooltip to the MDN docs widget. *