diff options
Diffstat (limited to 'dom/browser-element/mochitest/browserElement_CopyPaste.js')
-rw-r--r-- | dom/browser-element/mochitest/browserElement_CopyPaste.js | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/dom/browser-element/mochitest/browserElement_CopyPaste.js b/dom/browser-element/mochitest/browserElement_CopyPaste.js new file mode 100644 index 000000000..b23feef59 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_CopyPaste.js @@ -0,0 +1,339 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test that "cut, copy, paste, selectall" and caretstatechanged event works from inside an <iframe mozbrowser>. +"use strict"; + +SimpleTest.waitForExplicitFinish(); +SimpleTest.requestFlakyTimeout("untriaged"); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.setupAccessibleCaretPref(); +browserElementTestHelpers.addPermission(); +const { Services } = SpecialPowers.Cu.import('resource://gre/modules/Services.jsm'); + +var gTextarea = null; +var mm; +var iframeOuter; +var iframeInner; +var state = 0; +var stateMeaning; +var defaultData; +var pasteData; +var focusScript; +var createEmbededFrame = false; +var testSelectionChange = false; + +function copyToClipboard(str) { + gTextarea.value = str; + SpecialPowers.wrap(gTextarea).editor.selectAll(); + SpecialPowers.wrap(gTextarea).editor.copy(); +} + +function getScriptForGetContent() { + var script = 'data:,\ + var elt = content.document.getElementById("text"); \ + var txt = ""; \ + if (elt) { \ + if (elt.tagName === "DIV" || elt.tagName === "BODY") { \ + txt = elt.textContent; \ + } else { \ + txt = elt.value; \ + } \ + } \ + sendAsyncMessage("content-text", txt);'; + return script; +} + +function getScriptForSetFocus() { + var script = 'data:,' + focusScript + 'sendAsyncMessage("content-focus")'; + return script; +} + +function runTest() { + iframeOuter = document.createElement('iframe'); + iframeOuter.setAttribute('mozbrowser', 'true'); + if (createEmbededFrame) { + iframeOuter.src = "file_empty.html"; + } + document.body.appendChild(iframeOuter); + + gTextarea = document.createElement('textarea'); + document.body.appendChild(gTextarea); + + iframeOuter.addEventListener("mozbrowserloadend", function onloadend(e) { + iframeOuter.removeEventListener("mozbrowserloadend", onloadend); + + if (createEmbededFrame) { + var contentWin = SpecialPowers.wrap(iframeOuter) + .QueryInterface(SpecialPowers.Ci.nsIFrameLoaderOwner) + .frameLoader.docShell.contentViewer.DOMDocument.defaultView; + var contentDoc = contentWin.document; + iframeInner = contentDoc.createElement('iframe'); + iframeInner.setAttribute('mozbrowser', true); + iframeInner.setAttribute('remote', 'false'); + contentDoc.body.appendChild(iframeInner); + iframeInner.addEventListener("mozbrowserloadend", function onloadendinner(e) { + iframeInner.removeEventListener("mozbrowserloadend", onloadendinner); + mm = SpecialPowers.getBrowserFrameMessageManager(iframeInner); + dispatchTest(e); + }); + } else { + iframeInner = iframeOuter; + mm = SpecialPowers.getBrowserFrameMessageManager(iframeInner); + dispatchTest(e); + } + }); +} + +function doCommand(cmd) { + var COMMAND_MAP = { + 'cut': 'cmd_cut', + 'copy': 'cmd_copyAndCollapseToEnd', + 'paste': 'cmd_paste', + 'selectall': 'cmd_selectAll' + }; + var script = 'data:,docShell.doCommand("' + COMMAND_MAP[cmd] + '");'; + mm.loadFrameScript(script, false); +} + +function dispatchTest(e) { + iframeInner.addEventListener("mozbrowserloadend", function onloadend2(e) { + iframeInner.removeEventListener("mozbrowserloadend", onloadend2); + iframeInner.focus(); + SimpleTest.executeSoon(function() { testSelectAll(e); }); + }); + + switch (state) { + case 0: // test for textarea + defaultData = "Test for selection change event"; + pasteData = "from parent "; + iframeInner.src = "data:text/html,<html><body>" + + "<textarea id='text'>" + defaultData + "</textarea>" + + "</body>" + + "</html>"; + stateMeaning = " (test: textarea)"; + focusScript = "var elt=content.document.getElementById('text');elt.focus();elt.select();"; + break; + case 1: // test for input text + defaultData = "Test for selection change event"; + pasteData = "from parent "; + iframeInner.src = "data:text/html,<html><body>" + + "<input type='text' id='text' value='" + defaultData + "'>" + + "</body>" + + "</html>"; + stateMeaning = " (test: <input type=text>)"; + focusScript = "var elt=content.document.getElementById('text');elt.focus();elt.select();"; + break; + case 2: // test for input number + defaultData = "12345"; + pasteData = "67890"; + iframeInner.src = "data:text/html,<html><body>" + + "<input type='number' id='text' value='" + defaultData + "'>" + + "</body>" + + "</html>"; + stateMeaning = " (test: <input type=number>)"; + focusScript = "var elt=content.document.getElementById('text');elt.focus();elt.select();"; + break; + case 3: // test for div contenteditable + defaultData = "Test for selection change event"; + pasteData = "from parent "; + iframeInner.src = "data:text/html,<html><body>" + + "<div contenteditable='true' id='text'>" + defaultData + "</div>" + + "</body>" + + "</html>"; + stateMeaning = " (test: content editable div)"; + focusScript = "var elt=content.document.getElementById('text');elt.focus();"; + break; + case 4: // test for normal div + defaultData = "Test for selection change event"; + pasteData = "from parent "; + iframeInner.src = "data:text/html,<html><body>" + + "<div id='text'>" + defaultData + "</div>" + + "</body>" + + "</html>"; + stateMeaning = " (test: normal div)"; + focusScript = "var elt=content.document.getElementById('text');elt.focus();"; + break; + case 5: // test for normal div with designMode:on + defaultData = "Test for selection change event"; + pasteData = "from parent "; + iframeInner.src = "data:text/html,<html><body id='text'>" + + defaultData + + "</body>" + + "<script>document.designMode='on';</script>" + + "</html>"; + stateMeaning = " (test: normal div with designMode:on)"; + focusScript = "var elt=content.document.getElementById('text');elt.focus();"; + break; + default: + if (createEmbededFrame || browserElementTestHelpers.getOOPByDefaultPref()) { + SimpleTest.finish(); + } else { + createEmbededFrame = true; + + // clean up and run test again. + document.body.removeChild(iframeOuter); + document.body.removeChild(gTextarea); + state = 0; + runTest(); + } + break; + } +} + +function isChildProcess() { + return SpecialPowers.Cc["@mozilla.org/xre/app-info;1"] + .getService(SpecialPowers.Ci.nsIXULRuntime) + .processType != SpecialPowers.Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT; +} + +function testSelectAll(e) { + // Skip mozbrowser test if we're at child process. + if (!isChildProcess()) { + let eventName = "mozbrowsercaretstatechanged"; + iframeOuter.addEventListener(eventName, function caretchangeforselectall(e) { + iframeOuter.removeEventListener(eventName, caretchangeforselectall, true); + ok(true, "got mozbrowsercaretstatechanged event." + stateMeaning); + ok(e.detail, "event.detail is not null." + stateMeaning); + ok(e.detail.width != 0, "event.detail.width is not zero" + stateMeaning); + ok(e.detail.height != 0, "event.detail.height is not zero" + stateMeaning); + SimpleTest.executeSoon(function() { testCopy1(e); }); + }, true); + } + + mm.addMessageListener('content-focus', function messageforfocus(msg) { + mm.removeMessageListener('content-focus', messageforfocus); + // test selectall command, after calling this the caretstatechanged event should be fired. + doCommand('selectall'); + if (isChildProcess()) { + SimpleTest.executeSoon(function() { testCopy1(e); }); + } + }); + + mm.loadFrameScript(getScriptForSetFocus(), false); +} + +function testCopy1(e) { + // Right now we're at "selectall" state, so we can test copy commnad by + // calling doCommand + copyToClipboard(""); + let setup = function() { + doCommand("copy"); + }; + + let nextTest = function(success) { + ok(success, "copy command works" + stateMeaning); + SimpleTest.executeSoon(function() { testPaste1(e); }); + }; + + let success = function() { + nextTest(true); + } + + let fail = function() { + nextTest(false); + } + + let compareData = defaultData; + SimpleTest.waitForClipboard(compareData, setup, success, fail); +} + +function testPaste1(e) { + // Next test paste command, first we copy to global clipboard in parent side. + // Then paste it to child side. + copyToClipboard(pasteData); + + doCommand('selectall'); + doCommand("paste"); + SimpleTest.executeSoon(function() { testPaste2(e); }); +} + +function testPaste2(e) { + mm.addMessageListener('content-text', function messageforpaste(msg) { + mm.removeMessageListener('content-text', messageforpaste); + if (state == 4) { + // normal div cannot paste, so the content remain unchange + ok(SpecialPowers.wrap(msg).json === defaultData, "paste command works" + stateMeaning); + } else if (state == 3 && browserElementTestHelpers.getOOPByDefaultPref()) { + // Something weird when we doCommand with content editable element in OOP. Mark this case as todo + todo(false, "paste command works" + stateMeaning); + } else { + ok(SpecialPowers.wrap(msg).json === pasteData, "paste command works" + stateMeaning); + } + SimpleTest.executeSoon(function() { testCut1(e); }); + }); + + mm.loadFrameScript(getScriptForGetContent(), false); +} + +function testCut1(e) { + // Clean clipboard first + copyToClipboard(""); + let setup = function() { + doCommand("selectall"); + doCommand("cut"); + }; + + let nextTest = function(success) { + if (state == 3 && browserElementTestHelpers.getOOPByDefaultPref()) { + // Something weird when we doCommand with content editable element in OOP. + todo(false, "cut function works" + stateMeaning); + } else { + ok(success, "cut function works" + stateMeaning); + } + SimpleTest.executeSoon(function() { testCut2(e); }); + }; + + let success = function() { + nextTest(true); + } + + let fail = function() { + nextTest(false); + } + + let compareData = pasteData; + // Something weird when we doCommand with content editable element in OOP. + // Always true in this case + // Normal div case cannot cut, always true as well. + if ((state == 3 && browserElementTestHelpers.getOOPByDefaultPref()) || + state == 4) { + compareData = function() { return true; } + } + + SimpleTest.waitForClipboard(compareData, setup, success, fail); +} + +function testCut2(e) { + mm.addMessageListener('content-text', function messageforcut(msg) { + mm.removeMessageListener('content-text', messageforcut); + // normal div cannot cut + if (state == 4) { + ok(SpecialPowers.wrap(msg).json !== "", "cut command works" + stateMeaning); + } else if (state == 3 && browserElementTestHelpers.getOOPByDefaultPref()) { + // Something weird when we doCommand with content editable element in OOP. Mark this case as todo + todo(false, "cut command works" + stateMeaning); + } else { + ok(SpecialPowers.wrap(msg).json === "", "cut command works" + stateMeaning); + } + + state++; + dispatchTest(e); + }); + + mm.loadFrameScript(getScriptForGetContent(), false); +} + +// Give our origin permission to open browsers, and remove it when the test is complete. +var principal = SpecialPowers.wrap(document).nodePrincipal; +var context = { url: SpecialPowers.wrap(principal.URI).spec, + originAttributes: { + appId: principal.appId, + inIsolatedMozBrowser: true }}; + +addEventListener('testready', function() { + SpecialPowers.pushPermissions([ + {type: 'browser', allow: 1, context: context} + ], runTest); +}); + |