browser_target_command_content_scripts.js (5968B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 // Test the TargetCommand API around workers 7 8 const FISSION_TEST_URL = URL_ROOT_SSL + "fission_document.html"; 9 10 add_task(async function () { 11 // Disable the preloaded process as it creates processes intermittently 12 // which forces the emission of RDP requests we aren't correctly waiting for. 13 await pushPref("dom.ipc.processPrelaunch.enabled", false); 14 15 await pushPref("devtools.debugger.show-content-scripts", true); 16 17 const extension = ExtensionTestUtils.loadExtension({ 18 manifest: { 19 name: "Addon with content script", 20 content_scripts: [ 21 { 22 matches: [`https://example.com/*`], 23 js: ["content-script.js"], 24 }, 25 ], 26 }, 27 files: { 28 "content-script.js": function () { 29 // eslint-disable-next-line no-undef 30 browser.test.notifyPass("contentScriptRan"); 31 }, 32 }, 33 }); 34 35 await extension.startup(); 36 37 info("Test TargetCommand against content scripts via a tab target"); 38 const tab = await addTab(FISSION_TEST_URL); 39 40 await extension.awaitFinish("contentScriptRan"); 41 42 // Create a TargetCommand for the tab 43 const commands = await CommandsFactory.forTab(tab); 44 const targetCommand = commands.targetCommand; 45 46 await commands.targetCommand.startListening(); 47 48 const { TYPES } = targetCommand; 49 50 info("Check that getAllTargets only returns content scripts"); 51 const contentScripts = await targetCommand.getAllTargets([ 52 TYPES.CONTENT_SCRIPT, 53 ]); 54 55 is(contentScripts.length, 1, "Retrieved the content script"); 56 const [contentScript] = contentScripts; 57 Assert.stringContains(contentScript.title, "Addon with content script"); 58 59 info("Assert that watchTargets works for the existing content script"); 60 const targets = []; 61 const destroyedTargets = []; 62 const onAvailable = async ({ targetFront }) => { 63 info(`onAvailable called for ${targetFront.title}`); 64 is( 65 targetFront.targetType, 66 TYPES.CONTENT_SCRIPT, 67 "We are only notified about content script targets" 68 ); 69 ok(!targetFront.isTopLevel, "The content scripts are never top level"); 70 targets.push(targetFront); 71 info(`Handled ${targets.length} targets\n`); 72 }; 73 const onDestroyed = async ({ targetFront }) => { 74 is( 75 targetFront.targetType, 76 TYPES.CONTENT_SCRIPT, 77 "We are only notified about content script targets" 78 ); 79 destroyedTargets.push(targetFront); 80 }; 81 82 await targetCommand.watchTargets({ 83 types: [TYPES.CONTENT_SCRIPT], 84 onAvailable, 85 onDestroyed, 86 }); 87 88 is(targets.length, 1, "watchTargets notifies about a unique target"); 89 is( 90 targets[0], 91 contentScript, 92 "watchTargets reports the same target instance" 93 ); 94 95 await reloadBrowser(); 96 97 await waitFor( 98 () => destroyedTargets.length == 1, 99 "Wait for content script target to be destroyed on navigation" 100 ); 101 await waitFor( 102 () => targets.length == 2, 103 "Wait for a new content script target to be created on navigation" 104 ); 105 106 is(destroyedTargets[0], contentScript, "the previous target is destroyed"); 107 is(targets.length, 2, "a new target is notified"); 108 Assert.stringContains( 109 targets[1].title, 110 "Addon with content script", 111 "the new target is still about the same content script" 112 ); 113 114 await extension.unload(); 115 116 await waitFor( 117 () => destroyedTargets.length == 2, 118 "Content scripts are destroyed on extension destruction" 119 ); 120 121 targetCommand.unwatchTargets({ 122 types: [TYPES.CONTENT_SCRIPT], 123 onAvailable, 124 onDestroyed, 125 }); 126 targetCommand.destroy(); 127 128 BrowserTestUtils.removeTab(tab); 129 await commands.destroy(); 130 }); 131 132 // Cover the special codepath used by VS.Code which listens to CONTENT SCRIPT targets 133 // on a parent process watcher. 134 add_task(async function () { 135 info( 136 "Test TargetCommand against content scripts via multiprocess descriptor" 137 ); 138 139 await pushPref("devtools.browsertoolbox.scope", "everything"); 140 141 const extension = ExtensionTestUtils.loadExtension({ 142 manifest: { 143 name: "Addon with content script", 144 content_scripts: [ 145 { 146 matches: [`https://example.com/*`], 147 js: ["content-script.js"], 148 }, 149 ], 150 }, 151 files: { 152 "content-script.js": function () { 153 // eslint-disable-next-line no-undef 154 browser.test.notifyPass("contentScriptRan"); 155 }, 156 }, 157 }); 158 159 await extension.startup(); 160 161 const tab = await addTab(FISSION_TEST_URL); 162 163 await extension.awaitFinish("contentScriptRan"); 164 165 info(" ### Listen for content scripts"); 166 { 167 // Create a TargetCommand for the tab 168 const commands = await CommandsFactory.forMainProcess(); 169 const targetCommand = commands.targetCommand; 170 171 targetCommand.listenForContentScripts = true; 172 await targetCommand.startListening(); 173 174 const { TYPES } = targetCommand; 175 176 info("Check that getAllTargets only returns content scripts"); 177 const contentScripts = await targetCommand.getAllTargets([ 178 TYPES.CONTENT_SCRIPT, 179 ]); 180 181 is(contentScripts.length, 1, "Retrieved the content script"); 182 const [contentScript] = contentScripts; 183 Assert.stringContains(contentScript.title, "Addon with content script"); 184 185 await commands.destroy(); 186 } 187 188 info(" ### Do not listen for content script"); 189 { 190 // Create a TargetCommand for the tab 191 const commands = await CommandsFactory.forMainProcess(); 192 const targetCommand = commands.targetCommand; 193 194 targetCommand.listenForContentScripts = false; 195 await targetCommand.startListening(); 196 197 const { TYPES } = targetCommand; 198 199 info("Check that getAllTargets only returns content scripts"); 200 const contentScripts = await targetCommand.getAllTargets([ 201 TYPES.CONTENT_SCRIPT, 202 ]); 203 204 is(contentScripts.length, 0, "No content script is retrieved"); 205 206 await commands.destroy(); 207 } 208 209 await extension.unload(); 210 211 BrowserTestUtils.removeTab(tab); 212 });