browser_navigator_clipboard_readText_ext.js (7527B)
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 /* import-globals-from head.js */ 10 11 const kContentFileUrl = kBaseUrlForContent + "simple_page_ext.html"; 12 13 const sharedScript = function () { 14 this.clipboardReadText = function () { 15 return navigator.clipboard.readText().then( 16 data => { 17 browser.test.sendMessage("result", data); 18 }, 19 error => { 20 browser.test.sendMessage("result", [error.name, error.message]); 21 } 22 ); 23 }; 24 }; 25 26 let contentScript = function () { 27 document.querySelector("button").addEventListener("click", function (e) { 28 clipboardReadText(); 29 }); 30 browser.test.sendMessage("ready"); 31 }; 32 33 const backgroundScript = function () { 34 clipboardReadText(); 35 }; 36 37 add_setup(async function () { 38 await SpecialPowers.pushPrefEnv({ 39 set: [["test.events.async.enabled", true]], 40 }); 41 }); 42 43 // There’s another test that checks calling readText() without permission in 44 // toolkit/components/extensions/test/mochitest/test_ext_async_clipboard.html. 45 describe("test extension without clipboardRead permission", () => { 46 it("test content script", async function () { 47 const text = await promiseWritingRandomTextToClipboard(); 48 const extensionData = { 49 manifest: { 50 content_scripts: [ 51 { 52 js: ["sharedScript.js", "contentscript.js"], 53 matches: ["https://example.com/*"], 54 }, 55 ], 56 }, 57 files: { 58 "sharedScript.js": sharedScript, 59 "contentscript.js": contentScript, 60 }, 61 }; 62 const extension = ExtensionTestUtils.loadExtension(extensionData); 63 await extension.startup(); 64 await BrowserTestUtils.withNewTab(kContentFileUrl, async browser => { 65 await extension.awaitMessage("ready"); 66 67 // click on the content and wait for pasted button shown. 68 await Promise.all([ 69 promisePasteButtonIsShown(), 70 promiseClickContentElement(browser, "btn"), 71 ]); 72 73 // click on the paste button. 74 let resultPromise = extension.awaitMessage("result"); 75 await Promise.all([ 76 promisePasteButtonIsHidden(), 77 promiseClickPasteButton(), 78 ]); 79 is(await resultPromise, text, "check readText() result"); 80 81 // click on the content and wait for pasted button shown. 82 await Promise.all([ 83 promisePasteButtonIsShown(), 84 promiseClickContentElement(browser, "btn"), 85 ]); 86 87 // dismiss the paste button. 88 resultPromise = extension.awaitMessage("result"); 89 await Promise.all([ 90 promisePasteButtonIsHidden(), 91 promiseDismissPasteButton(), 92 ]); 93 const [name, message] = await resultPromise; 94 is(name, "NotAllowedError", "check readText() error name"); 95 is( 96 message, 97 "Clipboard read operation is not allowed.", 98 "check readText() error message" 99 ); 100 }); 101 await extension.unload(); 102 }); 103 104 describe("test background script", () => { 105 // paste button should not be shown during the test. 106 const popupShownListener = function (e) { 107 const pastePopup = document.getElementById(kPasteMenuPopupId); 108 if (e.target != pastePopup) { 109 return; 110 } 111 ok( 112 false, 113 "Paste popup should not be shown for extension with permission" 114 ); 115 promiseDismissPasteButton(); 116 }; 117 beforeEach(() => { 118 document.addEventListener("popupshown", popupShownListener); 119 }); 120 afterEach(() => { 121 document.removeEventListener("popupshown", popupShownListener); 122 }); 123 124 it("test without user activation", async function () { 125 const text = await promiseWritingRandomTextToClipboard(); 126 const extensionData = { 127 background: [sharedScript, backgroundScript], 128 }; 129 const extension = ExtensionTestUtils.loadExtension(extensionData); 130 await extension.startup(); 131 const [name, message] = await extension.awaitMessage("result"); 132 is(name, "NotAllowedError", "check readText() error name"); 133 is( 134 message, 135 "Clipboard read request was blocked due to lack of user activation.", 136 "check readText() error message" 137 ); 138 await extension.unload(); 139 }); 140 141 it("test with user activation", async function () { 142 const backgroundScriptWithUserActivation = function () { 143 browser.test.withHandlingUserInput(() => { 144 clipboardReadText(); 145 }); 146 }; 147 const text = await promiseWritingRandomTextToClipboard(); 148 const extensionData = { 149 background: [sharedScript, backgroundScriptWithUserActivation], 150 }; 151 const extension = ExtensionTestUtils.loadExtension(extensionData); 152 await extension.startup(); 153 const [name, message] = await extension.awaitMessage("result"); 154 is(name, "NotAllowedError", "check readText() error name"); 155 is( 156 message, 157 "Clipboard read operation is not allowed.", 158 "check readText() error message" 159 ); 160 await extension.unload(); 161 }); 162 }); 163 }); 164 165 // There’s another test that checks calling readText() with permission in 166 // toolkit/components/extensions/test/mochitest/test_ext_async_clipboard.html. 167 describe("test extension with clipboardRead permission", () => { 168 // paste button should not be shown during the test. 169 const popupShownListener = function (e) { 170 const pastePopup = document.getElementById(kPasteMenuPopupId); 171 if (e.target != pastePopup) { 172 return; 173 } 174 ok(false, "Paste popup should not be shown for extension with permission"); 175 promiseDismissPasteButton(); 176 }; 177 beforeEach(() => { 178 document.addEventListener("popupshown", popupShownListener); 179 }); 180 afterEach(() => { 181 document.removeEventListener("popupshown", popupShownListener); 182 }); 183 184 it("test content script", async function () { 185 const text = await promiseWritingRandomTextToClipboard(); 186 const extensionData = { 187 manifest: { 188 content_scripts: [ 189 { 190 js: ["sharedScript.js", "contentscript.js"], 191 matches: ["https://example.com/*"], 192 }, 193 ], 194 permissions: ["clipboardRead"], 195 }, 196 files: { 197 "sharedScript.js": sharedScript, 198 "contentscript.js": contentScript, 199 }, 200 }; 201 const extension = ExtensionTestUtils.loadExtension(extensionData); 202 await extension.startup(); 203 await BrowserTestUtils.withNewTab(kContentFileUrl, async browser => { 204 await extension.awaitMessage("ready"); 205 206 // extension with clipboardRead permission should not show paste button. 207 const resultPromise = extension.awaitMessage("result"); 208 await promiseClickContentElement(browser, "btn"); 209 is(await resultPromise, text, "check readText() result"); 210 }); 211 await extension.unload(); 212 }); 213 214 it("test background script", async function () { 215 const text = await promiseWritingRandomTextToClipboard(); 216 const extensionData = { 217 background: [sharedScript, backgroundScript], 218 manifest: { 219 permissions: ["clipboardRead"], 220 }, 221 }; 222 const extension = ExtensionTestUtils.loadExtension(extensionData); 223 await extension.startup(); 224 is(await extension.awaitMessage("result"), text, "check readText() result"); 225 await extension.unload(); 226 }); 227 });