/* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ function modifySelection(s) { var g = window.getSelection(); var l = g.getRangeAt(0); var d = document.createElement("p"); d.innerHTML = s; d.appendChild(l.cloneContents()); var e = document.createElement("div"); document.body.appendChild(e); e.appendChild(d); var a = document.createRange(); a.selectNode(d); g.removeAllRanges(); g.addRange(a); window.setTimeout(function () { e.remove(); g.removeAllRanges(); g.addRange(l); }, 0); } function getLoadContext() { var Ci = SpecialPowers.Ci; return SpecialPowers.wrap(window).docShell.QueryInterface(Ci.nsILoadContext); } async function testCopyPaste(isXHTML) { var suppressUnicodeCheckIfHidden = !!isXHTML; var suppressHTMLCheck = !!isXHTML; var docShell = SpecialPowers.wrap(window).docShell; var documentViewer = docShell.docViewer.QueryInterface( SpecialPowers.Ci.nsIDocumentViewerEdit ); var clipboard = SpecialPowers.Services.clipboard; var textarea = SpecialPowers.wrap(document.getElementById("input")); async function copySelectionToClipboard(suppressUnicodeCheck) { await SimpleTest.promiseClipboardChange( () => true, () => { documentViewer.copySelection(); } ); if (!suppressUnicodeCheck) { ok( clipboard.hasDataMatchingFlavors(["text/plain"], 1), "check text/plain" ); } if (!suppressHTMLCheck) { ok(clipboard.hasDataMatchingFlavors(["text/html"], 1), "check text/html"); } } function clear(node, suppressUnicodeCheck) { textarea.blur(); var sel = window.getSelection(); sel.removeAllRanges(); } async function copyToClipboard(node, suppressUnicodeCheck) { clear(); var r = document.createRange(); r.selectNode(node); window.getSelection().addRange(r); await copySelectionToClipboard(suppressUnicodeCheck); } function addRange(startNode, startIndex, endNode, endIndex) { var sel = window.getSelection(); var r = document.createRange(); r.setStart(startNode, startIndex); r.setEnd(endNode, endIndex); sel.addRange(r); } async function copyRangeToClipboard( startNode, startIndex, endNode, endIndex, suppressUnicodeCheck ) { clear(); addRange(startNode, startIndex, endNode, endIndex); await copySelectionToClipboard(suppressUnicodeCheck); } async function copyChildrenToClipboard(id) { clear(); window.getSelection().selectAllChildren(document.getElementById(id)); await copySelectionToClipboard(); } function getClipboardData(mime) { var transferable = SpecialPowers.Cc[ "@mozilla.org/widget/transferable;1" ].createInstance(SpecialPowers.Ci.nsITransferable); transferable.init(getLoadContext()); transferable.addDataFlavor(mime); clipboard.getData(transferable, 1); var data = SpecialPowers.createBlankObject(); transferable.getTransferData(mime, data); return data; } function testHtmlClipboardValue(mime, expected) { // For Windows, navigator.platform returns "Win32". var expectedValue = expected; if (navigator.platform.includes("Win")) { // Windows has extra content. var expectedValue = kTextHtmlPrefixClipboardDataWindows + expected.replace(/\n/g, "\n") + kTextHtmlSuffixClipboardDataWindows; } testClipboardValue(mime, expectedValue); } function testClipboardValue(mime, expected) { if (suppressHTMLCheck && mime == "text/html") { return null; } var data = SpecialPowers.wrap(getClipboardData(mime)); is( data.value == null ? data.value : data.value.QueryInterface(SpecialPowers.Ci.nsISupportsString).data, expected, mime + " value in the clipboard" ); return data.value; } function testPasteText(expected) { textarea.value = ""; textarea.focus(); textarea.editor.paste(1); is(textarea.value, expected, "value of the textarea after the paste"); } function testPasteHTML(id, expected) { var contentEditable = $(id); contentEditable.focus(); synthesizeKey("v", { accelKey: true }); is(contentEditable.innerHTML, expected, id + ".innerHtml after the paste"); } function testSelectionToString(expected) { is( window.getSelection().toString().replace(/\r\n/g, "\n"), expected, "Selection.toString" ); } function testInnerHTML(id, expected) { var value = document.getElementById(id).innerHTML; is(value, expected, id + ".innerHTML"); } await copyChildrenToClipboard("draggable"); testSelectionToString("This is a draggable bit of text."); testClipboardValue("text/plain", "This is a draggable bit of text."); testHtmlClipboardValue( "text/html", '
This is a draggable bit of text.
' ); testPasteText("This is a draggable bit of text."); await copyChildrenToClipboard("alist"); testSelectionToString(" bla\n\n foo\n bar\n\n"); testClipboardValue("text/plain", " bla\n\n foo\n bar\n\n"); testHtmlClipboardValue( "text/html", '
\n bla\n \n
' ); testPasteText(" bla\n\n foo\n bar\n\n"); await copyChildrenToClipboard("blist"); testSelectionToString(" mozilla\n\n foo\n bar\n\n"); testClipboardValue("text/plain", " mozilla\n\n foo\n bar\n\n"); testHtmlClipboardValue( "text/html", '
\n mozilla\n
    \n
  1. foo
  2. \n \n
  3. bar
  4. \n
\n
' ); testPasteText(" mozilla\n\n foo\n bar\n\n"); await copyChildrenToClipboard("clist"); testSelectionToString(" mzla\n\n foo\n bazzinga!\n bar\n\n"); testClipboardValue( "text/plain", " mzla\n\n foo\n bazzinga!\n bar\n\n" ); testHtmlClipboardValue( "text/html", '
\n mzla\n \n
' ); testPasteText(" mzla\n\n foo\n bazzinga!\n bar\n\n"); await copyChildrenToClipboard("div4"); testSelectionToString(" Tt t t "); testClipboardValue("text/plain", " Tt t t "); if (isXHTML) { testHtmlClipboardValue( "text/html", '
\n T\n
' ); testInnerHTML( "div4", '\n T\n' ); } else { testHtmlClipboardValue( "text/html", '
\n T\n
' ); testInnerHTML("div4", "\n T\n"); } testPasteText(" Tt t t "); await copyChildrenToClipboard("div5"); testSelectionToString(" T "); testClipboardValue("text/plain", " T "); if (isXHTML) { testHtmlClipboardValue( "text/html", '
\n T\n
' ); testInnerHTML( "div5", '\n T\n' ); } else { testHtmlClipboardValue( "text/html", '
\n T\n
' ); testInnerHTML("div5", "\n T\n"); } testPasteText(" T "); await copyRangeToClipboard( $("div6").childNodes[0], 0, $("div6").childNodes[1], 1, suppressUnicodeCheckIfHidden ); testSelectionToString(""); // START Disabled due to bug 564688 if (false) { testClipboardValue("text/plain", ""); testClipboardValue("text/html", ""); } // END Disabled due to bug 564688 testInnerHTML("div6", "div6"); await copyRangeToClipboard( $("div7").childNodes[0], 0, $("div7").childNodes[0], 4, suppressUnicodeCheckIfHidden ); testSelectionToString(""); // START Disabled due to bug 564688 if (false) { testClipboardValue("text/plain", ""); testClipboardValue("text/html", ""); } // END Disabled due to bug 564688 testInnerHTML("div7", "div7"); await copyRangeToClipboard( $("div8").childNodes[0], 0, $("div8").childNodes[0], 4, suppressUnicodeCheckIfHidden ); testSelectionToString(""); // START Disabled due to bug 564688 if (false) { testClipboardValue("text/plain", ""); testClipboardValue("text/html", ""); } // END Disabled due to bug 564688 testInnerHTML("div8", "div8"); await copyRangeToClipboard( $("div9").childNodes[0], 0, $("div9").childNodes[0], 4, suppressUnicodeCheckIfHidden ); testSelectionToString("div9"); testClipboardValue("text/plain", "div9"); testHtmlClipboardValue("text/html", "div9"); testInnerHTML("div9", "div9"); await copyToClipboard($("div10"), suppressUnicodeCheckIfHidden); testSelectionToString(""); testInnerHTML("div10", "div10"); await copyToClipboard($("div10").firstChild, suppressUnicodeCheckIfHidden); testSelectionToString(""); await copyRangeToClipboard( $("div10").childNodes[0], 0, $("div10").childNodes[0], 1, suppressUnicodeCheckIfHidden ); testSelectionToString(""); await copyRangeToClipboard( $("div10").childNodes[1], 0, $("div10").childNodes[1], 1, suppressUnicodeCheckIfHidden ); testSelectionToString(""); if (!isXHTML) { // ============ copy/paste multi-range selection (bug 1123505) // with text start node var sel = window.getSelection(); sel.removeAllRanges(); var r = document.createRange(); var ul = $("ul1"); var parent = ul.parentNode; r.setStart(parent, 0); r.setEnd(parent.firstChild, 15); sel.addRange(r); //
{Copy1then Paste]
r = document.createRange(); r.setStart(ul, 1); r.setEnd(parent, 2); sel.addRange(r); //
Copy1then Paste}
await copySelectionToClipboard(true); testPasteHTML("contentEditable1", "Copy1then Paste"); // The