Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: headless OR os == 'android'
- Manifest: dom/events/test/clipboard/mochitest.toml
<html><head>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<script class="testbody" type="application/javascript">
function ImageTester() {
var counter = 0;
var images = [];
var that = this;
this.add = function(aFile) {
images.push(aFile);
};
this.test = async function() {
for (var i = 0; i < images.length; i++) {
await testImageSize(images[i]);
}
};
this.returned = function() {
counter++;
info("returned=" + counter + " images.length=" + images.length);
if (counter == images.length) {
info("test finish");
}
};
async function testImageSize(aFile) {
var source = window.URL.createObjectURL(aFile);
var image = new Image();
image.src = source;
var imageTester = that;
let promise = new Promise(resolve => {
image.addEventListener("load", function(e) {
is(this.width, 62, "Check generated image width");
is(this.height, 71, "Check generated image height");
// This fails on OSX only.
if (!navigator.platform.includes("Mac")) {
testImageCanvas(image);
}
imageTester.returned();
resolve();
}, { once: true });
});
document.body.appendChild(image);
await promise;
};
function testImageCanvas(aImage) {
var canvas = drawToCanvas(aImage);
var refImage = document.getElementById('image');
var refCanvas = drawToCanvas(refImage);
is(canvas.toDataURL(), refCanvas.toDataURL(), "Image should map pixel-by-pixel");
}
function drawToCanvas(aImage) {
var canvas = document.createElement("CANVAS");
document.body.appendChild(canvas);
canvas.width = aImage.width;
canvas.height = aImage.height;
canvas.getContext('2d').drawImage(aImage, 0, 0);
return canvas;
}
}
function copyImage(aImageId) {
// selection of the node
var node = document.getElementById(aImageId);
var docShell = SpecialPowers.wrap(window).docShell;
// let's copy the node
var documentViewer = docShell.docViewer
.QueryInterface(SpecialPowers.Ci.nsIDocumentViewerEdit);
documentViewer.setCommandNode(node);
documentViewer.copyImage(documentViewer.COPY_IMAGE_ALL);
}
async function doTest(imageAsFileEnabled) {
await SpecialPowers.pushPrefEnv({
set: [["clipboard.imageAsFile.enabled", imageAsFileEnabled]],
});
copyImage('image');
//--------- now check the content of the clipboard
var clipboard = SpecialPowers.Cc["@mozilla.org/widget/clipboard;1"]
.getService(SpecialPowers.Ci.nsIClipboard);
// does the clipboard contain text/plain data ?
ok(clipboard.hasDataMatchingFlavors(["text/plain"], clipboard.kGlobalClipboard),
"clipboard contains unicode text");
// does the clipboard contain text/html data ?
ok(clipboard.hasDataMatchingFlavors(["text/html"], clipboard.kGlobalClipboard),
"clipboard contains html text");
// does the clipboard contain image data ?
ok(clipboard.hasDataMatchingFlavors(["image/png"], clipboard.kGlobalClipboard),
"clipboard contains image");
let promise = new Promise(resolve => {
window.addEventListener("paste", async (e) => {
isDeeply(e.clipboardData.types,
(navigator.platform.includes("Win") && imageAsFileEnabled) ?
["application/x-moz-file", "Files"] : ["text/html", "text/plain", "Files"]);
await onPaste(e, imageAsFileEnabled);
resolve();
}, { once: true });
});
var textarea = SpecialPowers.wrap(document.getElementById('textarea'));
textarea.focus();
textarea.editor.paste(clipboard.kGlobalClipboard);
await promise;
clipboard.emptyClipboard(clipboard.kGlobalClipboard);
}
async function onPaste(e, imageAsFileEnabled) {
var imageTester = new ImageTester;
testFiles(e, imageTester, imageAsFileEnabled);
testItems(e, imageTester);
await imageTester.test();
}
function testItems(e, imageTester) {
var items = e.clipboardData.items;
is(items, e.clipboardData.items,
"Getting @items twice should return the same object");
var haveFiles = false;
ok(items instanceof DataTransferItemList, "@items implements DataTransferItemList");
ok(items.length, "@items is not empty");
for (var i = 0; i < items.length; i++) {
var item = items[i];
ok(item instanceof DataTransferItem, "each element of @items must implement DataTransferItem");
if (item.kind == "file") {
var file = item.getAsFile();
ok(file instanceof File, ".getAsFile() returns a File object");
ok(file.size > 0, "Files shouldn't have size 0");
imageTester.add(file);
}
}
}
function testFiles(e, imageTester, imageAsFileEnabled) {
var files = e.clipboardData.files;
is(files, e.clipboardData.files,
"Getting the files array twice should return the same array");
is(files.length, 1, "There should be one file in the clipboard");
for (var i = 0; i < files.length; i++) {
var file = files[i];
ok(file instanceof File, ".files should contain only File objects");
ok(file.size > 0, "This file shouldn't have size 0");
if (navigator.platform.includes("Win") && imageAsFileEnabled) {
ok(file.name.startsWith("Untitled") && file.name.endsWith(".png"),
`Check filename, got "${file.name}"`);
} else {
is(file.name, "image.png", "Check filename");
}
testSlice(file);
imageTester.add(file);
// Adding the same image again so we can test concurrency
imageTester.add(file);
}
}
function testSlice(aFile) {
var blob = aFile.slice();
ok(blob instanceof Blob, ".slice returns a blob");
is(blob.size, aFile.size, "the blob has the same size");
blob = aFile.slice(123123);
is(blob.size, 0, ".slice overflow check");
blob = aFile.slice(123, 123141);
is(blob.size, aFile.size - 123, ".slice @size check");
blob = aFile.slice(123, 12);
is(blob.size, 0, ".slice @size check 2");
blob = aFile.slice(124, 134, "image/png");
is(blob.size, 10, ".slice @size check 3");
is(blob.type, "image/png", ".slice @type check");
}
add_task(async function test_imageAsFile_enabled() {
await doTest(true);
});
add_task(async function test_imageAsFile_disabled() {
await doTest(false);
});
</script>
<body>
<img id="image" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD4AAABHCA
IAAADQjmMaAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3goUAwAgSAORBwAAABl0RVh0Q29
tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAABPSURBVGje7c4BDQAACAOga//OmuMbJGAurTbq
6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6s31B0IqAY2/t
QVCAAAAAElFTkSuQmCC" />
<form>
<textarea id="textarea"></textarea>
</form>
</body>
</html>