Bug 788890 - GCLI screenshot command with no filename should copy to clipboard, r=jwalker

This commit is contained in:
Girish Sharma 2012-09-14 02:26:19 +05:30
parent 6a76cd692c
commit d8b7a09166
5 changed files with 298 additions and 30 deletions

View File

@ -12,6 +12,10 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "LayoutHelpers",
"resource:///modules/devtools/LayoutHelpers.jsm");
// String used as an indication to generate default file name in the following
// format: "Screen Shot yyyy-mm-dd at HH.MM.SS.png"
const FILENAME_DEFAULT_VALUE = " ";
/**
* 'screenshot' command
*/
@ -19,33 +23,45 @@ gcli.addCommand({
name: "screenshot",
description: gcli.lookup("screenshotDesc"),
manual: gcli.lookup("screenshotManual"),
returnType: "string",
returnType: "html",
params: [
{
name: "filename",
type: "string",
defaultValue: FILENAME_DEFAULT_VALUE,
description: gcli.lookup("screenshotFilenameDesc"),
manual: gcli.lookup("screenshotFilenameManual")
},
{
name: "delay",
type: { name: "number", min: 0 },
defaultValue: 0,
description: gcli.lookup("screenshotDelayDesc"),
manual: gcli.lookup("screenshotDelayManual")
},
{
name: "fullpage",
type: "boolean",
description: gcli.lookup("screenshotFullPageDesc"),
manual: gcli.lookup("screenshotFullPageManual")
},
{
name: "selector",
type: "node",
defaultValue: null,
description: gcli.lookup("inspectNodeDesc"),
manual: gcli.lookup("inspectNodeManual")
group: gcli.lookup("screenshotGroupOptions"),
params: [
{
name: "clipboard",
type: "boolean",
description: gcli.lookup("screenshotClipboardDesc"),
manual: gcli.lookup("screenshotClipboardManual")
},
{
name: "delay",
type: { name: "number", min: 0 },
defaultValue: 0,
description: gcli.lookup("screenshotDelayDesc"),
manual: gcli.lookup("screenshotDelayManual")
},
{
name: "fullpage",
type: "boolean",
description: gcli.lookup("screenshotFullPageDesc"),
manual: gcli.lookup("screenshotFullPageManual")
},
{
name: "selector",
type: "node",
defaultValue: null,
description: gcli.lookup("inspectNodeDesc"),
manual: gcli.lookup("inspectNodeManual")
}
]
}
],
exec: function Command_screenshot(args, context) {
@ -53,23 +69,27 @@ gcli.addCommand({
if (args.delay > 0) {
var promise = context.createPromise();
document.defaultView.setTimeout(function Command_screenshotDelay() {
let reply = this.grabScreen(document, args.filename);
let reply = this.grabScreen(document, args.filename, args.clipboard,
args.fullpage);
promise.resolve(reply);
}.bind(this), args.delay * 1000);
return promise;
}
else {
return this.grabScreen(document, args.filename, args.fullpage, args.selector);
return this.grabScreen(document, args.filename, args.clipboard,
args.fullpage, args.selector);
}
},
grabScreen:
function Command_screenshotGrabScreen(document, filename, fullpage, node) {
function Command_screenshotGrabScreen(document, filename, clipboard,
fullpage, node) {
let window = document.defaultView;
let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
let left = 0;
let top = 0;
let width;
let height;
let div = document.createElementNS("http://www.w3.org/1999/xhtml", "div");
if (!fullpage) {
if (!node) {
@ -93,19 +113,70 @@ gcli.addCommand({
let ctx = canvas.getContext("2d");
ctx.drawWindow(window, left, top, width, height, "#fff");
let data = canvas.toDataURL("image/png", "");
try {
if (clipboard) {
let io = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
let channel = io.newChannel(data, null, null);
let input = channel.open();
let imgTools = Cc["@mozilla.org/image/tools;1"]
.getService(Ci.imgITools);
let container = {};
imgTools.decodeImageData(input, channel.contentType, container);
let wrapped = Cc["@mozilla.org/supports-interface-pointer;1"]
.createInstance(Ci.nsISupportsInterfacePointer);
wrapped.data = container.value;
let trans = Cc["@mozilla.org/widget/transferable;1"]
.createInstance(Ci.nsITransferable);
if ("init" in trans) {
trans.init(null);
}
trans.addDataFlavor(channel.contentType);
trans.setTransferData(channel.contentType, wrapped, -1);
let clipid = Ci.nsIClipboard;
let clip = Cc["@mozilla.org/widget/clipboard;1"].getService(clipid);
clip.setData(trans, null, clipid.kGlobalClipboard);
div.textContent = gcli.lookup("screenshotCopied");
return div;
}
}
catch (ex) {
div.textContent = gcli.lookup("screenshotErrorCopying");
return div;
}
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
// Create a name for the file if not present
if (filename == FILENAME_DEFAULT_VALUE) {
let date = new Date();
let dateString = date.getFullYear() + "-" + (date.getMonth() + 1) +
"-" + date.getDate();
dateString = dateString.split("-").map(function(part) {
if (part.length == 1) {
part = "0" + part;
}
return part;
}).join("-");
let timeString = date.toTimeString().replace(/:/g, ".").split(" ")[0];
filename = gcli.lookupFormat("screenshotGeneratedFilename",
[dateString, timeString]) + ".png";
}
// Check there is a .png extension to filename
if (!filename.match(/.png$/i)) {
else if (!filename.match(/.png$/i)) {
filename += ".png";
}
// If the filename is relative, tack it onto the download directory
if (!filename.match(/[\\\/]/)) {
let downloadMgr = Cc["@mozilla.org/download-manager;1"]
.getService(Ci.nsIDownloadManager);
.getService(Ci.nsIDownloadManager);
let tempfile = downloadMgr.userDownloadsDirectory;
tempfile.append(filename);
filename = tempfile.path;
@ -114,21 +185,28 @@ gcli.addCommand({
try {
file.initWithPath(filename);
} catch (ex) {
return "Error saving to " + filename;
div.textContent = gcli.lookup("screenshotErrorSavingToFile") + " " + filename;
return div;
}
let ioService = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
.getService(Ci.nsIIOService);
let Persist = Ci.nsIWebBrowserPersist;
let persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
.createInstance(Persist);
.createInstance(Persist);
persist.persistFlags = Persist.PERSIST_FLAGS_REPLACE_EXISTING_FILES |
Persist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
let source = ioService.newURI(data, "UTF8", null);
persist.saveURI(source, null, null, null, null, file);
return "Saved to " + filename;
div.textContent = gcli.lookup("screenshotSavedToFile") + " " + filename;
div.addEventListener("click", function openFile() {
div.removeEventListener("click", openFile);
file.reveal();
});
div.style.cursor = "pointer";
return div;
}
});
});

View File

@ -24,6 +24,7 @@ MOCHITEST_BROWSER_FILES = \
browser_cmd_pagemod_export.js \
browser_cmd_pref.js \
browser_cmd_restart.js \
browser_cmd_screenshot.js \
browser_cmd_settings.js \
browser_gcli_web.js \
head.js \
@ -33,6 +34,7 @@ MOCHITEST_BROWSER_FILES = \
MOCHITEST_BROWSER_FILES += \
browser_dbg_cmd_break.html \
browser_dbg_cmd.html \
browser_cmd_screenshot.html \
browser_cmd_pagemod_export.html \
browser_cmd_jsb_script.jsi \
$(NULL)

View File

@ -0,0 +1,6 @@
<html>
<head></head>
<body>
<img id="testImage" ></img>
</body>
</html>

View File

@ -0,0 +1,146 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that screenshot command works properly
const TEST_URI = "http://example.com/browser/browser/devtools/commandline/" +
"test/browser_cmd_screenshot.html";
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
let tempScope = {};
Cu.import("resource://gre/modules/FileUtils.jsm", tempScope);
let FileUtils = tempScope.FileUtils;
function test() {
DeveloperToolbarTest.test(TEST_URI, [ testInput, testCapture ]);
}
function testInput() {
helpers.setInput('screenshot');
helpers.check({
input: 'screenshot',
markup: 'VVVVVVVVVV',
status: 'VALID',
args: {
}
});
helpers.setInput('screenshot abc.png');
helpers.check({
input: 'screenshot abc.png',
markup: 'VVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
filename: { value: "abc.png"},
}
});
helpers.setInput('screenshot --fullpage');
helpers.check({
input: 'screenshot --fullpage',
markup: 'VVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
fullpage: { value: true},
}
});
helpers.setInput('screenshot abc --delay 5');
helpers.check({
input: 'screenshot abc --delay 5',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
filename: { value: "abc"},
delay: { value: "5"},
}
});
helpers.setInput('screenshot --selector img#testImage');
helpers.check({
input: 'screenshot --selector img#testImage',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
selector: { value: content.document.getElementById("testImage")},
}
});
}
function testCapture() {
function checkTemporaryFile() {
// Create a temporary file.
let gFile = FileUtils.getFile("TmpD", ["TestScreenshotFile.png"]);
if (gFile.exists()) {
gFile.remove(false);
return true;
}
else {
return false;
}
}
function clearClipboard() {
let clipid = Ci.nsIClipboard;
let clip = Cc["@mozilla.org/widget/clipboard;1"].getService(clipid);
clip.emptyClipboard(clipid.kGlobalClipboard);
}
function checkClipboard() {
try {
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);
if ("init" in trans) {
trans.init(null);
}
let io = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
let contentType = io.newChannel("", null, null).contentType;
trans.addDataFlavor(contentType);
clip.getData(trans, clipid.kGlobalClipboard);
let str = new Object();
let strLength = new Object();
trans.getTransferData(contentType, str, strLength);
if (str && strLength > 0) {
clip.emptyClipboard(clipid.kGlobalClipboard);
return true;
}
}
catch (ex) {}
return false;
}
let path = FileUtils.getFile("TmpD", ["TestScreenshotFile.png"]).path;
DeveloperToolbarTest.exec({
typed: "screenshot " + path,
args: {
delay: 0,
filename: "" + path,
fullpage: false,
clipboard: false,
node: null,
},
outputMatch: new RegExp("^Saved to "),
});
ok(checkTemporaryFile, "Screenshot got created");
clearClipboard();
DeveloperToolbarTest.exec({
typed: "screenshot --fullpage --clipboard",
args: {
delay: 0,
filename: " ",
fullpage: true,
clipboard: true,
node: null,
},
outputMatch: new RegExp("^Copied to clipboard.$"),
});
ok(checkClipboard, "Screenshot got created and copied");
}

View File

@ -60,6 +60,20 @@ screenshotFilenameDesc=Destination filename
# asks for help on what it does.
screenshotFilenameManual=The name of the file (should have a '.png' extension) to which we write the screenshot.
# LOCALIZATION NOTE (screenshotClipboardDesc) A very short string to describe
# the 'clipboard' parameter to the 'screenshot' command, which is displayed in
# a dialog when the user is using this command.
screenshotClipboardDesc=Copy screenshot to clipboard? (true/false)
# LOCALIZATION NOTE (screenshotClipboardManual) A fuller description of the
# 'clipboard' parameter to the 'screenshot' command, displayed when the user
# asks for help on what it does.
screenshotClipboardManual=True if you want to copy the screenshot instead of saving it to a file.
# LOCALIZATION NOTE (screenshotGroupOptions) A label for the optional options of
# the screenshot command.
screenshotGroupOptions=Options
# LOCALIZATION NOTE (screenshotDelayDesc) A very short string to describe
# the 'delay' parameter to the 'screenshot' command, which is displayed in
# a dialog when the user is using this command.
@ -80,6 +94,28 @@ screenshotFullPageDesc=Entire webpage? (true/false)
# asks for help on what it does.
screenshotFullPageManual=True if the screenshot should also include parts of the webpage which are outside the current scrolled bounds.
# LOCALIZATION NOTE (screenshotGeneratedFilename) The auto generated filename
# when no file name is provided. the first argument (%1$S) is the date string
# in yyyy-mm-dd format and the second argument (%2$S) is the time string
# in HH.MM.SS format. Please don't add the extension here.
screenshotGeneratedFilename=Screen Shot %1$S at %2$S
# LOCALIZATION NOTE (screenshotErrorSavingToFile) Text displayed to user upon
# encountering error while saving the screenshot to the file specified.
screenshotErrorSavingToFile=Error saving to
# LOCALIZATION NOTE (screenshotSavedToFile) Text displayed to user when the
# screenshot is successfully saved to the file specified.
screenshotSavedToFile=Saved to
# LOCALIZATION NOTE (screenshotErrorCopying) Text displayed to user upon
# encountering error while copying the screenshot to clipboard.
screenshotErrorCopying=Error occurred while copying to clipboard.
# LOCALIZATION NOTE (screenshotCopied) Text displayed to user when the
# screenshot is successfully copied to the clipboard.
screenshotCopied=Copied to clipboard.
# LOCALIZATION NOTE (restartFirefoxDesc) A very short description of the
# 'restart' command. This string is designed to be shown in a menu alongside the
# command name, which is why it should be as short as possible.