browser_document_command_paste.js (12587B)
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 add_setup(async function init() { 12 await SpecialPowers.pushPrefEnv({ 13 // This to turn off the paste contextmenu for testing. 14 set: [["dom.events.testing.asyncClipboard", true]], 15 }); 16 }); 17 18 [true, false].forEach(aPrefValue => { 19 describe(`dom.execCommand.paste.enabled=${aPrefValue}`, () => { 20 it("set preference", async () => { 21 await SpecialPowers.pushPrefEnv({ 22 set: [["dom.execCommand.paste.enabled", aPrefValue]], 23 }); 24 }); 25 26 describe("test paste comment", () => { 27 beforeEach(async () => { 28 info("Write random text to clipboard"); 29 await promiseWritingRandomTextToClipboard(); 30 }); 31 32 it(`called from system principal`, async () => { 33 document.clearUserGestureActivation(); 34 ok( 35 document.queryCommandSupported("paste"), 36 "Check if the 'paste' command is supported" 37 ); 38 39 // Test without editing. 40 ok( 41 !document.queryCommandEnabled("paste"), 42 "Check if the 'paste' command is enabled without editing" 43 ); 44 ok( 45 !document.execCommand("paste"), 46 "Check if the 'paste' command is succeed without editing" 47 ); 48 49 // Test with editing. 50 const textArea = document.createElement("textarea"); 51 document.body.appendChild(textArea); 52 textArea.textContent = "textarea text"; 53 textArea.setSelectionRange(0, textArea.value.length); 54 textArea.focus(); 55 ok( 56 document.queryCommandEnabled("paste"), 57 "Check if the 'paste' command is enabled when editing" 58 ); 59 ok( 60 document.execCommand("paste"), 61 "Check if the 'paste' command is succeed when editing" 62 ); 63 textArea.remove(); 64 }); 65 66 it(`called from web content`, async () => { 67 await BrowserTestUtils.withNewTab(kContentFileUrl, async browser => { 68 await SpecialPowers.spawn(browser, [aPrefValue], async aPrefValue => { 69 const doc = Cu.waiveXrays(content.document); 70 is( 71 doc.queryCommandSupported("paste"), 72 aPrefValue, 73 `Check if the 'paste' command is supported` 74 ); 75 76 // Test no user activation. 77 content.document.clearUserGestureActivation(); 78 ok( 79 !doc.queryCommandEnabled("paste"), 80 "Check if the 'paste' command is enabled without user activation" 81 ); 82 ok( 83 !doc.execCommand("paste"), 84 "Check if the 'paste' command is succeed without user activation" 85 ); 86 87 // Test with user activation. 88 content.document.notifyUserGestureActivation(); 89 is( 90 doc.queryCommandEnabled("paste"), 91 aPrefValue, 92 "Check if the 'paste' command is enabled with user activation" 93 ); 94 is( 95 doc.execCommand("paste"), 96 aPrefValue, 97 "Check if the 'paste' command is succeed with user activation" 98 ); 99 100 // Test with editing. 101 const textArea = content.document.createElement("textarea"); 102 content.document.body.appendChild(textArea); 103 textArea.textContent = "textarea text"; 104 textArea.setSelectionRange(0, textArea.value.length); 105 textArea.focus(); 106 107 // Test no user activation. 108 content.document.clearUserGestureActivation(); 109 ok( 110 !doc.queryCommandEnabled("paste"), 111 "Check if the 'paste' command is enabled without user activation when editing" 112 ); 113 ok( 114 !doc.execCommand("paste"), 115 "Check if the 'paste' command is succeed without user activation when editing" 116 ); 117 118 // Test with user activation. 119 textArea.textContent = "textarea text"; 120 textArea.setSelectionRange(0, textArea.value.length); 121 textArea.focus(); 122 content.document.notifyUserGestureActivation(); 123 is( 124 doc.queryCommandEnabled("paste"), 125 aPrefValue, 126 "Check if the 'paste' command is enabled with user activation when editing" 127 ); 128 is( 129 doc.execCommand("paste"), 130 aPrefValue, 131 "Check if the 'paste' command is succeed with user activation when editing" 132 ); 133 }); 134 }); 135 }); 136 137 [true, false].forEach(aPermission => { 138 describe(`extension ${aPermission ? "with" : "without"} clipboardRead permission`, () => { 139 const sharedScript = function () { 140 this.testPasteCommand = function () { 141 return [ 142 document.queryCommandSupported("paste"), 143 document.queryCommandEnabled("paste"), 144 document.execCommand("paste"), 145 ]; 146 }; 147 }; 148 149 it("called from content script", async () => { 150 const contentScript = function () { 151 document 152 .querySelector("button") 153 .addEventListener("click", function (e) { 154 browser.test.sendMessage("result", testPasteCommand()); 155 }); 156 browser.test.sendMessage("ready", testPasteCommand()); 157 }; 158 const extensionData = { 159 manifest: { 160 content_scripts: [ 161 { 162 js: ["sharedScript.js", "contentscript.js"], 163 matches: ["https://example.com/*"], 164 }, 165 ], 166 }, 167 files: { 168 "sharedScript.js": sharedScript, 169 "contentscript.js": contentScript, 170 }, 171 }; 172 if (aPermission) { 173 extensionData.manifest.permissions = ["clipboardRead"]; 174 } 175 176 // Load and start the extension. 177 const extension = ExtensionTestUtils.loadExtension(extensionData); 178 await extension.startup(); 179 await BrowserTestUtils.withNewTab( 180 kContentFileUrl, 181 async browser => { 182 let [supported, enabled, succeed] = 183 await extension.awaitMessage("ready"); 184 is( 185 supported, 186 aPrefValue || aPermission, 187 "Check if the 'paste' command is supported" 188 ); 189 190 // Test no user activation. 191 is( 192 enabled, 193 aPermission, 194 "Check if the 'paste' command is enabled without user activation" 195 ); 196 is( 197 succeed, 198 aPermission, 199 "Check if the 'paste' command is succeed without user activation" 200 ); 201 202 // Click on the content to trigger user activation. 203 promiseClickContentElement(browser, "btn"); 204 [supported, enabled, succeed] = 205 await extension.awaitMessage("result"); 206 is( 207 enabled, 208 aPrefValue || aPermission, 209 "Check if the 'paste' command is enabled with user activation" 210 ); 211 is( 212 succeed, 213 aPrefValue || aPermission, 214 "Check if the 'paste' command is succeed with user activation" 215 ); 216 } 217 ); 218 await extension.unload(); 219 }); 220 221 it("called from content script when editing", async () => { 222 const contentScript = function () { 223 const textArea = document.createElement("textarea"); 224 document.body.appendChild(textArea); 225 const testPasteCommandWhenEditing = function () { 226 // Start editing. 227 textArea.textContent = "textarea text"; 228 textArea.setSelectionRange(0, textArea.value.length); 229 textArea.focus(); 230 return testPasteCommand(); 231 }; 232 document 233 .querySelector("button") 234 .addEventListener("click", function (e) { 235 browser.test.sendMessage( 236 "result", 237 testPasteCommandWhenEditing() 238 ); 239 }); 240 browser.test.sendMessage("ready", testPasteCommandWhenEditing()); 241 }; 242 const extensionData = { 243 manifest: { 244 content_scripts: [ 245 { 246 js: ["sharedScript.js", "contentscript.js"], 247 matches: ["https://example.com/*"], 248 }, 249 ], 250 }, 251 files: { 252 "sharedScript.js": sharedScript, 253 "contentscript.js": contentScript, 254 }, 255 }; 256 if (aPermission) { 257 extensionData.manifest.permissions = ["clipboardRead"]; 258 } 259 260 // Load and start the extension. 261 const extension = ExtensionTestUtils.loadExtension(extensionData); 262 await extension.startup(); 263 await BrowserTestUtils.withNewTab( 264 kContentFileUrl, 265 async browser => { 266 let [supported, enabled, succeed] = 267 await extension.awaitMessage("ready"); 268 is( 269 supported, 270 aPrefValue || aPermission, 271 "Check if the 'paste' command is supported" 272 ); 273 is( 274 enabled, 275 aPermission, 276 "Check if the 'paste' command is enabled without user activation" 277 ); 278 is( 279 succeed, 280 aPermission, 281 "Check if the 'paste' command is succeed without user activation" 282 ); 283 284 // Click on the content to trigger user activation. 285 promiseClickContentElement(browser, "btn"); 286 [supported, enabled, succeed] = 287 await extension.awaitMessage("result"); 288 is( 289 enabled, 290 aPrefValue || aPermission, 291 "Check if the 'paste' command is enabled with user activation" 292 ); 293 is( 294 succeed, 295 aPrefValue || aPermission, 296 "Check if the 'paste' command is succeed with user activation" 297 ); 298 } 299 ); 300 await extension.unload(); 301 }); 302 303 it("called from background script", async () => { 304 const backgroundScript = function () { 305 browser.test.sendMessage("ready", testPasteCommand()); 306 }; 307 const extensionData = { 308 background: [sharedScript, backgroundScript], 309 }; 310 if (aPermission) { 311 extensionData.manifest = { 312 permissions: ["clipboardRead"], 313 }; 314 } 315 316 // Load and start the extension. 317 const extension = ExtensionTestUtils.loadExtension(extensionData); 318 await extension.startup(); 319 await BrowserTestUtils.withNewTab( 320 kContentFileUrl, 321 async browser => { 322 let [supported, enabled, succeed] = 323 await extension.awaitMessage("ready"); 324 is( 325 supported, 326 aPrefValue || aPermission, 327 "Check if the 'paste' command is supported" 328 ); 329 is( 330 enabled, 331 aPermission, 332 "Check if the 'paste' command is enabled" 333 ); 334 is( 335 succeed, 336 aPermission, 337 "Check if the 'paste' command is succeed" 338 ); 339 } 340 ); 341 await extension.unload(); 342 }); 343 }); 344 }); 345 }); 346 }); 347 });