summaryrefslogtreecommitdiffstats
path: root/dom/browser-element/mochitest/browserElement_CopyPaste.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/browser-element/mochitest/browserElement_CopyPaste.js')
-rw-r--r--dom/browser-element/mochitest/browserElement_CopyPaste.js339
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);
+});
+