tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 });