browser_document_command_paste_contextmenu_ext.js (11442B)
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 = kBaseUrlForContent + "simple_page_ext.html"; 10 11 async function promiseExecCommandPasteFromExtension(aBrowser, aExtension) { 12 await SpecialPowers.spawn(aBrowser, [], async () => { 13 content.document.notifyUserGestureActivation(); 14 }); 15 16 aExtension.sendMessage("paste"); 17 return await aExtension.awaitMessage("result"); 18 } 19 20 async function execCommandPasteFromExtensionWithoutResult( 21 aBrowser, 22 aExtension 23 ) { 24 await SpecialPowers.spawn(aBrowser, [], async () => { 25 content.document.notifyUserGestureActivation(); 26 }); 27 28 aExtension.sendMessage("pasteWithoutResult"); 29 } 30 31 add_setup(async function () { 32 await SpecialPowers.pushPrefEnv({ 33 set: [ 34 ["test.events.async.enabled", true], 35 // Disable the paste contextmenu delay to make the test run faster. 36 ["security.dialog_enable_delay", 0], 37 ], 38 }); 39 }); 40 41 kPasteCommandTests.forEach(test => { 42 describe(test.description, () => { 43 const contentScript = function () { 44 browser.test.onMessage.addListener(async aMsg => { 45 if (aMsg === "paste") { 46 let clipboardData = null; 47 document.addEventListener( 48 "paste", 49 e => { 50 clipboardData = e.clipboardData.getData("text/plain"); 51 }, 52 { once: true } 53 ); 54 55 const execCommandResult = document.execCommand("paste"); 56 browser.test.sendMessage("result", { 57 execCommandResult, 58 clipboardData, 59 }); 60 } else if (aMsg === "pasteWithoutResult") { 61 setTimeout(() => { 62 document.execCommand("paste"); 63 }, 0); 64 } 65 }); 66 }; 67 const extensionData = { 68 manifest: { 69 content_scripts: [ 70 { 71 js: ["contentscript.js"], 72 matches: ["https://example.com/*"], 73 }, 74 ], 75 }, 76 files: { 77 "contentscript.js": contentScript, 78 }, 79 }; 80 81 it("Accepting paste contextmenu", async () => { 82 info(`Randomized text to avoid overlappings with other tests`); 83 const clipboardText = await promiseWritingRandomTextToClipboard(); 84 85 info(`Load and start the extension`); 86 const extension = ExtensionTestUtils.loadExtension(extensionData); 87 await extension.startup(); 88 89 await BrowserTestUtils.withNewTab( 90 kContentFileUrl, 91 async function (aBrowser) { 92 if (test.setupFn) { 93 info(`Setup`); 94 await test.setupFn(aBrowser); 95 } 96 97 const pasteButtonIsShown = promisePasteButtonIsShown(); 98 99 info(`Trigger execCommand("paste") from extension`); 100 const pasteCommandResult = promiseExecCommandPasteFromExtension( 101 aBrowser, 102 extension 103 ); 104 105 info(`Wait for paste context menu is shown`); 106 await pasteButtonIsShown; 107 108 info(`Click paste context menu`); 109 const pasteButtonIsHidden = promisePasteButtonIsHidden(); 110 await promiseClickPasteButton(); 111 await pasteButtonIsHidden; 112 113 const { execCommandResult, clipboardData } = await pasteCommandResult; 114 ok(execCommandResult, `execCommand("paste") should be succeed`); 115 is(clipboardData, clipboardText, `Check clipboard data`); 116 117 if (test.additionalCheckFunc) { 118 info(`Additional checks`); 119 await test.additionalCheckFunc(aBrowser, clipboardText); 120 } 121 } 122 ); 123 124 info(`Unload extension`); 125 await extension.unload(); 126 }); 127 128 it("Dismissing paste contextmenu", async () => { 129 info(`Randomized text to avoid overlappings with other tests`); 130 await promiseWritingRandomTextToClipboard(); 131 132 info(`Load and start the extension`); 133 const extension = ExtensionTestUtils.loadExtension(extensionData); 134 await extension.startup(); 135 136 await BrowserTestUtils.withNewTab( 137 kContentFileUrl, 138 async function (aBrowser) { 139 if (test.setupFn) { 140 info(`Setup`); 141 await test.setupFn(aBrowser); 142 } 143 144 const pasteButtonIsShown = promisePasteButtonIsShown(); 145 146 info(`Trigger execCommand("paste") from extension`); 147 const pasteCommandResult = promiseExecCommandPasteFromExtension( 148 aBrowser, 149 extension 150 ); 151 152 info(`Wait for paste context menu is shown`); 153 await pasteButtonIsShown; 154 155 info(`Dismiss paste context menu`); 156 const pasteButtonIsHidden = promisePasteButtonIsHidden(); 157 await promiseDismissPasteButton(); 158 await pasteButtonIsHidden; 159 160 const { execCommandResult, clipboardData } = await pasteCommandResult; 161 ok(!execCommandResult, `execCommand("paste") should not be succeed`); 162 is(clipboardData, null, `Check clipboard data`); 163 164 if (test.additionalCheckFunc) { 165 info(`Additional checks`); 166 await test.additionalCheckFunc(aBrowser, ""); 167 } 168 } 169 ); 170 171 info(`Unload extension`); 172 await extension.unload(); 173 }); 174 175 it("Tab close", async () => { 176 info(`Randomized text to avoid overlappings with other tests`); 177 await promiseWritingRandomTextToClipboard(); 178 179 info(`Load and start the extension`); 180 const extension = ExtensionTestUtils.loadExtension(extensionData); 181 await extension.startup(); 182 183 let pasteButtonIsHidden; 184 await BrowserTestUtils.withNewTab( 185 kContentFileUrl, 186 async function (aBrowser) { 187 if (test.setupFn) { 188 info(`Setup`); 189 await test.setupFn(aBrowser); 190 } 191 192 const pasteButtonIsShown = promisePasteButtonIsShown(); 193 194 info(`Trigger execCommand("paste") from extension`); 195 execCommandPasteFromExtensionWithoutResult(aBrowser, extension); 196 197 info(`Wait for paste context menu is shown`); 198 await pasteButtonIsShown; 199 200 pasteButtonIsHidden = promisePasteButtonIsHidden(); 201 info("Close tab"); 202 } 203 ); 204 205 await pasteButtonIsHidden; 206 207 info(`Unload extension`); 208 await extension.unload(); 209 }); 210 211 it("Tab switch", async () => { 212 info(`Randomized text to avoid overlappings with other tests`); 213 await promiseWritingRandomTextToClipboard(); 214 215 info(`Load and start the extension`); 216 const extension = ExtensionTestUtils.loadExtension(extensionData); 217 await extension.startup(); 218 219 await BrowserTestUtils.withNewTab( 220 kContentFileUrl, 221 async function (aBrowser) { 222 if (test.setupFn) { 223 info(`Setup`); 224 await test.setupFn(aBrowser); 225 } 226 227 const pasteButtonIsShown = promisePasteButtonIsShown(); 228 229 info(`Trigger execCommand("paste") from extension`); 230 execCommandPasteFromExtensionWithoutResult(aBrowser, extension); 231 232 info(`Wait for paste context menu is shown`); 233 await pasteButtonIsShown; 234 235 info("Switch tab"); 236 let pasteButtonIsHidden = promisePasteButtonIsHidden(); 237 let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); 238 239 info(`Wait for paste context menu is hidden`); 240 await pasteButtonIsHidden; 241 242 BrowserTestUtils.removeTab(tab); 243 } 244 ); 245 246 info(`Unload extension`); 247 await extension.unload(); 248 }); 249 250 it("Window switch", async () => { 251 info(`Randomized text to avoid overlappings with other tests`); 252 await promiseWritingRandomTextToClipboard(); 253 254 info(`Load and start the extension`); 255 const extension = ExtensionTestUtils.loadExtension(extensionData); 256 await extension.startup(); 257 258 await BrowserTestUtils.withNewTab( 259 kContentFileUrl, 260 async function (aBrowser) { 261 if (test.setupFn) { 262 info(`Setup`); 263 await test.setupFn(aBrowser); 264 } 265 266 const pasteButtonIsShown = promisePasteButtonIsShown(); 267 268 info(`Trigger execCommand("paste") from extension`); 269 execCommandPasteFromExtensionWithoutResult(aBrowser, extension); 270 271 info(`Wait for paste context menu is shown`); 272 await pasteButtonIsShown; 273 274 info("Switch browser window"); 275 let pasteButtonIsHidden = promisePasteButtonIsHidden(); 276 let newWin = await BrowserTestUtils.openNewBrowserWindow(); 277 278 info(`Wait for paste context menu is hidden`); 279 await pasteButtonIsHidden; 280 281 await BrowserTestUtils.closeWindow(newWin); 282 } 283 ); 284 285 info(`Unload extension`); 286 await extension.unload(); 287 }); 288 289 it("Tab navigate", async () => { 290 info(`Randomized text to avoid overlappings with other tests`); 291 await promiseWritingRandomTextToClipboard(); 292 293 info(`Load and start the extension`); 294 const extension = ExtensionTestUtils.loadExtension(extensionData); 295 await extension.startup(); 296 297 await BrowserTestUtils.withNewTab( 298 kContentFileUrl, 299 async function (aBrowser) { 300 if (test.setupFn) { 301 info(`Setup`); 302 await test.setupFn(aBrowser); 303 } 304 305 const pasteButtonIsShown = promisePasteButtonIsShown(); 306 307 info(`Trigger execCommand("paste") from extension`); 308 execCommandPasteFromExtensionWithoutResult(aBrowser, extension); 309 310 info(`Wait for paste context menu is shown`); 311 await pasteButtonIsShown; 312 313 info("Navigate tab"); 314 let pasteButtonIsHidden = promisePasteButtonIsHidden(); 315 aBrowser.loadURI(Services.io.newURI("https://example.com/"), { 316 triggeringPrincipal: 317 Services.scriptSecurityManager.getSystemPrincipal(), 318 }); 319 320 info(`Wait for paste context menu is hidden`); 321 await pasteButtonIsHidden; 322 } 323 ); 324 325 info(`Unload extension`); 326 await extension.unload(); 327 }); 328 329 it("Tab reload", async () => { 330 info(`Randomized text to avoid overlappings with other tests`); 331 await promiseWritingRandomTextToClipboard(); 332 333 info(`Load and start the extension`); 334 const extension = ExtensionTestUtils.loadExtension(extensionData); 335 await extension.startup(); 336 337 await BrowserTestUtils.withNewTab( 338 kContentFileUrl, 339 async function (aBrowser) { 340 if (test.setupFn) { 341 info(`Setup`); 342 await test.setupFn(aBrowser); 343 } 344 345 const pasteButtonIsShown = promisePasteButtonIsShown(); 346 347 info(`Trigger execCommand("paste") from extension`); 348 execCommandPasteFromExtensionWithoutResult(aBrowser, extension); 349 350 info(`Wait for paste context menu is shown`); 351 await pasteButtonIsShown; 352 353 info("Reload tab"); 354 let pasteButtonIsHidden = promisePasteButtonIsHidden(); 355 await BrowserTestUtils.reloadTab(gBrowser.selectedTab); 356 357 info(`Wait for paste context menu is hidden`); 358 await pasteButtonIsHidden; 359 } 360 ); 361 362 info(`Unload extension`); 363 await extension.unload(); 364 }); 365 }); 366 });