Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Errors

// This test is used to check copy and paste in editable areas to ensure that non-text
// types (html and images) are copied to and pasted from the clipboard properly.
var testPage =
"<body style='margin: 0'>" +
" <div id='main' contenteditable='true'>Test <b>Bold</b> After Text</div>" +
"</body>";
add_task(async function () {
let tab = BrowserTestUtils.addTab(gBrowser);
let browser = gBrowser.getBrowserForTab(tab);
gBrowser.selectedTab = tab;
await promiseTabLoadEvent(tab, "data:text/html," + escape(testPage));
await SimpleTest.promiseFocus(browser);
function sendKey(key, code) {
return BrowserTestUtils.synthesizeKey(
key,
{ code, accelKey: true },
browser
);
}
// On windows, HTML clipboard includes extra data.
// The values are from widget/windows/nsDataObj.cpp.
const htmlPrefix = navigator.platform.includes("Win")
? "<html><body>\n<!--StartFragment-->"
: "";
const htmlPostfix = navigator.platform.includes("Win")
? "<!--EndFragment-->\n</body>\n</html>"
: "";
await SpecialPowers.spawn(browser, [], () => {
var doc = content.document;
var main = doc.getElementById("main");
main.focus();
// Select an area of the text.
let selection = doc.getSelection();
selection.modify("move", "left", "line");
selection.modify("move", "right", "character");
selection.modify("move", "right", "character");
selection.modify("move", "right", "character");
selection.modify("extend", "right", "word");
selection.modify("extend", "right", "word");
});
// The data is empty as the selection was copied during the event default phase.
let copyEventPromise = BrowserTestUtils.waitForContentEvent(
browser,
"copy",
false,
event => {
return event.clipboardData.mozItemCount == 0;
}
);
await SpecialPowers.spawn(browser, [], () => {});
await sendKey("c");
await copyEventPromise;
let pastePromise = SpecialPowers.spawn(
browser,
[htmlPrefix, htmlPostfix],
(htmlPrefixChild, htmlPostfixChild) => {
let selection = content.document.getSelection();
selection.modify("move", "right", "line");
return new Promise(resolve => {
content.addEventListener(
"paste",
event => {
let clipboardData = event.clipboardData;
Assert.equal(
clipboardData.mozItemCount,
1,
"One item on clipboard"
);
Assert.equal(
clipboardData.types.length,
2,
"Two types on clipboard"
);
Assert.equal(
clipboardData.types[0],
"text/html",
"text/html on clipboard"
);
Assert.equal(
clipboardData.types[1],
"text/plain",
"text/plain on clipboard"
);
Assert.equal(
clipboardData.getData("text/html"),
htmlPrefixChild + "t <b>Bold</b>" + htmlPostfixChild,
"text/html value"
);
Assert.equal(
clipboardData.getData("text/plain"),
"t Bold",
"text/plain value"
);
resolve();
},
{ capture: true, once: true }
);
});
}
);
await SpecialPowers.spawn(browser, [], () => {});
await sendKey("v");
await pastePromise;
let copyPromise = SpecialPowers.spawn(browser, [], () => {
var main = content.document.getElementById("main");
Assert.equal(
main.innerHTML,
"Test <b>Bold</b> After Textt <b>Bold</b>",
"Copy and paste html"
);
let selection = content.document.getSelection();
selection.modify("extend", "left", "word");
selection.modify("extend", "left", "word");
selection.modify("extend", "left", "character");
return new Promise(resolve => {
content.addEventListener(
"cut",
event => {
event.clipboardData.setData("text/plain", "Some text");
event.clipboardData.setData("text/html", "<i>Italic</i> ");
selection.deleteFromDocument();
event.preventDefault();
resolve();
},
{ capture: true, once: true }
);
});
});
await SpecialPowers.spawn(browser, [], () => {});
await sendKey("x");
await copyPromise;
pastePromise = SpecialPowers.spawn(
browser,
[htmlPrefix, htmlPostfix],
(htmlPrefixChild, htmlPostfixChild) => {
let selection = content.document.getSelection();
selection.modify("move", "left", "line");
return new Promise(resolve => {
content.addEventListener(
"paste",
event => {
let clipboardData = event.clipboardData;
Assert.equal(
clipboardData.mozItemCount,
1,
"One item on clipboard 2"
);
Assert.equal(
clipboardData.types.length,
2,
"Two types on clipboard 2"
);
Assert.equal(
clipboardData.types[0],
"text/html",
"text/html on clipboard 2"
);
Assert.equal(
clipboardData.types[1],
"text/plain",
"text/plain on clipboard 2"
);
Assert.equal(
clipboardData.getData("text/html"),
htmlPrefixChild + "<i>Italic</i> " + htmlPostfixChild,
"text/html value 2"
);
Assert.equal(
clipboardData.getData("text/plain"),
"Some text",
"text/plain value 2"
);
resolve();
},
{ capture: true, once: true }
);
});
}
);
await SpecialPowers.spawn(browser, [], () => {});
await sendKey("v");
await pastePromise;
await SpecialPowers.spawn(browser, [], () => {
var main = content.document.getElementById("main");
Assert.equal(
main.innerHTML,
"<i>Italic</i> Test <b>Bold</b> After<b></b>",
"Copy and paste html 2"
);
});
// Next, check that the Copy Image command works.
// The context menu needs to be opened to properly initialize for the copy
// image command to run.
let contextMenu = document.getElementById("contentAreaContextMenu");
let contextMenuShown = promisePopupShown(contextMenu);
BrowserTestUtils.synthesizeMouseAtCenter(
"#img",
{ type: "contextmenu", button: 2 },
gBrowser.selectedBrowser
);
await contextMenuShown;
document.getElementById("context-copyimage-contents").doCommand();
contextMenu.hidePopup();
await promisePopupHidden(contextMenu);
// Focus the content again
await SimpleTest.promiseFocus(browser);
pastePromise = SpecialPowers.spawn(
browser,
[htmlPrefix, htmlPostfix],
(htmlPrefixChild, htmlPostfixChild) => {
var doc = content.document;
var main = doc.getElementById("main");
main.focus();
return new Promise((resolve, reject) => {
content.addEventListener(
"paste",
event => {
let clipboardData = event.clipboardData;
// DataTransfer doesn't support the image types yet, so only text/html
// will be present.
if (
clipboardData.getData("text/html") !==
htmlPrefixChild +
htmlPostfixChild
) {
reject(
"Clipboard Data did not contain an image, was " +
clipboardData.getData("text/html")
);
}
resolve();
},
{ capture: true, once: true }
);
});
}
);
await SpecialPowers.spawn(browser, [], () => {});
await sendKey("v");
await pastePromise;
// The new content should now include an image.
await SpecialPowers.spawn(browser, [], () => {
var main = content.document.getElementById("main");
Assert.equal(
main.innerHTML,
'<i>Italic</i> <img id="img" tabindex="1" ' +
"Test <b>Bold</b> After<b></b>",
"Paste after copy image"
);
});
gBrowser.removeCurrentTab();
});