browser_navigator_clipboard_read.js (6751B)
1 /* -*- Mode: JavaScript; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 "use strict"; 8 9 const kContentFileUrl = 10 kBaseUrlForContent + "simple_navigator_clipboard_read.html"; 11 12 // @param aBrowser browser object of the content tab. 13 // @param aMultipleReadTextCalls if false, exactly one call is made, two 14 // otherwise. 15 function promiseClickContentToTriggerClipboardRead( 16 aBrowser, 17 aMultipleReadTextCalls 18 ) { 19 return promiseClickContentElement( 20 aBrowser, 21 aMultipleReadTextCalls ? "invokeReadTwiceId" : "invokeReadOnceId" 22 ); 23 } 24 25 // @param aBrowser browser object of the content tab. 26 function promiseMutatedReadResultFromContentElement(aBrowser) { 27 return promiseMutatedTextContentFromContentElement(aBrowser, "readResultId"); 28 } 29 30 add_setup(async function () { 31 await SpecialPowers.pushPrefEnv({ 32 set: [["test.events.async.enabled", true]], 33 }); 34 }); 35 36 add_task(async function test_paste_button_position() { 37 // Ensure there's text on the clipboard. 38 await promiseWritingRandomTextToClipboard(); 39 40 await BrowserTestUtils.withNewTab(kContentFileUrl, async function (browser) { 41 const pasteButtonIsShown = promisePasteButtonIsShown(); 42 const coordsOfClickInContentRelativeToScreenInDevicePixels = 43 await promiseClickContentToTriggerClipboardRead(browser, false); 44 info( 45 "coordsOfClickInContentRelativeToScreenInDevicePixels: " + 46 coordsOfClickInContentRelativeToScreenInDevicePixels.x + 47 ", " + 48 coordsOfClickInContentRelativeToScreenInDevicePixels.y 49 ); 50 51 const pasteButtonCoordsRelativeToScreenInDevicePixels = 52 await pasteButtonIsShown; 53 info( 54 "pasteButtonCoordsRelativeToScreenInDevicePixels: " + 55 pasteButtonCoordsRelativeToScreenInDevicePixels.x + 56 ", " + 57 pasteButtonCoordsRelativeToScreenInDevicePixels.y 58 ); 59 60 const mouseCoordsRelativeToScreenInDevicePixels = 61 getMouseCoordsRelativeToScreenInDevicePixels(); 62 info( 63 "mouseCoordsRelativeToScreenInDevicePixels: " + 64 mouseCoordsRelativeToScreenInDevicePixels.x + 65 ", " + 66 mouseCoordsRelativeToScreenInDevicePixels.y 67 ); 68 69 // Asserting not overlapping is important; otherwise, when the 70 // "Paste" button is shown via a `mousedown` event, the following 71 // `mouseup` event could accept the "Paste" button unnoticed by the 72 // user. 73 ok( 74 isCloselyLeftOnTopOf( 75 mouseCoordsRelativeToScreenInDevicePixels, 76 pasteButtonCoordsRelativeToScreenInDevicePixels 77 ), 78 "'Paste' button is closely left on top of the mouse pointer." 79 ); 80 ok( 81 isCloselyLeftOnTopOf( 82 coordsOfClickInContentRelativeToScreenInDevicePixels, 83 pasteButtonCoordsRelativeToScreenInDevicePixels 84 ), 85 "Coords of click in content are closely left on top of the 'Paste' button." 86 ); 87 88 // To avoid disturbing subsequent tests. 89 const pasteButtonIsHidden = promisePasteButtonIsHidden(); 90 await promiseClickPasteButton(); 91 await pasteButtonIsHidden; 92 }); 93 }); 94 95 add_task(async function test_accepting_paste_button() { 96 // Randomized text to avoid overlappings with other tests. 97 const clipboardText = await promiseWritingRandomTextToClipboard(); 98 99 await BrowserTestUtils.withNewTab(kContentFileUrl, async function (browser) { 100 const pasteButtonIsShown = promisePasteButtonIsShown(); 101 await promiseClickContentToTriggerClipboardRead(browser, false); 102 await pasteButtonIsShown; 103 const pasteButtonIsHidden = promisePasteButtonIsHidden(); 104 const mutatedReadResultFromContentElement = 105 promiseMutatedReadResultFromContentElement(browser); 106 await promiseClickPasteButton(); 107 await pasteButtonIsHidden; 108 await mutatedReadResultFromContentElement.then(value => { 109 is( 110 value, 111 "Resolved: " + clipboardText, 112 "Text returned from `navigator.clipboard.read()` is as expected." 113 ); 114 }); 115 }); 116 }); 117 118 add_task(async function test_dismissing_paste_button() { 119 await BrowserTestUtils.withNewTab(kContentFileUrl, async function (browser) { 120 const pasteButtonIsShown = promisePasteButtonIsShown(); 121 await promiseClickContentToTriggerClipboardRead(browser, false); 122 await pasteButtonIsShown; 123 const pasteButtonIsHidden = promisePasteButtonIsHidden(); 124 const mutatedReadResultFromContentElement = 125 promiseMutatedReadResultFromContentElement(browser); 126 await promiseDismissPasteButton(); 127 await pasteButtonIsHidden; 128 await mutatedReadResultFromContentElement.then(value => { 129 is( 130 value, 131 "Rejected: Clipboard read operation is not allowed.", 132 "`navigator.clipboard.read()` rejected after dismissing the 'Paste' button" 133 ); 134 }); 135 }); 136 }); 137 138 add_task( 139 async function test_multiple_read_invocations_for_same_user_activation() { 140 // Randomized text to avoid overlappings with other tests. 141 const clipboardText = await promiseWritingRandomTextToClipboard(); 142 143 await BrowserTestUtils.withNewTab( 144 kContentFileUrl, 145 async function (browser) { 146 const pasteButtonIsShown = promisePasteButtonIsShown(); 147 await promiseClickContentToTriggerClipboardRead(browser, true); 148 await pasteButtonIsShown; 149 const mutatedReadResultFromContentElement = 150 promiseMutatedReadResultFromContentElement(browser); 151 const pasteButtonIsHidden = promisePasteButtonIsHidden(); 152 await promiseClickPasteButton(); 153 await mutatedReadResultFromContentElement.then(value => { 154 is( 155 value, 156 "Resolved 1: " + clipboardText + "; Resolved 2: " + clipboardText, 157 "Two calls of `navigator.clipboard.read()` both resolved with the expected text." 158 ); 159 }); 160 161 // To avoid disturbing subsequent tests. 162 await pasteButtonIsHidden; 163 } 164 ); 165 } 166 ); 167 168 add_task(async function test_new_user_activation_shows_paste_button_again() { 169 await BrowserTestUtils.withNewTab(kContentFileUrl, async function (browser) { 170 // Ensure there's text on the clipboard. 171 await promiseWritingRandomTextToClipboard(); 172 173 for (let i = 0; i < 2; ++i) { 174 const pasteButtonIsShown = promisePasteButtonIsShown(); 175 // A click initiates a new user activation. 176 await promiseClickContentToTriggerClipboardRead(browser, false); 177 await pasteButtonIsShown; 178 179 const pasteButtonIsHidden = promisePasteButtonIsHidden(); 180 await promiseClickPasteButton(); 181 await pasteButtonIsHidden; 182 } 183 }); 184 });