зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1498143 - Pass nodeActorID to screenshot actor to enable feature in iframes and shadowroots;r=pbro,yulia
Differential Revision: https://phabricator.services.mozilla.com/D12124 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
8e870bf61e
Коммит
6380b99f50
|
@ -2294,7 +2294,7 @@ Inspector.prototype = {
|
|||
.getBoolPref("devtools.screenshot.clipboard.enabled");
|
||||
const args = {
|
||||
file: true,
|
||||
selector: this.selectionCssSelector,
|
||||
nodeActorID: this.selection.nodeFront.actorID,
|
||||
clipboard: clipboardEnabled,
|
||||
};
|
||||
const screenshotFront = this.target.getFront("screenshot");
|
||||
|
|
|
@ -52,6 +52,7 @@ support-files =
|
|||
helper_events_test_runner.js
|
||||
helper_markup_accessibility_navigation.js
|
||||
helper_outerhtml_test_runner.js
|
||||
helper_screenshot_node.js
|
||||
helper_style_attr_test_runner.js
|
||||
lib_babel_6.21.0_min.js
|
||||
lib_jquery_1.0.js
|
||||
|
@ -170,6 +171,9 @@ skip-if = verify
|
|||
[browser_markup_pagesize_02.js]
|
||||
[browser_markup_pseudo_on_reload.js]
|
||||
[browser_markup_remove_xul_attributes.js]
|
||||
[browser_markup_screenshot_node.js]
|
||||
[browser_markup_screenshot_node_iframe.js]
|
||||
[browser_markup_screenshot_node_shadowdom.js]
|
||||
[browser_markup_search_01.js]
|
||||
[browser_markup_shadowdom.js]
|
||||
[browser_markup_shadowdom_clickreveal.js]
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* import-globals-from helper_screenshot_node.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
loadHelperScript("helper_screenshot_node.js");
|
||||
|
||||
const TEST_URL = `data:text/html;charset=utf8,
|
||||
<div id="blue-node" style="width:30px;height:30px;background:rgb(0, 0, 255)"></div>`;
|
||||
|
||||
// Test that the "Screenshot Node" feature works with a regular node in the main document.
|
||||
add_task(async function() {
|
||||
const { inspector, toolbox } = await openInspectorForURL(encodeURI(TEST_URL));
|
||||
|
||||
info("Select the blue node");
|
||||
await selectNode("#blue-node", inspector);
|
||||
|
||||
info("Take a screenshot of the blue node and verify it looks as expected");
|
||||
const blueScreenshot = await takeNodeScreenshot(inspector);
|
||||
await assertSingleColorScreenshotImage(blueScreenshot, 30, 30, { r: 0, g: 0, b: 255 });
|
||||
|
||||
await toolbox.destroy();
|
||||
});
|
|
@ -0,0 +1,27 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* import-globals-from helper_screenshot_node.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
loadHelperScript("helper_screenshot_node.js");
|
||||
|
||||
const TEST_URL = `data:text/html;charset=utf8,
|
||||
<iframe
|
||||
src="data:text/html;charset=utf8,
|
||||
<div style='width:30px;height:30px;background:rgb(255, 0, 0)'></div>"></iframe>`;
|
||||
|
||||
// Test that the "Screenshot Node" feature works with a node inside an iframe.
|
||||
add_task(async function() {
|
||||
const { inspector, toolbox } = await openInspectorForURL(encodeURI(TEST_URL));
|
||||
|
||||
info("Select the red node");
|
||||
const redNode = await getNodeFrontInFrame("div", "iframe", inspector);
|
||||
await selectNode(redNode, inspector);
|
||||
|
||||
info("Take a screenshot of the red node and verify it looks as expected");
|
||||
const redScreenshot = await takeNodeScreenshot(inspector);
|
||||
await assertSingleColorScreenshotImage(redScreenshot, 30, 30, { r: 255, g: 0, b: 0 });
|
||||
|
||||
await toolbox.destroy();
|
||||
});
|
|
@ -0,0 +1,36 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* import-globals-from helper_screenshot_node.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
loadHelperScript("helper_screenshot_node.js");
|
||||
|
||||
const TEST_URL = `data:text/html;charset=utf8,
|
||||
<test-component></test-component>
|
||||
<script>
|
||||
'use strict';
|
||||
customElements.define('test-component', class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
let shadowRoot = this.attachShadow({mode: 'open'});
|
||||
shadowRoot.innerHTML =
|
||||
'<div style="width:30px;height:30px;background:rgb(0, 128, 0)"></div>';
|
||||
}
|
||||
});
|
||||
</script>`;
|
||||
|
||||
// Test that the "Screenshot Node" feature works with a node inside a shadow root.
|
||||
add_task(async function() {
|
||||
const { inspector, toolbox } = await openInspectorForURL(encodeURI(TEST_URL));
|
||||
|
||||
info("Select the green node");
|
||||
const greenNode = await getNodeFrontInShadowDom("div", "test-component", inspector);
|
||||
await selectNode(greenNode, inspector);
|
||||
|
||||
info("Take a screenshot of the green node and verify it looks as expected");
|
||||
const greenScreenshot = await takeNodeScreenshot(inspector);
|
||||
await assertSingleColorScreenshotImage(greenScreenshot, 30, 30, { r: 0, g: 128, b: 0 });
|
||||
|
||||
await toolbox.destroy();
|
||||
});
|
|
@ -0,0 +1,84 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
function colorAt(image, x, y) {
|
||||
// Create a test canvas element.
|
||||
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
const canvas = document.createElementNS(HTML_NS, "canvas");
|
||||
canvas.width = image.width;
|
||||
canvas.height = image.height;
|
||||
|
||||
// Draw the image in the canvas
|
||||
const context = canvas.getContext("2d");
|
||||
context.drawImage(image, 0, 0, image.width, image.height);
|
||||
|
||||
// Return the color found at the provided x,y coordinates as a "r, g, b" string.
|
||||
const [r, g, b] = context.getImageData(x, y, 1, 1).data;
|
||||
return { r, g, b };
|
||||
}
|
||||
|
||||
function waitUntilScreenshot() {
|
||||
return new Promise(async function(resolve) {
|
||||
const { Downloads } = require("resource://gre/modules/Downloads.jsm");
|
||||
const list = await Downloads.getList(Downloads.ALL);
|
||||
|
||||
const view = {
|
||||
onDownloadAdded: download => {
|
||||
download.whenSucceeded().then(() => {
|
||||
resolve(download.target.path);
|
||||
list.removeView(view);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
await list.addView(view);
|
||||
});
|
||||
}
|
||||
|
||||
async function resetDownloads() {
|
||||
info("Reset downloads");
|
||||
const { Downloads } = require("resource://gre/modules/Downloads.jsm");
|
||||
const publicList = await Downloads.getList(Downloads.PUBLIC);
|
||||
const downloads = await publicList.getAll();
|
||||
for (const download of downloads) {
|
||||
publicList.remove(download);
|
||||
await download.finalize(true);
|
||||
}
|
||||
}
|
||||
|
||||
async function takeNodeScreenshot(inspector) {
|
||||
// Cleanup all downloads at the end of the test.
|
||||
registerCleanupFunction(resetDownloads);
|
||||
|
||||
info("Call screenshotNode() and wait until the screenshot is found in the Downloads");
|
||||
const whenScreenshotSucceeded = waitUntilScreenshot();
|
||||
inspector.screenshotNode();
|
||||
const filePath = await whenScreenshotSucceeded;
|
||||
|
||||
info("Create an image using the downloaded fileas source");
|
||||
const image = new Image();
|
||||
image.src = OS.Path.toFileURI(filePath);
|
||||
await once(image, "load");
|
||||
|
||||
return image;
|
||||
}
|
||||
/* exported takeNodeScreenshot */
|
||||
|
||||
/**
|
||||
* Check that the provided image has the expected width, height, and color.
|
||||
* NOTE: This test assumes that the image is only made of a single color and will only
|
||||
* check one pixel.
|
||||
*/
|
||||
async function assertSingleColorScreenshotImage(image, width, height, { r, g, b }) {
|
||||
is(image.width, width, "node screenshot has the expected width");
|
||||
is(image.height, height, "node screenshot has the expected height");
|
||||
|
||||
const color = colorAt(image, 0, 0);
|
||||
is(color.r, r, "node screenshot has the expected red component");
|
||||
is(color.g, g, "node screenshot has the expected green component");
|
||||
is(color.b, b, "node screenshot has the expected blue component");
|
||||
}
|
||||
/* exported assertSingleColorScreenshotImage */
|
|
@ -236,6 +236,31 @@ var getNodeFrontInFrame = async function(selector, frameSelector,
|
|||
return inspector.walker.querySelector(nodes[0], selector);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the NodeFront for a node that matches a given css selector inside a shadow root.
|
||||
*
|
||||
* @param {String} selector
|
||||
* CSS selector of the node inside the shadow root.
|
||||
* @param {String|NodeFront} hostSelector
|
||||
* Selector or front of the element to which the shadow root is attached.
|
||||
* @param {InspectorPanel} inspector
|
||||
* The instance of InspectorPanel currently loaded in the toolbox
|
||||
* @return {Promise} Resolves the node front when the inspector is updated with the new
|
||||
* node.
|
||||
*/
|
||||
var getNodeFrontInShadowDom = async function(selector, hostSelector, inspector) {
|
||||
const hostFront = await getNodeFront(hostSelector, inspector);
|
||||
const {nodes} = await inspector.walker.children(hostFront);
|
||||
|
||||
// Find the shadow root in the children of the host element.
|
||||
const shadowRoot = nodes.filter(node => node.isShadowRoot)[0];
|
||||
if (!shadowRoot) {
|
||||
throw new Error("Could not find a shadow root under selector: " + hostSelector);
|
||||
}
|
||||
|
||||
return inspector.walker.querySelector(shadowRoot, selector);
|
||||
};
|
||||
|
||||
var focusSearchBoxUsingShortcut = async function(panelWin, callback) {
|
||||
info("Focusing search box");
|
||||
const searchBox = panelWin.document.getElementById("inspector-searchbox");
|
||||
|
|
|
@ -15,6 +15,14 @@ exports.ScreenshotActor = protocol.ActorClassWithSpec(screenshotSpec, {
|
|||
},
|
||||
|
||||
capture: function(args) {
|
||||
if (args.nodeActorID) {
|
||||
const nodeActor = this.conn.getActor(args.nodeActorID);
|
||||
if (!nodeActor) {
|
||||
throw new Error(
|
||||
`Screenshot actor failed to find Node actor for '${args.nodeActorID}'`);
|
||||
}
|
||||
args.rawNode = nodeActor.rawNode;
|
||||
}
|
||||
return captureScreenshot(args, this.document);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -48,7 +48,7 @@ exports.captureScreenshot = captureScreenshot;
|
|||
* area of the browser window
|
||||
*/
|
||||
function createScreenshotDataURL(document, args) {
|
||||
const window = document.defaultView;
|
||||
let window = document.defaultView;
|
||||
let left = 0;
|
||||
let top = 0;
|
||||
let width;
|
||||
|
@ -65,6 +65,9 @@ function createScreenshotDataURL(document, args) {
|
|||
width = window.innerWidth + window.scrollMaxX - window.scrollMinX;
|
||||
height = window.innerHeight + window.scrollMaxY - window.scrollMinY;
|
||||
filename = filename.replace(".png", "-fullpage.png");
|
||||
} else if (args.rawNode) {
|
||||
window = args.rawNode.ownerDocument.defaultView;
|
||||
({ top, left, width, height } = getRect(window, args.rawNode, window));
|
||||
} else if (args.selector) {
|
||||
const node = window.document.querySelector(args.selector);
|
||||
({ top, left, width, height } = getRect(window, node, window));
|
||||
|
|
Загрузка…
Ссылка в новой задаче