123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375 |
- /* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
- /* global helpers, btoa, whenDelayedStartupFinished, OpenBrowserWindow */
- // Test that screenshot command works properly
- "use strict";
- const TEST_URI = "http://example.com/browser/devtools/client/commandline/" +
- "test/browser_cmd_screenshot.html";
- var FileUtils = (Cu.import("resource://gre/modules/FileUtils.jsm", {})).FileUtils;
- function test() {
- // This test gets bombarded by a cascade of GCs and often takes 50s so lets be
- // safe and give the test 90s to run.
- requestLongerTimeout(3);
- return Task.spawn(spawnTest).then(finish, helpers.handleError);
- }
- function* spawnTest() {
- waitForExplicitFinish();
- info("RUN TEST: non-private window");
- let normWin = yield addWindow({ private: false });
- yield addTabWithToolbarRunTests(normWin);
- normWin.close();
- info("RUN TEST: private window");
- let pbWin = yield addWindow({ private: true });
- yield addTabWithToolbarRunTests(pbWin);
- pbWin.close();
- }
- function* addTabWithToolbarRunTests(win) {
- let options = yield helpers.openTab(TEST_URI, { chromeWindow: win });
- let browser = options.browser;
- yield helpers.openToolbar(options);
- // Test input status
- yield helpers.audit(options, [
- {
- setup: "screenshot",
- check: {
- input: "screenshot",
- markup: "VVVVVVVVVV",
- status: "VALID",
- args: {
- }
- },
- },
- {
- setup: "screenshot abc.png",
- check: {
- input: "screenshot abc.png",
- markup: "VVVVVVVVVVVVVVVVVV",
- status: "VALID",
- args: {
- filename: { value: "abc.png"},
- }
- },
- },
- {
- setup: "screenshot --fullpage",
- check: {
- input: "screenshot --fullpage",
- markup: "VVVVVVVVVVVVVVVVVVVVV",
- status: "VALID",
- args: {
- fullpage: { value: true},
- }
- },
- },
- {
- setup: "screenshot abc --delay 5",
- check: {
- input: "screenshot abc --delay 5",
- markup: "VVVVVVVVVVVVVVVVVVVVVVVV",
- status: "VALID",
- args: {
- filename: { value: "abc"},
- delay: { value: 5 },
- }
- },
- },
- {
- setup: "screenshot --selector img#testImage",
- check: {
- input: "screenshot --selector img#testImage",
- markup: "VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV",
- status: "VALID",
- },
- },
- ]);
- // Test capture to file
- let file = FileUtils.getFile("TmpD", [ "TestScreenshotFile.png" ]);
- yield helpers.audit(options, [
- {
- setup: "screenshot " + file.path,
- check: {
- args: {
- filename: { value: "" + file.path },
- fullpage: { value: false },
- clipboard: { value: false },
- },
- },
- exec: {
- output: new RegExp("^Saved to "),
- },
- post: function () {
- // Bug 849168: screenshot command tests fail in try but not locally
- // ok(file.exists(), "Screenshot file exists");
- if (file.exists()) {
- file.remove(false);
- }
- }
- },
- ]);
- // Test capture to clipboard
- yield helpers.audit(options, [
- {
- setup: "screenshot --clipboard",
- check: {
- args: {
- clipboard: { value: true },
- },
- },
- exec: {
- output: new RegExp("^Copied to clipboard.$"),
- },
- post: Task.async(function* () {
- let imgSize1 = yield getImageSizeFromClipboard();
- yield ContentTask.spawn(browser, imgSize1, function* (imgSize) {
- Assert.equal(imgSize.width, content.innerWidth,
- "Image width matches window size");
- Assert.equal(imgSize.height, content.innerHeight,
- "Image height matches window size");
- });
- })
- },
- {
- setup: "screenshot --fullpage --clipboard",
- check: {
- args: {
- fullpage: { value: true },
- clipboard: { value: true },
- },
- },
- exec: {
- output: new RegExp("^Copied to clipboard.$"),
- },
- post: Task.async(function* () {
- let imgSize1 = yield getImageSizeFromClipboard();
- yield ContentTask.spawn(browser, imgSize1, function* (imgSize) {
- Assert.equal(imgSize.width,
- content.innerWidth + content.scrollMaxX - content.scrollMinX,
- "Image width matches page size");
- Assert.equal(imgSize.height,
- content.innerHeight + content.scrollMaxY - content.scrollMinY,
- "Image height matches page size");
- });
- })
- },
- {
- setup: "screenshot --selector img#testImage --clipboard",
- check: {
- args: {
- clipboard: { value: true },
- },
- },
- exec: {
- output: new RegExp("^Copied to clipboard.$"),
- },
- post: Task.async(function* () {
- let imgSize1 = yield getImageSizeFromClipboard();
- yield ContentTask.spawn(browser, imgSize1, function* (imgSize) {
- let img = content.document.querySelector("img#testImage");
- Assert.equal(imgSize.width, img.clientWidth,
- "Image width matches element size");
- Assert.equal(imgSize.height, img.clientHeight,
- "Image height matches element size");
- });
- })
- },
- ]);
- // Trigger scrollbars by forcing document to overflow
- // This only affects results on OSes with scrollbars that reduce document size
- // (non-floating scrollbars). With default OS settings, this means Windows
- // and Linux are affected, but Mac is not. For Mac to exhibit this behavior,
- // change System Preferences -> General -> Show scroll bars to Always.
- yield ContentTask.spawn(browser, {}, function* () {
- content.document.body.classList.add("overflow");
- });
- let scrollbarSize = yield ContentTask.spawn(browser, {}, function* () {
- const winUtils = content.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindowUtils);
- let scrollbarHeight = {};
- let scrollbarWidth = {};
- winUtils.getScrollbarSize(true, scrollbarWidth, scrollbarHeight);
- return {
- width: scrollbarWidth.value,
- height: scrollbarHeight.value,
- };
- });
- info(`Scrollbar size: ${scrollbarSize.width}x${scrollbarSize.height}`);
- // Test capture to clipboard in presence of scrollbars
- yield helpers.audit(options, [
- {
- setup: "screenshot --clipboard",
- check: {
- args: {
- clipboard: { value: true },
- },
- },
- exec: {
- output: new RegExp("^Copied to clipboard.$"),
- },
- post: Task.async(function* () {
- let imgSize1 = yield getImageSizeFromClipboard();
- imgSize1.scrollbarWidth = scrollbarSize.width;
- imgSize1.scrollbarHeight = scrollbarSize.height;
- yield ContentTask.spawn(browser, imgSize1, function* (imgSize) {
- Assert.equal(imgSize.width, content.innerWidth - imgSize.scrollbarWidth,
- "Image width matches window size minus scrollbar size");
- Assert.equal(imgSize.height, content.innerHeight - imgSize.scrollbarHeight,
- "Image height matches window size minus scrollbar size");
- });
- })
- },
- {
- setup: "screenshot --fullpage --clipboard",
- check: {
- args: {
- fullpage: { value: true },
- clipboard: { value: true },
- },
- },
- exec: {
- output: new RegExp("^Copied to clipboard.$"),
- },
- post: Task.async(function* () {
- let imgSize1 = yield getImageSizeFromClipboard();
- imgSize1.scrollbarWidth = scrollbarSize.width;
- imgSize1.scrollbarHeight = scrollbarSize.height;
- yield ContentTask.spawn(browser, imgSize1, function* (imgSize) {
- Assert.equal(imgSize.width,
- (content.innerWidth + content.scrollMaxX -
- content.scrollMinX) - imgSize.scrollbarWidth,
- "Image width matches page size minus scrollbar size");
- Assert.equal(imgSize.height,
- (content.innerHeight + content.scrollMaxY -
- content.scrollMinY) - imgSize.scrollbarHeight,
- "Image height matches page size minus scrollbar size");
- });
- })
- },
- {
- setup: "screenshot --selector img#testImage --clipboard",
- check: {
- args: {
- clipboard: { value: true },
- },
- },
- exec: {
- output: new RegExp("^Copied to clipboard.$"),
- },
- post: Task.async(function* () {
- let imgSize1 = yield getImageSizeFromClipboard();
- yield ContentTask.spawn(browser, imgSize1, function* (imgSize) {
- let img = content.document.querySelector("img#testImage");
- Assert.equal(imgSize.width, img.clientWidth,
- "Image width matches element size");
- Assert.equal(imgSize.height, img.clientHeight,
- "Image height matches element size");
- });
- })
- },
- ]);
- yield helpers.closeToolbar(options);
- yield helpers.closeTab(options);
- }
- function addWindow(windowOptions) {
- return new Promise(resolve => {
- let win = OpenBrowserWindow(windowOptions);
- // This feels hacky, we should refactor it
- whenDelayedStartupFinished(win, () => {
- // Would like to get rid of this executeSoon, but without it the url
- // (TEST_URI) provided in addTabWithToolbarRunTests hasn't loaded
- executeSoon(() => {
- resolve(win);
- });
- });
- });
- }
- let getImageSizeFromClipboard = Task.async(function* () {
- let clipid = Ci.nsIClipboard;
- let clip = Cc["@mozilla.org/widget/clipboard;1"].getService(clipid);
- let trans = Cc["@mozilla.org/widget/transferable;1"]
- .createInstance(Ci.nsITransferable);
- let flavor = "image/png";
- trans.init(null);
- trans.addDataFlavor(flavor);
- clip.getData(trans, clipid.kGlobalClipboard);
- let data = new Object();
- let dataLength = new Object();
- trans.getTransferData(flavor, data, dataLength);
- ok(data.value, "screenshot exists");
- ok(dataLength.value > 0, "screenshot has length");
- let image = data.value;
- let dataURI = `data:${flavor};base64,`;
- // Due to the differences in how images could be stored in the clipboard the
- // checks below are needed. The clipboard could already provide the image as
- // byte streams, but also as pointer, or as image container. If it's not
- // possible obtain a byte stream, the function returns `null`.
- if (image instanceof Ci.nsISupportsInterfacePointer) {
- image = image.data;
- }
- if (image instanceof Ci.imgIContainer) {
- image = Cc["@mozilla.org/image/tools;1"]
- .getService(Ci.imgITools)
- .encodeImage(image, flavor);
- }
- if (image instanceof Ci.nsIInputStream) {
- let binaryStream = Cc["@mozilla.org/binaryinputstream;1"]
- .createInstance(Ci.nsIBinaryInputStream);
- binaryStream.setInputStream(image);
- let rawData = binaryStream.readBytes(binaryStream.available());
- let charCodes = Array.from(rawData, c => c.charCodeAt(0) & 0xff);
- let encodedData = String.fromCharCode(...charCodes);
- encodedData = btoa(encodedData);
- dataURI = dataURI + encodedData;
- } else {
- throw new Error("Unable to read image data");
- }
- let img = document.createElementNS("http://www.w3.org/1999/xhtml", "img");
- let loaded = new Promise(resolve => {
- img.addEventListener("load", function onLoad() {
- img.removeEventListener("load", onLoad);
- resolve();
- });
- });
- img.src = dataURI;
- document.documentElement.appendChild(img);
- yield loaded;
- img.remove();
- return {
- width: img.width,
- height: img.height,
- };
- });
|