Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | <!DOCTYPE HTML> |
michael@0 | 2 | <html> |
michael@0 | 3 | <head> |
michael@0 | 4 | <title>Test for Clipboard Events</title> |
michael@0 | 5 | <script type="text/javascript" src="/MochiKit/MochiKit.js"></script> |
michael@0 | 6 | <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> |
michael@0 | 7 | <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> |
michael@0 | 8 | <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> |
michael@0 | 9 | </head> |
michael@0 | 10 | <body> |
michael@0 | 11 | <p id="display"></p> |
michael@0 | 12 | <div id="content" style="border: 3px solid black; padding: 3em;">CONTENT TEXT<input id="content-input" value="INPUT TEXT"></div> |
michael@0 | 13 | <button id="button">Button</button> |
michael@0 | 14 | |
michael@0 | 15 | <div id="syntheticSpot" oncut="compareSynthetic(event, 'cut')" |
michael@0 | 16 | oncopy="compareSynthetic(event, 'copy')" |
michael@0 | 17 | onpaste="compareSynthetic(event, 'paste')">Spot</div> |
michael@0 | 18 | |
michael@0 | 19 | <pre id="test"> |
michael@0 | 20 | <script class="testbody" type="text/javascript;version=1.7"> |
michael@0 | 21 | |
michael@0 | 22 | var content = document.getElementById("content"); |
michael@0 | 23 | var contentInput = document.getElementById("content-input"); |
michael@0 | 24 | var clipboardInitialValue = "empty"; |
michael@0 | 25 | |
michael@0 | 26 | // Test that clearing and reading the clipboard works. A random number |
michael@0 | 27 | // is used to make sure that leftover clipboard values from a previous |
michael@0 | 28 | // test run don't cause a false-positive test. |
michael@0 | 29 | var cb_text = "empty_" + Math.random(); |
michael@0 | 30 | setClipboardText(cb_text); |
michael@0 | 31 | |
michael@0 | 32 | is(getClipboardText(), cb_text, "set/get clipboard text failed"); |
michael@0 | 33 | |
michael@0 | 34 | // Some test functions need to be run with delays. |
michael@0 | 35 | var delayedTests = []; |
michael@0 | 36 | |
michael@0 | 37 | var cachedCutData, cachedCopyData, cachedPasteData; |
michael@0 | 38 | |
michael@0 | 39 | // Ensure window focus before running tests, otherwise key events can |
michael@0 | 40 | // misfire. We set the onfocus event handler here to actually begin |
michael@0 | 41 | // running tests, and call window.focus() afterwards. |
michael@0 | 42 | window.onfocus = function() |
michael@0 | 43 | { |
michael@0 | 44 | window.onfocus = null; |
michael@0 | 45 | |
michael@0 | 46 | // A list of test functions to run. Before each test function is run, the |
michael@0 | 47 | // clipboard is initialized to clipboardInitialValue, and the contents of |
michael@0 | 48 | // div#content are set as the window's selection. |
michael@0 | 49 | var testFunctions = [ |
michael@0 | 50 | test_dom_oncopy, |
michael@0 | 51 | test_dom_oncut, |
michael@0 | 52 | test_dom_onpaste, |
michael@0 | 53 | test_dom_oncopy_abort, |
michael@0 | 54 | test_input_oncopy, |
michael@0 | 55 | test_input_oncut, |
michael@0 | 56 | test_input_onpaste, |
michael@0 | 57 | test_input_oncopy_abort, |
michael@0 | 58 | test_input_oncut_abort, |
michael@0 | 59 | test_input_onpaste_abort, |
michael@0 | 60 | test_input_cut_dataTransfer, |
michael@0 | 61 | test_input_cut_abort_dataTransfer, |
michael@0 | 62 | test_input_copy_dataTransfer, |
michael@0 | 63 | test_input_paste_dataTransfer, |
michael@0 | 64 | test_input_paste_abort_dataTransfer, |
michael@0 | 65 | test_input_copypaste_dataTransfer_multiple, |
michael@0 | 66 | test_input_copy_button_dataTransfer, |
michael@0 | 67 | test_eventspref_disabled |
michael@0 | 68 | ]; |
michael@0 | 69 | |
michael@0 | 70 | // Run the main tests. This will also populate the delayedTests array |
michael@0 | 71 | for (let i = 0; i < testFunctions.length; i++) { |
michael@0 | 72 | // Init clipboard |
michael@0 | 73 | setClipboardText(clipboardInitialValue); |
michael@0 | 74 | |
michael@0 | 75 | // Reset value of contentInput. |
michael@0 | 76 | contentInput.value = "INPUT TEXT"; |
michael@0 | 77 | |
michael@0 | 78 | var func = testFunctions[i]; |
michael@0 | 79 | func(); |
michael@0 | 80 | } |
michael@0 | 81 | |
michael@0 | 82 | // Check if the cached clipboard data can be accessed or modified |
michael@0 | 83 | // and whether it modifies the real clipboard |
michael@0 | 84 | checkCachedDataTransfer(cachedCutData, "cut"); |
michael@0 | 85 | checkCachedDataTransfer(cachedCopyData, "copy"); |
michael@0 | 86 | checkCachedDataTransfer(cachedPasteData, "paste"); |
michael@0 | 87 | |
michael@0 | 88 | checkSyntheticEvents(); |
michael@0 | 89 | |
michael@0 | 90 | SimpleTest.finish(); |
michael@0 | 91 | } |
michael@0 | 92 | |
michael@0 | 93 | // Calling .focus begins the test run. |
michael@0 | 94 | SimpleTest.waitForExplicitFinish(); |
michael@0 | 95 | window.focus(); |
michael@0 | 96 | |
michael@0 | 97 | function getLoadContext() { |
michael@0 | 98 | return SpecialPowers.wrap(window).QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor) |
michael@0 | 99 | .getInterface(SpecialPowers.Ci.nsIWebNavigation) |
michael@0 | 100 | .QueryInterface(SpecialPowers.Ci.nsILoadContext); |
michael@0 | 101 | } |
michael@0 | 102 | |
michael@0 | 103 | function getClipboardText() { |
michael@0 | 104 | return SpecialPowers.getClipboardData("text/unicode"); |
michael@0 | 105 | } |
michael@0 | 106 | |
michael@0 | 107 | |
michael@0 | 108 | function setClipboardText(text) { |
michael@0 | 109 | var helper = SpecialPowers.Cc["@mozilla.org/widget/clipboardhelper;1"] |
michael@0 | 110 | .getService(SpecialPowers.Ci.nsIClipboardHelper); |
michael@0 | 111 | helper.copyString(text); |
michael@0 | 112 | } |
michael@0 | 113 | |
michael@0 | 114 | function selectContentDiv() { |
michael@0 | 115 | // Set selection |
michael@0 | 116 | var selection = window.getSelection(); |
michael@0 | 117 | selection.removeAllRanges(); |
michael@0 | 118 | selection.selectAllChildren(content); |
michael@0 | 119 | } |
michael@0 | 120 | |
michael@0 | 121 | function selectContentInput() { |
michael@0 | 122 | contentInput.select(); |
michael@0 | 123 | contentInput.focus(); |
michael@0 | 124 | } |
michael@0 | 125 | |
michael@0 | 126 | function test_dom_oncopy() { |
michael@0 | 127 | // Setup an oncopy event handler, fire copy. Ensure that the event |
michael@0 | 128 | // handler was called, and the clipboard contents have set to CONTENT TEXT. |
michael@0 | 129 | // Test firing oncopy event on ctrl-c: |
michael@0 | 130 | selectContentDiv(); |
michael@0 | 131 | |
michael@0 | 132 | var oncopy_fired = false; |
michael@0 | 133 | content.oncopy = function() { oncopy_fired = true; }; |
michael@0 | 134 | try { |
michael@0 | 135 | synthesizeKey("c", {accelKey: 1}); |
michael@0 | 136 | ok(oncopy_fired, "copy event firing on DOM element"); |
michael@0 | 137 | is(getClipboardText(), "CONTENT TEXT", |
michael@0 | 138 | "copy on DOM element set clipboard correctly"); |
michael@0 | 139 | } finally { |
michael@0 | 140 | content.oncopy = null; |
michael@0 | 141 | } |
michael@0 | 142 | } |
michael@0 | 143 | |
michael@0 | 144 | function test_dom_oncut() { |
michael@0 | 145 | // Setup an oncut event handler, fire cut. Ensure that the event handler |
michael@0 | 146 | // was called. The <div> doesn't handle a cut, so ensure that the |
michael@0 | 147 | // clipboard text is clipboardInitialValue, NOT "CONTENT TEXT". |
michael@0 | 148 | selectContentDiv(); |
michael@0 | 149 | var oncut_fired = false; |
michael@0 | 150 | content.oncut = function() { oncut_fired = true; }; |
michael@0 | 151 | try { |
michael@0 | 152 | synthesizeKey("x", {accelKey: 1}); |
michael@0 | 153 | ok(!oncut_fired, "cut event firing on DOM element") |
michael@0 | 154 | is(getClipboardText(), clipboardInitialValue, |
michael@0 | 155 | "cut on DOM element did not modify clipboard"); |
michael@0 | 156 | } finally { |
michael@0 | 157 | content.oncut = null; |
michael@0 | 158 | } |
michael@0 | 159 | } |
michael@0 | 160 | |
michael@0 | 161 | |
michael@0 | 162 | function test_dom_onpaste() { |
michael@0 | 163 | // Setup an onpaste event handler, fire paste. Ensure that the event |
michael@0 | 164 | // handler was called. |
michael@0 | 165 | selectContentDiv(); |
michael@0 | 166 | var onpaste_fired = false; |
michael@0 | 167 | content.onpaste = function() { onpaste_fired = true; }; |
michael@0 | 168 | try { |
michael@0 | 169 | synthesizeKey("v", {accelKey: 1}); |
michael@0 | 170 | ok(!onpaste_fired, "paste event firing on DOM element"); |
michael@0 | 171 | } finally { |
michael@0 | 172 | content.onpaste = null; |
michael@0 | 173 | } |
michael@0 | 174 | } |
michael@0 | 175 | |
michael@0 | 176 | |
michael@0 | 177 | function test_dom_oncopy_abort() { |
michael@0 | 178 | // Setup an oncopy event handler that aborts the copy, and fire the copy |
michael@0 | 179 | // event. Ensure that the event handler was fired, and the clipboard |
michael@0 | 180 | // contents have not been modified. |
michael@0 | 181 | selectContentDiv(); |
michael@0 | 182 | var oncopy_fired = false; |
michael@0 | 183 | content.oncopy = function() { oncopy_fired = true; return false; }; |
michael@0 | 184 | try { |
michael@0 | 185 | synthesizeKey("c", {accelKey: 1}); |
michael@0 | 186 | ok(oncopy_fired, "copy event (to-be-cancelled) firing on DOM element"); |
michael@0 | 187 | is(getClipboardText(), clipboardInitialValue, |
michael@0 | 188 | "aborted copy on DOM element did not modify clipboard"); |
michael@0 | 189 | } finally { |
michael@0 | 190 | content.oncopy = null; |
michael@0 | 191 | } |
michael@0 | 192 | } |
michael@0 | 193 | |
michael@0 | 194 | |
michael@0 | 195 | function test_input_oncopy() { |
michael@0 | 196 | // Setup an oncopy event handler, fire copy. Ensure that the event |
michael@0 | 197 | // handler was called, and the clipboard contents have been set to 'PUT TE', |
michael@0 | 198 | // which is the part that is selected below. |
michael@0 | 199 | selectContentInput(); |
michael@0 | 200 | contentInput.focus(); |
michael@0 | 201 | contentInput.setSelectionRange(2, 8); |
michael@0 | 202 | |
michael@0 | 203 | var oncopy_fired = false; |
michael@0 | 204 | contentInput.oncopy = function() { oncopy_fired = true; }; |
michael@0 | 205 | try { |
michael@0 | 206 | synthesizeKey("c", {accelKey: 1}); |
michael@0 | 207 | ok(oncopy_fired, "copy event firing on plaintext editor"); |
michael@0 | 208 | is(getClipboardText(), "PUT TE", |
michael@0 | 209 | "copy on plaintext editor set clipboard correctly"); |
michael@0 | 210 | } finally { |
michael@0 | 211 | contentInput.oncopy = null; |
michael@0 | 212 | } |
michael@0 | 213 | } |
michael@0 | 214 | |
michael@0 | 215 | |
michael@0 | 216 | function test_input_oncut() { |
michael@0 | 217 | // Setup an oncut event handler, and fire cut. Ensure that the event |
michael@0 | 218 | // handler was fired, the clipboard contains the INPUT TEXT, and |
michael@0 | 219 | // that the input itself is empty. |
michael@0 | 220 | selectContentInput(); |
michael@0 | 221 | var oncut_fired = false; |
michael@0 | 222 | contentInput.oncut = function() { oncut_fired = true; }; |
michael@0 | 223 | try { |
michael@0 | 224 | synthesizeKey("x", {accelKey: 1}); |
michael@0 | 225 | ok(oncut_fired, "cut event firing on plaintext editor"); |
michael@0 | 226 | is(getClipboardText(), "INPUT TEXT", |
michael@0 | 227 | "cut on plaintext editor set clipboard correctly"); |
michael@0 | 228 | is(contentInput.value, "", |
michael@0 | 229 | "cut on plaintext editor emptied editor"); |
michael@0 | 230 | } finally { |
michael@0 | 231 | contentInput.oncut = null; |
michael@0 | 232 | } |
michael@0 | 233 | } |
michael@0 | 234 | |
michael@0 | 235 | |
michael@0 | 236 | function test_input_onpaste() { |
michael@0 | 237 | // Setup an onpaste event handler, and fire paste. Ensure that the event |
michael@0 | 238 | // handler was fired, the clipboard contents didn't change, and that the |
michael@0 | 239 | // input value did change (ie. paste succeeded). |
michael@0 | 240 | selectContentInput(); |
michael@0 | 241 | var onpaste_fired = false; |
michael@0 | 242 | contentInput.onpaste = function() { onpaste_fired = true; }; |
michael@0 | 243 | try { |
michael@0 | 244 | synthesizeKey("v", {accelKey: 1}); |
michael@0 | 245 | ok(onpaste_fired, "paste event firing on plaintext editor"); |
michael@0 | 246 | is(getClipboardText(), clipboardInitialValue, |
michael@0 | 247 | "paste on plaintext editor did not modify clipboard contents"); |
michael@0 | 248 | is(contentInput.value, clipboardInitialValue, |
michael@0 | 249 | "paste on plaintext editor did modify editor value"); |
michael@0 | 250 | } finally { |
michael@0 | 251 | contentInput.onpaste = null; |
michael@0 | 252 | } |
michael@0 | 253 | } |
michael@0 | 254 | |
michael@0 | 255 | |
michael@0 | 256 | function test_input_oncopy_abort() { |
michael@0 | 257 | // Setup an oncopy event handler, fire copy. Ensure that the event |
michael@0 | 258 | // handler was called, and that the clipboard value did NOT change. |
michael@0 | 259 | selectContentInput(); |
michael@0 | 260 | var oncopy_fired = false; |
michael@0 | 261 | contentInput.oncopy = function() { oncopy_fired = true; return false; }; |
michael@0 | 262 | try { |
michael@0 | 263 | synthesizeKey("c", {accelKey: 1}); |
michael@0 | 264 | ok(oncopy_fired, "copy event (to-be-cancelled) firing on plaintext editor"); |
michael@0 | 265 | is(getClipboardText(), clipboardInitialValue, |
michael@0 | 266 | "aborted copy on plaintext editor did not modify clipboard"); |
michael@0 | 267 | } finally { |
michael@0 | 268 | contentInput.oncopy = null; |
michael@0 | 269 | } |
michael@0 | 270 | } |
michael@0 | 271 | |
michael@0 | 272 | |
michael@0 | 273 | function test_input_oncut_abort() { |
michael@0 | 274 | // Setup an oncut event handler, and fire cut. Ensure that the event |
michael@0 | 275 | // handler was fired, the clipboard contains the INPUT TEXT, and |
michael@0 | 276 | // that the input itself is empty. |
michael@0 | 277 | selectContentInput(); |
michael@0 | 278 | var oncut_fired = false; |
michael@0 | 279 | contentInput.oncut = function() { oncut_fired = true; return false; }; |
michael@0 | 280 | try { |
michael@0 | 281 | synthesizeKey("x", {accelKey: 1}); |
michael@0 | 282 | ok(oncut_fired, "cut event (to-be-cancelled) firing on plaintext editor"); |
michael@0 | 283 | is(getClipboardText(), clipboardInitialValue, |
michael@0 | 284 | "aborted cut on plaintext editor did not modify clipboard."); |
michael@0 | 285 | is(contentInput.value, "INPUT TEXT", |
michael@0 | 286 | "aborted cut on plaintext editor did not modify editor contents"); |
michael@0 | 287 | } finally { |
michael@0 | 288 | contentInput.oncut = null; |
michael@0 | 289 | } |
michael@0 | 290 | } |
michael@0 | 291 | |
michael@0 | 292 | |
michael@0 | 293 | function test_input_onpaste_abort() { |
michael@0 | 294 | // Setup an onpaste event handler, and fire paste. Ensure that the event |
michael@0 | 295 | // handler was fired, the clipboard contents didn't change, and that the |
michael@0 | 296 | // input value did change (ie. paste succeeded). |
michael@0 | 297 | selectContentInput(); |
michael@0 | 298 | var onpaste_fired = false; |
michael@0 | 299 | contentInput.onpaste = function() { onpaste_fired = true; return false; }; |
michael@0 | 300 | try { |
michael@0 | 301 | synthesizeKey("v", {accelKey: 1}); |
michael@0 | 302 | ok(onpaste_fired, |
michael@0 | 303 | "paste event (to-be-cancelled) firing on plaintext editor"); |
michael@0 | 304 | is(getClipboardText(), clipboardInitialValue, |
michael@0 | 305 | "aborted paste on plaintext editor did not modify clipboard"); |
michael@0 | 306 | is(contentInput.value, "INPUT TEXT", |
michael@0 | 307 | "aborted paste on plaintext editor did not modify modified editor value"); |
michael@0 | 308 | } finally { |
michael@0 | 309 | contentInput.onpaste = null; |
michael@0 | 310 | } |
michael@0 | 311 | } |
michael@0 | 312 | |
michael@0 | 313 | |
michael@0 | 314 | function test_input_cut_dataTransfer() { |
michael@0 | 315 | // Cut using event.dataTransfer. The event is not cancelled so the default |
michael@0 | 316 | // cut should occur |
michael@0 | 317 | selectContentInput(); |
michael@0 | 318 | contentInput.oncut = function(event) { |
michael@0 | 319 | ok(event instanceof ClipboardEvent, "cut event is a ClipboardEvent"); |
michael@0 | 320 | ok(event.clipboardData instanceof DataTransfer, "cut event dataTransfer is a DataTransfer"); |
michael@0 | 321 | is(event.target, contentInput, "cut event target"); |
michael@0 | 322 | is(event.clipboardData.mozItemCount, 0, "cut event mozItemCount"); |
michael@0 | 323 | is(event.clipboardData.getData("text/plain"), "", "cut event getData"); |
michael@0 | 324 | event.clipboardData.setData("text/plain", "This is some dataTransfer text"); |
michael@0 | 325 | cachedCutData = event.clipboardData; |
michael@0 | 326 | }; |
michael@0 | 327 | try { |
michael@0 | 328 | synthesizeKey("x", {accelKey: 1}); |
michael@0 | 329 | is(getClipboardText(), "INPUT TEXT", |
michael@0 | 330 | "cut using dataTransfer on plaintext editor set clipboard correctly"); |
michael@0 | 331 | is(contentInput.value, "", |
michael@0 | 332 | "cut using dataTransfer on plaintext editor cleared input"); |
michael@0 | 333 | } finally { |
michael@0 | 334 | contentInput.oncut = null; |
michael@0 | 335 | } |
michael@0 | 336 | } |
michael@0 | 337 | |
michael@0 | 338 | |
michael@0 | 339 | function test_input_cut_abort_dataTransfer() { |
michael@0 | 340 | // Cut using event.dataTransfer but cancel the event. The data should be |
michael@0 | 341 | // put on the clipboard but since we don't modify the input value, the input |
michael@0 | 342 | // should have the same value. |
michael@0 | 343 | selectContentInput(); |
michael@0 | 344 | contentInput.oncut = function(event) { |
michael@0 | 345 | event.clipboardData.setData("text/plain", "Cut dataTransfer text"); |
michael@0 | 346 | return false; |
michael@0 | 347 | }; |
michael@0 | 348 | try { |
michael@0 | 349 | synthesizeKey("x", {accelKey: 1}); |
michael@0 | 350 | is(getClipboardText(), "Cut dataTransfer text", |
michael@0 | 351 | "aborted cut using dataTransfer on plaintext editor set clipboard correctly"); |
michael@0 | 352 | is(contentInput.value, "INPUT TEXT", |
michael@0 | 353 | "aborted cut using dataTransfer on plaintext editor did not modify input"); |
michael@0 | 354 | } finally { |
michael@0 | 355 | contentInput.oncut = null; |
michael@0 | 356 | } |
michael@0 | 357 | } |
michael@0 | 358 | |
michael@0 | 359 | |
michael@0 | 360 | function test_input_copy_dataTransfer() { |
michael@0 | 361 | // Copy using event.dataTransfer |
michael@0 | 362 | selectContentInput(); |
michael@0 | 363 | contentInput.oncopy = function(event) { |
michael@0 | 364 | ok(event instanceof ClipboardEvent, "copy event is a ClipboardEvent"); |
michael@0 | 365 | ok(event.clipboardData instanceof DataTransfer, "copy event dataTransfer is a DataTransfer"); |
michael@0 | 366 | is(event.target, contentInput, "copy event target"); |
michael@0 | 367 | is(event.clipboardData.mozItemCount, 0, "copy event mozItemCount"); |
michael@0 | 368 | is(event.clipboardData.getData("text/plain"), "", "copy event getData"); |
michael@0 | 369 | event.clipboardData.setData("text/plain", "Copied dataTransfer text"); |
michael@0 | 370 | cachedCopyData = event.clipboardData; |
michael@0 | 371 | }; |
michael@0 | 372 | try { |
michael@0 | 373 | synthesizeKey("c", {accelKey: 1}); |
michael@0 | 374 | is(getClipboardText(), "INPUT TEXT", |
michael@0 | 375 | "copy using dataTransfer on plaintext editor set clipboard correctly"); |
michael@0 | 376 | is(contentInput.value, "INPUT TEXT", |
michael@0 | 377 | "copy using dataTransfer on plaintext editor did not modify input"); |
michael@0 | 378 | } finally { |
michael@0 | 379 | contentInput.oncopy = null; |
michael@0 | 380 | } |
michael@0 | 381 | } |
michael@0 | 382 | |
michael@0 | 383 | |
michael@0 | 384 | function test_input_copy_abort_dataTransfer() { |
michael@0 | 385 | // Copy using event.dataTransfer but cancel the event. |
michael@0 | 386 | selectContentInput(); |
michael@0 | 387 | contentInput.oncopy = function(event) { |
michael@0 | 388 | event.clipboardData.setData("text/plain", "Copy dataTransfer text"); |
michael@0 | 389 | return false; |
michael@0 | 390 | }; |
michael@0 | 391 | try { |
michael@0 | 392 | synthesizeKey("x", {accelKey: 1}); |
michael@0 | 393 | is(getClipboardText(), "Copy dataTransfer text", |
michael@0 | 394 | "aborted copy using dataTransfer on plaintext editor set clipboard correctly"); |
michael@0 | 395 | is(contentInput.value, "INPUT TEXT", |
michael@0 | 396 | "aborted copy using dataTransfer on plaintext editor did not modify input"); |
michael@0 | 397 | } finally { |
michael@0 | 398 | contentInput.oncopy = null; |
michael@0 | 399 | } |
michael@0 | 400 | } |
michael@0 | 401 | |
michael@0 | 402 | |
michael@0 | 403 | function test_input_paste_dataTransfer() { |
michael@0 | 404 | // Paste using event.dataTransfer |
michael@0 | 405 | selectContentInput(); |
michael@0 | 406 | contentInput.onpaste = function(event) { |
michael@0 | 407 | ok(event instanceof ClipboardEvent, "paste event is an ClipboardEvent"); |
michael@0 | 408 | ok(event.clipboardData instanceof DataTransfer, "paste event dataTransfer is a DataTransfer"); |
michael@0 | 409 | is(event.target, contentInput, "paste event target"); |
michael@0 | 410 | is(event.clipboardData.mozItemCount, 1, "paste event mozItemCount"); |
michael@0 | 411 | is(event.clipboardData.getData("text/plain"), clipboardInitialValue, "paste event getData"); |
michael@0 | 412 | cachedPasteData = event.clipboardData; |
michael@0 | 413 | }; |
michael@0 | 414 | try { |
michael@0 | 415 | synthesizeKey("v", {accelKey: 1}); |
michael@0 | 416 | is(getClipboardText(), clipboardInitialValue, |
michael@0 | 417 | "paste using dataTransfer on plaintext editor did not modify clipboard contents"); |
michael@0 | 418 | is(contentInput.value, clipboardInitialValue, |
michael@0 | 419 | "paste using dataTransfer on plaintext editor modified input"); |
michael@0 | 420 | } finally { |
michael@0 | 421 | contentInput.onpaste = null; |
michael@0 | 422 | } |
michael@0 | 423 | } |
michael@0 | 424 | |
michael@0 | 425 | |
michael@0 | 426 | function test_input_paste_abort_dataTransfer() { |
michael@0 | 427 | // Paste using event.dataTransfer but cancel the event |
michael@0 | 428 | selectContentInput(); |
michael@0 | 429 | contentInput.onpaste = function(event) { |
michael@0 | 430 | is(event.clipboardData.getData("text/plain"), clipboardInitialValue, "get data on aborted paste"); |
michael@0 | 431 | contentInput.value = "Alternate Paste"; |
michael@0 | 432 | return false; |
michael@0 | 433 | }; |
michael@0 | 434 | try { |
michael@0 | 435 | synthesizeKey("v", {accelKey: 1}); |
michael@0 | 436 | is(getClipboardText(), clipboardInitialValue, |
michael@0 | 437 | "aborted paste using dataTransfer on plaintext editor did not modify clipboard contents"); |
michael@0 | 438 | is(contentInput.value, "Alternate Paste", |
michael@0 | 439 | "aborted paste using dataTransfer on plaintext editor modified input"); |
michael@0 | 440 | } finally { |
michael@0 | 441 | contentInput.onpaste = null; |
michael@0 | 442 | } |
michael@0 | 443 | } |
michael@0 | 444 | |
michael@0 | 445 | function test_input_copypaste_dataTransfer_multiple() { |
michael@0 | 446 | // Cut several types of data and paste it again |
michael@0 | 447 | contentInput.value = "This is a line of text"; |
michael@0 | 448 | contentInput.oncopy = function(event) { |
michael@0 | 449 | var cd = event.clipboardData; |
michael@0 | 450 | cd.setData("text/plain", "would be a phrase"); |
michael@0 | 451 | |
michael@0 | 452 | var exh = false; |
michael@0 | 453 | try { cd.mozSetDataAt("text/plain", "Text", 1); } catch (ex) { exh = true; } |
michael@0 | 454 | ok(exh, "exception occured mozSetDataAt 1"); |
michael@0 | 455 | exh = false; |
michael@0 | 456 | try { cd.mozTypesAt(1); } catch (ex) { exh = true; } |
michael@0 | 457 | ok(exh, "exception occured mozTypesAt 1"); |
michael@0 | 458 | exh = false; |
michael@0 | 459 | try { cd.mozGetDataAt("text/plain", 1); } catch (ex) { exh = true; } |
michael@0 | 460 | ok(exh, "exception occured mozGetDataAt 1"); |
michael@0 | 461 | exh = false; |
michael@0 | 462 | try { cd.mozClearDataAt("text/plain", 1); } catch (ex) { exh = true; } |
michael@0 | 463 | ok(exh, "exception occured mozClearDataAt 1"); |
michael@0 | 464 | |
michael@0 | 465 | cd.setData("text/x-moz-url", "http://www.mozilla.org"); |
michael@0 | 466 | cd.mozSetDataAt("text/x-custom", "Custom Text", 0); |
michael@0 | 467 | is(cd.mozItemCount, 1, "mozItemCount after set multiple types"); |
michael@0 | 468 | return false; |
michael@0 | 469 | }; |
michael@0 | 470 | |
michael@0 | 471 | try { |
michael@0 | 472 | selectContentInput(); |
michael@0 | 473 | synthesizeKey("c", {accelKey: 1}); |
michael@0 | 474 | } |
michael@0 | 475 | finally { |
michael@0 | 476 | contentInput.oncopy = null; |
michael@0 | 477 | } |
michael@0 | 478 | |
michael@0 | 479 | is(getClipboardText(), "would be a phrase", "copy multiple types text"); |
michael@0 | 480 | |
michael@0 | 481 | contentInput.setSelectionRange(5, 14); |
michael@0 | 482 | |
michael@0 | 483 | contentInput.onpaste = function(event) { |
michael@0 | 484 | var cd = event.clipboardData; |
michael@0 | 485 | is(cd.mozItemCount, 1, "paste after copy multiple types mozItemCount"); |
michael@0 | 486 | is(cd.getData("text/plain"), "would be a phrase", "paste text/plain multiple types"); |
michael@0 | 487 | |
michael@0 | 488 | // Firefox for Android's clipboard code doesn't handle x-moz-url. Therefore |
michael@0 | 489 | // disabling the following test. Enable this once bug #840101 is fixed. |
michael@0 | 490 | if (navigator.appVersion.indexOf("Android") == -1) { |
michael@0 | 491 | is(cd.getData("text/x-moz-url"), "http://www.mozilla.org", "paste text/x-moz-url multiple types"); |
michael@0 | 492 | } |
michael@0 | 493 | // this is empty because only the built-in types are supported at the moment |
michael@0 | 494 | is(cd.getData("text/x-custom"), "", "paste text/custom multiple types"); |
michael@0 | 495 | |
michael@0 | 496 | exh = false; |
michael@0 | 497 | try { cd.setData("text/plain", "Text on Paste"); } catch (ex) { exh = true; } |
michael@0 | 498 | ok(exh, "exception occured setData on paste"); |
michael@0 | 499 | |
michael@0 | 500 | is(cd.getData("text/plain"), "would be a phrase", "text/plain data unchanged"); |
michael@0 | 501 | }; |
michael@0 | 502 | try { |
michael@0 | 503 | synthesizeKey("v", {accelKey: 1}); |
michael@0 | 504 | is(contentInput.value, "This would be a phrase of text", |
michael@0 | 505 | "default paste after copy multiple types"); |
michael@0 | 506 | } finally { |
michael@0 | 507 | contentInput.onpaste = null; |
michael@0 | 508 | } |
michael@0 | 509 | } |
michael@0 | 510 | |
michael@0 | 511 | function test_input_copy_button_dataTransfer() { |
michael@0 | 512 | // Copy using event.dataTransfer when a button is focused. |
michael@0 | 513 | var button = document.getElementById("button"); |
michael@0 | 514 | button.focus(); |
michael@0 | 515 | button.oncopy = function(event) { |
michael@0 | 516 | ok(false, "should not be firing copy event on button"); |
michael@0 | 517 | return false; |
michael@0 | 518 | }; |
michael@0 | 519 | try { |
michael@0 | 520 | // copy should not occur here because buttons don't have any controller |
michael@0 | 521 | // for the copy command |
michael@0 | 522 | synthesizeKey("c", {accelKey: 1}); |
michael@0 | 523 | is(getClipboardText(), clipboardInitialValue, |
michael@0 | 524 | "copy using dataTransfer on plaintext editor set clipboard correctly for button"); |
michael@0 | 525 | |
michael@0 | 526 | selectContentDiv(); |
michael@0 | 527 | synthesizeKey("c", {accelKey: 1}); |
michael@0 | 528 | is(getClipboardText(), "CONTENT TEXT", |
michael@0 | 529 | "copy using dataTransfer with selection on plaintext editor set clipboard correctly for button"); |
michael@0 | 530 | |
michael@0 | 531 | } finally { |
michael@0 | 532 | document.documentElement.oncopy = null; |
michael@0 | 533 | } |
michael@0 | 534 | } |
michael@0 | 535 | |
michael@0 | 536 | function test_eventspref_disabled() { |
michael@0 | 537 | // Disable clipboard events |
michael@0 | 538 | SpecialPowers.setBoolPref("dom.event.clipboardevents.enabled", false); |
michael@0 | 539 | |
michael@0 | 540 | var event_fired = false; |
michael@0 | 541 | contentInput.oncut = function() { event_fired = true; }; |
michael@0 | 542 | contentInput.oncopy = function() { event_fired = true; }; |
michael@0 | 543 | contentInput.onpaste = function() { event_fired = true; }; |
michael@0 | 544 | try { |
michael@0 | 545 | selectContentInput(); |
michael@0 | 546 | contentInput.setSelectionRange(1, 4); |
michael@0 | 547 | synthesizeKey("x", {accelKey: 1}); |
michael@0 | 548 | is(contentInput.value, "IT TEXT", "cut changed text when preference is disabled"); |
michael@0 | 549 | is(getClipboardText(), "NPU", "cut changed clipboard when preference is disabled"); |
michael@0 | 550 | ok(!event_fired, "cut event did not fire when preference is disabled") |
michael@0 | 551 | |
michael@0 | 552 | event_fired = false; |
michael@0 | 553 | contentInput.setSelectionRange(3, 6); |
michael@0 | 554 | synthesizeKey("c", {accelKey: 1}); |
michael@0 | 555 | is(getClipboardText(), "TEX", "copy changed clipboard when preference is disabled"); |
michael@0 | 556 | ok(!event_fired, "copy event did not fire when preference is disabled") |
michael@0 | 557 | |
michael@0 | 558 | event_fired = false; |
michael@0 | 559 | contentInput.setSelectionRange(0, 2); |
michael@0 | 560 | synthesizeKey("v", {accelKey: 1}); |
michael@0 | 561 | is(contentInput.value, "TEX TEXT", "paste changed text when preference is disabled"); |
michael@0 | 562 | ok(!event_fired, "paste event did not fire when preference is disabled") |
michael@0 | 563 | } finally { |
michael@0 | 564 | contentInput.oncut = null; |
michael@0 | 565 | contentInput.oncopy = null; |
michael@0 | 566 | contentInput.onpaste = null; |
michael@0 | 567 | } |
michael@0 | 568 | |
michael@0 | 569 | SpecialPowers.clearUserPref("dom.event.clipboardevents.enabled"); |
michael@0 | 570 | } |
michael@0 | 571 | |
michael@0 | 572 | let expectedData = []; |
michael@0 | 573 | |
michael@0 | 574 | // Check to make that synthetic events do not change the clipboard |
michael@0 | 575 | function checkSyntheticEvents() |
michael@0 | 576 | { |
michael@0 | 577 | let syntheticSpot = document.getElementById("syntheticSpot"); |
michael@0 | 578 | setClipboardText(clipboardInitialValue); |
michael@0 | 579 | |
michael@0 | 580 | // No dataType specified |
michael@0 | 581 | let event = new ClipboardEvent("cut", { data: "something" }); |
michael@0 | 582 | expectedData = { type: "cut", data: null } |
michael@0 | 583 | compareSynthetic(event, "before"); |
michael@0 | 584 | syntheticSpot.dispatchEvent(event); |
michael@0 | 585 | ok(expectedData.eventFired, "cut event fired"); |
michael@0 | 586 | compareSynthetic(event, "after"); |
michael@0 | 587 | |
michael@0 | 588 | event = new ClipboardEvent("cut", { dataType: "text/plain", data: "something" }); |
michael@0 | 589 | expectedData = { type: "cut", dataType: "text/plain", data: "something" } |
michael@0 | 590 | compareSynthetic(event, "before"); |
michael@0 | 591 | syntheticSpot.dispatchEvent(event); |
michael@0 | 592 | ok(expectedData.eventFired, "cut event fired"); |
michael@0 | 593 | compareSynthetic(event, "after"); |
michael@0 | 594 | |
michael@0 | 595 | event = new ClipboardEvent("copy", { dataType: "text/plain", data: "something" }); |
michael@0 | 596 | expectedData = { type: "copy", dataType: "text/plain", data: "something" } |
michael@0 | 597 | compareSynthetic(event, "before"); |
michael@0 | 598 | syntheticSpot.dispatchEvent(event); |
michael@0 | 599 | ok(expectedData.eventFired, "copy event fired"); |
michael@0 | 600 | compareSynthetic(event, "after"); |
michael@0 | 601 | |
michael@0 | 602 | event = new ClipboardEvent("copy", { dataType: "text/plain" }); |
michael@0 | 603 | expectedData = { type: "copy", dataType: "text/plain", data: "" } |
michael@0 | 604 | compareSynthetic(event, "before"); |
michael@0 | 605 | syntheticSpot.dispatchEvent(event); |
michael@0 | 606 | ok(expectedData.eventFired, "copy event fired"); |
michael@0 | 607 | compareSynthetic(event, "after"); |
michael@0 | 608 | |
michael@0 | 609 | event = new ClipboardEvent("paste", { dataType: "text/plain", data: "something" }); |
michael@0 | 610 | expectedData = { type: "paste", dataType: "text/plain", data: "something" } |
michael@0 | 611 | compareSynthetic(event, "before"); |
michael@0 | 612 | syntheticSpot.dispatchEvent(event); |
michael@0 | 613 | ok(expectedData.eventFired, "paste event fired"); |
michael@0 | 614 | compareSynthetic(event, "after"); |
michael@0 | 615 | |
michael@0 | 616 | event = new ClipboardEvent("paste", { dataType: "application/unknown", data: "unknown" }); |
michael@0 | 617 | expectedData = { type: "paste", dataType: "application/unknown", data: "unknown" } |
michael@0 | 618 | compareSynthetic(event, "before"); |
michael@0 | 619 | syntheticSpot.dispatchEvent(event); |
michael@0 | 620 | ok(expectedData.eventFired, "paste event fired"); |
michael@0 | 621 | compareSynthetic(event, "after"); |
michael@0 | 622 | } |
michael@0 | 623 | |
michael@0 | 624 | function compareSynthetic(event, eventtype) |
michael@0 | 625 | { |
michael@0 | 626 | let step = (eventtype == "cut" || eventtype == "copy" || eventtype == "paste") ? "during" : eventtype; |
michael@0 | 627 | if (step == "during") { |
michael@0 | 628 | is(eventtype, expectedData.type, "synthetic " + eventtype + " event fired"); |
michael@0 | 629 | } |
michael@0 | 630 | |
michael@0 | 631 | ok(event.clipboardData instanceof DataTransfer, "clipboardData is assigned"); |
michael@0 | 632 | |
michael@0 | 633 | is(event.type, expectedData.type, "synthetic " + eventtype + " event type"); |
michael@0 | 634 | if (expectedData.data === null) { |
michael@0 | 635 | is(event.clipboardData.mozItemCount, 0, "synthetic " + eventtype + " empty data"); |
michael@0 | 636 | } |
michael@0 | 637 | else { |
michael@0 | 638 | is(event.clipboardData.mozItemCount, 1, "synthetic " + eventtype + " item count"); |
michael@0 | 639 | is(event.clipboardData.types.length, 1, "synthetic " + eventtype + " types length"); |
michael@0 | 640 | is(event.clipboardData.getData(expectedData.dataType), expectedData.data, |
michael@0 | 641 | "synthetic " + eventtype + " data"); |
michael@0 | 642 | } |
michael@0 | 643 | |
michael@0 | 644 | is(getClipboardText(), "empty", "event does not change the clipboard " + step + " dispatch"); |
michael@0 | 645 | |
michael@0 | 646 | if (step == "during") { |
michael@0 | 647 | expectedData.eventFired = true; |
michael@0 | 648 | } |
michael@0 | 649 | } |
michael@0 | 650 | |
michael@0 | 651 | function checkCachedDataTransfer(cd, eventtype) |
michael@0 | 652 | { |
michael@0 | 653 | var testprefix = "cached " + eventtype + " dataTransfer"; |
michael@0 | 654 | |
michael@0 | 655 | setClipboardText("Some Clipboard Text"); |
michael@0 | 656 | |
michael@0 | 657 | var oldtext = cd.getData("text/plain"); |
michael@0 | 658 | ok(oldtext != "Some Clipboard Text", "clipboard get using " + testprefix); |
michael@0 | 659 | |
michael@0 | 660 | var exh = false; |
michael@0 | 661 | try { cd.mozSetDataAt("text/plain", "Test Cache Data", 0); } catch (ex) { exh = true; } |
michael@0 | 662 | ok(eventtype == "paste" ? exh : !exh, "exception occured setting " + testprefix); |
michael@0 | 663 | |
michael@0 | 664 | var newtext = (eventtype == "paste") ? cd.getData("text/plain") : |
michael@0 | 665 | cd.mozGetDataAt("text/plain", 0); |
michael@0 | 666 | is(newtext, (eventtype == "paste") ? "" : "Test Cache Data", |
michael@0 | 667 | " clipboardData not changed using " + testprefix); |
michael@0 | 668 | |
michael@0 | 669 | is(getClipboardText(), "Some Clipboard Text", "clipboard not changed using " + testprefix); |
michael@0 | 670 | |
michael@0 | 671 | var exh = false; |
michael@0 | 672 | try { cd.mozClearDataAt("text/plain", 0); } catch (ex) { exh = true; } |
michael@0 | 673 | ok(eventtype == "paste" ? exh : !exh, "exception occured clearing " + testprefix); |
michael@0 | 674 | |
michael@0 | 675 | is(getClipboardText(), "Some Clipboard Text", "clipboard not changed using " + testprefix); |
michael@0 | 676 | } |
michael@0 | 677 | |
michael@0 | 678 | </script> |
michael@0 | 679 | </pre> |
michael@0 | 680 | </body> |
michael@0 | 681 | </html> |
michael@0 | 682 |