browser_connectToFrame.js (4480B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 /** 5 * Test `connectToFrame` method 6 */ 7 8 "use strict"; 9 10 const { 11 connectToFrame, 12 } = require("resource://devtools/server/connectors/frame-connector.js"); 13 14 add_task(async function () { 15 // Create a minimal browser with a message manager 16 const browser = document.createXULElement("browser"); 17 browser.setAttribute("type", "content"); 18 document.body.appendChild(browser); 19 20 await TestUtils.waitForCondition( 21 () => browser.browsingContext.currentWindowGlobal, 22 "browser has no window global" 23 ); 24 25 // Register a test actor in the child process so that we can know if and when 26 // this fake actor is destroyed. 27 await SpecialPowers.spawn(browser, [], () => { 28 const { require } = ChromeUtils.importESModule( 29 "resource://devtools/shared/loader/Loader.sys.mjs" 30 ); 31 const { 32 DevToolsServer, 33 } = require("resource://devtools/server/devtools-server.js"); 34 const { 35 ActorRegistry, 36 } = require("resource://devtools/server/actors/utils/actor-registry.js"); 37 38 DevToolsServer.init(); 39 40 const { Actor } = require("resource://devtools/shared/protocol/Actor.js"); 41 class ConnectToFrameTestActor extends Actor { 42 constructor(conn) { 43 super(conn, { typeName: "connectToFrameTest", methods: [] }); 44 dump("instantiate test actor\n"); 45 this.requestTypes = { 46 hello: this.hello, 47 }; 48 } 49 hello() { 50 return { msg: "world" }; 51 } 52 53 destroy() { 54 SpecialPowers.notifyObserversInParentProcess( 55 null, 56 "devtools-test-actor-destroyed", 57 "" 58 ); 59 } 60 } 61 62 ActorRegistry.addTargetScopedActor( 63 { 64 constructorName: "ConnectToFrameTestActor", 65 constructorFun: ConnectToFrameTestActor, 66 }, 67 "connectToFrameTestActor" 68 ); 69 }); 70 71 // Instantiate a minimal server 72 DevToolsServer.init(); 73 if (!DevToolsServer.createRootActor) { 74 DevToolsServer.registerAllActors(); 75 } 76 77 async function initAndCloseFirstClient() { 78 // Fake a first connection to a browser 79 const transport = DevToolsServer.connectPipe(); 80 const conn = transport._serverConnection; 81 const client = new DevToolsClient(transport); 82 // We aren't calling DevtoolsClient.connect, but still need to wait for the client to be connected 83 await client.once("connected"); 84 const actor = await connectToFrame(conn, browser); 85 ok(actor.connectToFrameTestActor, "Got the test actor"); 86 87 // Ensure sending at least one request to our actor, 88 // otherwise it won't be instantiated, nor be destroyed... 89 await client.request({ 90 to: actor.connectToFrameTestActor, 91 type: "hello", 92 }); 93 94 // Connect a second client in parallel to assert that it received a distinct set of 95 // target actors 96 await initAndCloseSecondClient(actor.connectToFrameTestActor); 97 98 ok( 99 DevToolsServer.initialized, 100 "DevToolsServer isn't destroyed until all clients are disconnected" 101 ); 102 103 // Ensure that our test actor got cleaned up; 104 // its destroy method should be called 105 const onActorDestroyed = TestUtils.topicObserved( 106 "devtools-test-actor-destroyed" 107 ); 108 109 // Then close the client. That should end up cleaning our test actor 110 await client.close(); 111 112 await onActorDestroyed; 113 114 // This test loads a frame in the parent process, so that we end up sharing the same 115 // DevToolsServer instance 116 ok( 117 !DevToolsServer.initialized, 118 "DevToolsServer is destroyed when all clients are disconnected" 119 ); 120 } 121 122 async function initAndCloseSecondClient(firstActor) { 123 // Then fake a second one, that should spawn a new set of target-scoped actors 124 const transport = DevToolsServer.connectPipe(); 125 const conn = transport._serverConnection; 126 const client = new DevToolsClient(transport); 127 // We aren't calling DevtoolsClient.connect, but still need to wait for the client to be connected 128 await client.once("connected"); 129 const actor = await connectToFrame(conn, browser); 130 ok( 131 actor.connectToFrameTestActor, 132 "Got a test actor for the second connection" 133 ); 134 isnot( 135 actor.connectToFrameTestActor, 136 firstActor, 137 "We get different actor instances between two connections" 138 ); 139 return client.close(); 140 } 141 142 await initAndCloseFirstClient(); 143 144 DevToolsServer.destroy(); 145 browser.remove(); 146 });