diff options
Diffstat (limited to 'dom/base/test/useractivation/file_clipboard_common.js')
-rw-r--r-- | dom/base/test/useractivation/file_clipboard_common.js | 505 |
1 files changed, 505 insertions, 0 deletions
diff --git a/dom/base/test/useractivation/file_clipboard_common.js b/dom/base/test/useractivation/file_clipboard_common.js new file mode 100644 index 0000000000..e205819c88 --- /dev/null +++ b/dom/base/test/useractivation/file_clipboard_common.js @@ -0,0 +1,505 @@ +// This test is called from both test_clipboard_editor.html and test_clipboard_noeditor.html +// This is to test that the code works both in the presence of a contentEditable node, and in the absense of one +var WATCH_TIMEOUT = 300; + +// Some global variables to make the debug messages easier to track down +var gTestN0 = 0, + gTestN1 = 0, + gTestN2 = 0; +function testLoc() { + return " " + gTestN0 + " - " + gTestN1 + " - " + gTestN2; +} + +// Listen for cut & copy events +var gCopyCount = 0, + gCutCount = 0; +document.addEventListener("copy", function() { + gCopyCount++; +}); +document.addEventListener("cut", function() { + gCutCount++; +}); + +// Helper methods +function selectNode(aSelector, aCb) { + var dn = document.querySelector(aSelector); + var range = document.createRange(); + range.selectNodeContents(dn); + window.getSelection().removeAllRanges(); + window.getSelection().addRange(range); + if (aCb) { + aCb(); + } +} + +function selectInputNode(aSelector, aCb) { + var dn = document.querySelector(aSelector); + synthesizeMouse(dn, 10, 10, {}); + SimpleTest.executeSoon(function() { + synthesizeKey("A", { accelKey: true }); + // Clear the user activation state which is set from synthesized mouse and + // key event. + SpecialPowers.wrap(document).clearUserGestureActivation(); + SimpleTest.executeSoon(aCb); + }); +} + +// Callback functions for attaching to the button +function execCommand(aCommand, aShouldSucceed, aAsync = false) { + var cb = function(e) { + e.preventDefault(); + document.removeEventListener("keydown", cb); + + if (aAsync) { + setTimeout(() => { + is( + aShouldSucceed, + document.execCommand(aCommand), + "Keydown caused " + aCommand + " invocation" + testLoc() + ); + }, 0); + } else { + is( + aShouldSucceed, + document.execCommand(aCommand), + "Keydown caused " + aCommand + " invocation" + testLoc() + ); + } + }; + return cb; +} + +// The basic test set. Tries to cut/copy everything +function cutCopyAll( + aDoCut, + aDoCopy, + aDone, + aNegate, + aClipOverride, + aJustClipboardNegate +) { + var execCommandAlwaysSucceed = !!(aClipOverride || aJustClipboardNegate); + + function waitForClipboard(aCond, aSetup, aNext, aNegateOne) { + if (aClipOverride) { + aCond = aClipOverride; + aNegateOne = false; + } + if (aNegate || aNegateOne || aJustClipboardNegate) { + SimpleTest.waitForClipboard( + null, + aSetup, + aNext, + aNext, + "text/unicode", + WATCH_TIMEOUT, + true + ); + } else { + SimpleTest.waitForClipboard(aCond, aSetup, aNext, aNext); + } + } + + function validateCutCopy(aExpectedCut, aExpectedCopy) { + if (aNegate) { + aExpectedCut = aExpectedCopy = 0; + } // When we are negating - we always expect callbacks not to be run + + is( + aExpectedCut, + gCutCount, + (aExpectedCut > 0 + ? "Expect cut callback to run" + : "Expect cut callback not to run") + testLoc() + ); + is( + aExpectedCopy, + gCopyCount, + (aExpectedCopy > 0 + ? "Expect copy callback to run" + : "Expect copy callback not to run") + testLoc() + ); + gCutCount = gCopyCount = 0; + } + + function step(n) { + function nextStep() { + step(n + 1); + } + + // Reset the user activation state before running next test. + SpecialPowers.wrap(document).clearUserGestureActivation(); + + document.querySelector("span").textContent = "span text"; + document.querySelector("input[type=text]").value = "text text"; + document.querySelector("input[type=password]").value = "password text"; + document.querySelector("textarea").value = "textarea text"; + + var contentEditableNode = document.querySelector( + "div[contentEditable=true]" + ); + if (contentEditableNode) { + contentEditableNode.textContent = "contenteditable text"; + } + + gTestN2 = n; + switch (n) { + case 0: + // copy on readonly selection + selectNode("span"); + waitForClipboard( + "span text", + function() { + aDoCopy(true); + }, + nextStep + ); + return; + + case 1: + validateCutCopy(0, 1); + + // cut on readonly selection + selectNode("span"); + + waitForClipboard( + "span text", + function() { + aDoCut(execCommandAlwaysSucceed); + }, + nextStep, + true + ); + return; + + case 2: + validateCutCopy(1, 0); + + // copy on textbox selection + selectInputNode("input[type=text]", nextStep); + return; + + case 3: + waitForClipboard( + "text text", + function() { + selectInputNode("input[type=text]", function() { + aDoCopy(true); + }); + }, + nextStep + ); + return; + + case 4: + validateCutCopy(0, 1); + + // cut on textbox selection + selectInputNode("input[type=text]", nextStep); + return; + + case 5: + waitForClipboard( + "text text", + function() { + aDoCut(true); + }, + nextStep + ); + return; + + case 6: + validateCutCopy(1, 0); + + // copy on password selection + selectInputNode("input[type=password]", nextStep); + return; + + case 7: + waitForClipboard( + null, + function() { + aDoCopy(execCommandAlwaysSucceed); + }, + nextStep, + true + ); + return; + + case 8: + validateCutCopy(0, 1); + + // cut on password selection + selectInputNode("input[type=password]", nextStep); + return; + + case 9: + waitForClipboard( + null, + function() { + aDoCut(execCommandAlwaysSucceed); + }, + nextStep, + true + ); + return; + + case 10: + validateCutCopy(1, 0); + + // copy on textarea selection + selectInputNode("textarea", nextStep); + return; + + case 11: + waitForClipboard( + "textarea text", + function() { + aDoCopy(true); + }, + nextStep + ); + return; + + case 12: + validateCutCopy(0, 1); + + // cut on password selection + selectInputNode("textarea", nextStep); + return; + + case 13: + waitForClipboard( + "textarea text", + function() { + aDoCut(true); + }, + nextStep + ); + return; + + case 14: + validateCutCopy(1, 0); + + // copy on no selection + document.querySelector("textarea").blur(); + + waitForClipboard( + null, + function() { + aDoCopy(true); + }, + nextStep, + true + ); + return; + + case 15: + validateCutCopy(0, 1); + + // cut on no selection + waitForClipboard( + null, + function() { + aDoCut(execCommandAlwaysSucceed); + }, + nextStep, + true + ); + return; + + case 16: + validateCutCopy(1, 0); + + if (!document.querySelector("div[contentEditable=true]")) { + // We're done! (no contentEditable node!) + step(-1); + return; + } + break; + + case 17: + // copy on contenteditable selection + waitForClipboard( + "contenteditable text", + function() { + selectNode("div[contentEditable=true]", function() { + aDoCopy(true); + }); + }, + nextStep + ); + return; + + case 18: + validateCutCopy(0, 1); + break; + + case 19: + // cut on contenteditable selection + waitForClipboard( + "contenteditable text", + function() { + selectNode("div[contentEditable=true]", function() { + aDoCut(true); + }); + }, + nextStep + ); + return; + + case 20: + validateCutCopy(1, 0); + break; + + default: + aDone(); + return; + } + + SimpleTest.executeSoon(function() { + step(n + 1); + }); + } + + step(0); +} + +function allMechanisms(aCb, aClipOverride, aNegateAll) { + function testStep(n) { + gTestN1 = n; + switch (n) { + /** Test for Bug 1012662 **/ + case 0: + // Keyboard issued + cutCopyAll( + function docut(aSucc) { + synthesizeKey("x", { accelKey: true }); + }, + function docopy(aSucc) { + synthesizeKey("c", { accelKey: true }); + }, + function done() { + testStep(n + 1); + }, + false, + aClipOverride, + aNegateAll + ); + return; + + case 1: + // Button issued + cutCopyAll( + function docut(aSucc) { + document.addEventListener("keydown", execCommand("cut", aSucc)); + sendString("Q"); + }, + function docopy(aSucc) { + document.addEventListener("keydown", execCommand("copy", aSucc)); + sendString("Q"); + }, + function done() { + testStep(n + 1); + }, + false, + aClipOverride, + aNegateAll + ); + return; + + case 2: + // Not triggered by user gesture + cutCopyAll( + function doCut(aSucc) { + is( + false, + document.execCommand("cut"), + "Can't directly execCommand not in a user callback" + ); + }, + function doCopy(aSucc) { + is( + false, + document.execCommand("copy"), + "Can't directly execCommand not in a user callback" + ); + }, + function done() { + testStep(n + 1); + }, + true, + aClipOverride, + aNegateAll + ); + return; + + /** Test for Bug 1597857 **/ + case 3: + // Button issued async + cutCopyAll( + function docut(aSucc) { + document.addEventListener( + "keydown", + execCommand("cut", aSucc, true) + ); + sendString("Q"); + }, + function docopy(aSucc) { + document.addEventListener( + "keydown", + execCommand("copy", aSucc, true) + ); + sendString("Q"); + }, + function done() { + testStep(n + 1); + }, + false, + aClipOverride, + aNegateAll + ); + return; + + default: + aCb(); + } + } + testStep(0); +} + +// Run the tests +SimpleTest.waitForExplicitFinish(); +SimpleTest.requestLongerTimeout(5); // On the emulator - this times out occasionally +SimpleTest.waitForFocus(function() { + function justCancel(aEvent) { + aEvent.preventDefault(); + } + + function override(aEvent) { + aEvent.clipboardData.setData("text/plain", "overridden"); + aEvent.preventDefault(); + } + + allMechanisms(function() { + gTestN0 = 1; + document.addEventListener("cut", override); + document.addEventListener("copy", override); + + allMechanisms(function() { + gTestN0 = 2; + document.removeEventListener("cut", override); + document.removeEventListener("copy", override); + document.addEventListener("cut", justCancel); + document.addEventListener("copy", justCancel); + + allMechanisms( + function() { + SimpleTest.finish(); + }, + null, + true + ); + }, "overridden"); + }); +}); |