browser_target_server_compartment.js (4255B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 // Bug 1515290 - Ensure that DevToolsServer runs in its own compartment when debugging 5 // chrome context. If not, Debugger API's addGlobal will throw when trying to attach 6 // to chrome scripts as debugger actor's module and the chrome script will be in the same 7 // compartment. Debugger and debuggee can't be running in the same compartment. 8 9 const CHROME_PAGE = 10 "chrome://mochitests/content/browser/devtools/client/framework/" + 11 "test/test_chrome_page.html"; 12 13 add_task(async function () { 14 await testChromeTab(); 15 await testMainProcess(); 16 }); 17 18 // Test that Tab Target can debug chrome pages 19 async function testChromeTab() { 20 const tab = await addTab(CHROME_PAGE); 21 const browser = tab.linkedBrowser; 22 ok(!browser.isRemoteBrowser, "chrome page is not remote"); 23 ok( 24 browser.contentWindow.document.nodePrincipal.isSystemPrincipal, 25 "chrome page is a privileged document" 26 ); 27 28 const onThreadActorInstantiated = new Promise(resolve => { 29 const observe = function (subject, topic) { 30 if (topic === "devtools-thread-ready") { 31 Services.obs.removeObserver(observe, "devtools-thread-ready"); 32 const threadActor = subject.wrappedJSObject; 33 resolve(threadActor); 34 } 35 }; 36 Services.obs.addObserver(observe, "devtools-thread-ready"); 37 }); 38 39 const commands = await CommandsFactory.forTab(tab); 40 await commands.targetCommand.startListening(); 41 42 const sources = []; 43 await commands.resourceCommand.watchResources( 44 [commands.resourceCommand.TYPES.SOURCE], 45 { 46 onAvailable(resources) { 47 sources.push(...resources); 48 }, 49 } 50 ); 51 ok( 52 sources.find(s => s.url == CHROME_PAGE), 53 "The thread actor is able to attach to the chrome page and its sources" 54 ); 55 56 const threadActor = await onThreadActorInstantiated; 57 const serverGlobal = Cu.getGlobalForObject(threadActor); 58 isnot( 59 loader.id, 60 serverGlobal.loader.id, 61 "The actors are loaded in a distinct loader in order for the actors to use its very own compartment" 62 ); 63 64 const onDedicatedLoaderDestroy = new Promise(resolve => { 65 const observe = function (subject, topic) { 66 if (topic === "devtools:loader:destroy") { 67 Services.obs.removeObserver(observe, "devtools:loader:destroy"); 68 resolve(); 69 } 70 }; 71 Services.obs.addObserver(observe, "devtools:loader:destroy"); 72 }); 73 74 await commands.destroy(); 75 76 // Wait for the dedicated loader used for DevToolsServer to be destroyed 77 // in order to prevent leak reports on try 78 await onDedicatedLoaderDestroy; 79 } 80 81 // Test that Main process Target can debug chrome scripts 82 async function testMainProcess() { 83 const onThreadActorInstantiated = new Promise(resolve => { 84 const observe = function (subject, topic) { 85 if (topic === "devtools-thread-ready") { 86 Services.obs.removeObserver(observe, "devtools-thread-ready"); 87 const threadActor = subject.wrappedJSObject; 88 resolve(threadActor); 89 } 90 }; 91 Services.obs.addObserver(observe, "devtools-thread-ready"); 92 }); 93 94 const client = await CommandsFactory.spawnClientToDebugSystemPrincipal(); 95 const commands = await CommandsFactory.forMainProcess({ client }); 96 await commands.targetCommand.startListening(); 97 98 const sources = []; 99 await commands.resourceCommand.watchResources( 100 [commands.resourceCommand.TYPES.SOURCE], 101 { 102 onAvailable(resources) { 103 sources.push(...resources); 104 }, 105 } 106 ); 107 ok( 108 sources.find( 109 s => s.url == "resource://devtools/client/framework/devtools.js" 110 ), 111 "The thread actor is able to attach to the chrome script, like client modules" 112 ); 113 114 const threadActor = await onThreadActorInstantiated; 115 const serverGlobal = Cu.getGlobalForObject(threadActor); 116 isnot( 117 loader.id, 118 serverGlobal.loader.id, 119 "The actors are loaded in a distinct loader in order for the actors to use its very own compartment" 120 ); 121 122 // As this target is remote (i.e. isn't a local tab) calling Target.destroy won't close 123 // the client. So do it manually here in order to ensure cleaning up the DevToolsServer 124 // spawn for this main process actor. 125 await commands.destroy(); 126 }