| <!DOCTYPE html> |
| <html> |
| <head> |
| <title>InputEvent: beforeinput shouldn't crash in removed iframe</title> |
| <script src="../../../resources/testharness.js"></script> |
| <script src="../../../resources/testharnessreport.js"></script> |
| </head> |
| <body> |
| <script> |
| test(function() { |
| assert_not_equals(window.eventSender, undefined, 'This test requires eventSender.'); |
| assert_not_equals(window.testRunner, undefined, 'This test requires testRunner.'); |
| |
| function testBeforeInputCrash(expectedBeforeInputCount, beforeInputTrigger, comments) { |
| const iframe = document.createElement('iframe'); |
| document.body.appendChild(iframe); |
| const childDocument = iframe.contentDocument; |
| childDocument.body.innerHTML = '<p id="editable" contenteditable>Foo</p>'; |
| |
| var actualBeforeInputCount = 0; |
| const editable = childDocument.getElementById('editable'); |
| editable.addEventListener('beforeinput', event => { |
| actualBeforeInputCount++; |
| if (actualBeforeInputCount == expectedBeforeInputCount && iframe.parentNode) |
| iframe.remove(); |
| }); |
| |
| editable.focus(); |
| beforeInputTrigger(childDocument, editable, iframe.contentWindow.testRunner); |
| |
| if (iframe.parentNode) |
| iframe.remove(); |
| assert_equals(actualBeforeInputCount, expectedBeforeInputCount, comments); |
| } |
| |
| // Text command. |
| testBeforeInputCrash(1, () => eventSender.keyDown('a'), 'Testing insertText "a"'); |
| testBeforeInputCrash(1, () => eventSender.keyDown('Enter', ['shiftKey']), 'Testing insertLineBreak'); |
| testBeforeInputCrash(1, () => eventSender.keyDown('Delete'), 'Testing deleteCharacterForward'); |
| |
| // Styling command. |
| testBeforeInputCrash(1, (childDocument, editable, testRunner) => { |
| var selection = childDocument.getSelection(); |
| selection.collapse(editable, 0); |
| selection.extend(editable, 1); |
| testRunner.execCommand('bold'); |
| }, 'Testing bold'); |
| |
| // Cut & Paste. |
| testBeforeInputCrash(1, (childDocument, editable, testRunner) => { |
| var selection = childDocument.getSelection(); |
| selection.collapse(editable, 0); |
| selection.extend(editable, 1); |
| eventSender.keyDown('Cut'); |
| }, 'Testing deleteByCut'); |
| testBeforeInputCrash(1, () => eventSender.keyDown('Paste'), 'Testing insertFromPaste'); |
| |
| // Undo & Redo. |
| testBeforeInputCrash(2, (childDocument, editable, testRunner) => { |
| eventSender.keyDown('a'); |
| testRunner.execCommand('undo'); |
| }, 'Testing undo'); |
| testBeforeInputCrash(3, (childDocument, editable, testRunner) => { |
| eventSender.keyDown('a'); |
| testRunner.execCommand('undo'); |
| testRunner.execCommand('redo'); |
| }, 'Testing redo'); |
| }, 'Testing beforeinput in removed iframe'); |
| |
| async_test(function(t) { |
| assert_not_equals(window.eventSender, undefined, 'This test requires eventSender.'); |
| assert_not_equals(window.testRunner, undefined, 'This test requires testRunner.'); |
| |
| function simulateDragDrop(dragElement, dropElement) { |
| eventSender.mouseMoveTo(dragElement.offsetLeft + dragElement.offsetWidth / 2, |
| dragElement.offsetTop + dragElement.offsetHeight / 2); |
| eventSender.mouseDown(); |
| eventSender.leapForward(100); |
| eventSender.mouseMoveTo(dropElement.offsetLeft + dropElement.offsetWidth / 2, |
| dropElement.offsetTop + dropElement.offsetHeight / 2); |
| eventSender.mouseUp(); |
| } |
| |
| function testDragDropCrash(inputTypeToCrash, comments, next) { |
| const iframe = document.createElement('iframe'); |
| iframe.src = '../resources/beforeinput-remove-iframe-crash-iframe.html'; |
| iframe.onload = t.step_func(() => { |
| var didFireInputTypeToCrash = false; |
| const childDocument = iframe.contentDocument; |
| const editable1 = childDocument.getElementById('editable1'); |
| const editable2 = childDocument.getElementById('editable2'); |
| childDocument.addEventListener('beforeinput', event => { |
| if (event.inputType == inputTypeToCrash) { |
| didFireInputTypeToCrash = true; |
| if (iframe.parentNode) |
| iframe.remove(); |
| } |
| }); |
| |
| simulateDragDrop(editable1, editable2); |
| |
| if (iframe.parentNode) |
| iframe.remove(); |
| assert_true(didFireInputTypeToCrash, comments); |
| next(); |
| }); |
| document.body.appendChild(iframe); |
| } |
| |
| // Test Drag&Drop. |
| t.step(() => testDragDropCrash('deleteByDrag', 'Testing deleteByDrag', |
| () => testDragDropCrash('insertFromDrop', 'Testing insertFromDrop', |
| () => t.done()))); |
| }, 'Testing beforeinput for Drag&Drop in removed iframe'); |
| </script> |
| </body> |
| </html> |