tor-browser

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

browser_resources_websocket.js (6884B)


      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 ResourceCommand API around WEBSOCKET.
      7 
      8 const ResourceCommand = require("resource://devtools/shared/commands/resource/resource-command.js");
      9 
     10 const IS_NUMBER = "IS_NUMBER";
     11 const SHOULD_EXIST = "SHOULD_EXIST";
     12 
     13 const targets = {
     14  TOP_LEVEL_DOCUMENT: "top-level-document",
     15  IN_PROCESS_IFRAME: "in-process-frame",
     16  OUT_PROCESS_IFRAME: "out-process-frame",
     17 };
     18 
     19 add_task(async function () {
     20  info("Testing the top-level document");
     21  await testWebsocketResources(targets.TOP_LEVEL_DOCUMENT);
     22  info("Testing the in-process iframe");
     23  await testWebsocketResources(targets.IN_PROCESS_IFRAME);
     24  info("Testing the out-of-process iframe");
     25  await testWebsocketResources(targets.OUT_PROCESS_IFRAME);
     26 });
     27 
     28 async function testWebsocketResources(target) {
     29  const tab = await addTab(URL_ROOT_SSL + "websocket_frontend.html");
     30  const { client, resourceCommand, targetCommand } =
     31    await initResourceCommand(tab);
     32 
     33  const availableResources = [];
     34  function onResourceAvailable(resources) {
     35    availableResources.push(...resources);
     36  }
     37 
     38  await resourceCommand.watchResources([resourceCommand.TYPES.WEBSOCKET], {
     39    onAvailable: onResourceAvailable,
     40  });
     41 
     42  info("Check available resources at initial");
     43  is(
     44    availableResources.length,
     45    0,
     46    "Length of existing resources is correct at initial"
     47  );
     48 
     49  info("Check resource of opening websocket");
     50  await executeFunctionInContext(tab, target, "openConnection");
     51 
     52  await waitUntil(() => availableResources.length === 1);
     53 
     54  const httpChannelId = availableResources[0].httpChannelId;
     55 
     56  ok(httpChannelId, "httpChannelId is present in the resource");
     57 
     58  assertResource(availableResources[0], {
     59    wsMessageType: "webSocketOpened",
     60    effectiveURI:
     61      "wss://example.com/browser/devtools/shared/commands/resource/tests/websocket_backend",
     62    extensions: "permessage-deflate",
     63    protocols: "",
     64  });
     65 
     66  info("Check resource of sending/receiving the data via websocket");
     67  await executeFunctionInContext(tab, target, "sendData", "test");
     68 
     69  await waitUntil(() => availableResources.length === 3);
     70 
     71  assertResource(availableResources[1], {
     72    wsMessageType: "frameSent",
     73    httpChannelId,
     74    data: {
     75      type: "sent",
     76      payload: "test",
     77      timeStamp: SHOULD_EXIST,
     78      finBit: SHOULD_EXIST,
     79      rsvBit1: SHOULD_EXIST,
     80      rsvBit2: SHOULD_EXIST,
     81      rsvBit3: SHOULD_EXIST,
     82      opCode: SHOULD_EXIST,
     83      mask: SHOULD_EXIST,
     84      maskBit: SHOULD_EXIST,
     85    },
     86  });
     87  assertResource(availableResources[2], {
     88    wsMessageType: "frameReceived",
     89    httpChannelId,
     90    data: {
     91      type: "received",
     92      payload: "test",
     93      timeStamp: SHOULD_EXIST,
     94      finBit: SHOULD_EXIST,
     95      rsvBit1: SHOULD_EXIST,
     96      rsvBit2: SHOULD_EXIST,
     97      rsvBit3: SHOULD_EXIST,
     98      opCode: SHOULD_EXIST,
     99      mask: SHOULD_EXIST,
    100      maskBit: SHOULD_EXIST,
    101    },
    102  });
    103 
    104  info("Check resource of closing websocket");
    105  await executeFunctionInContext(tab, target, "closeConnection");
    106 
    107  await waitUntil(() => availableResources.length === 6);
    108  assertResource(availableResources[3], {
    109    wsMessageType: "frameSent",
    110    httpChannelId,
    111    data: {
    112      type: "sent",
    113      payload: "",
    114      timeStamp: SHOULD_EXIST,
    115      finBit: SHOULD_EXIST,
    116      rsvBit1: SHOULD_EXIST,
    117      rsvBit2: SHOULD_EXIST,
    118      rsvBit3: SHOULD_EXIST,
    119      opCode: SHOULD_EXIST,
    120      mask: SHOULD_EXIST,
    121      maskBit: SHOULD_EXIST,
    122    },
    123  });
    124  assertResource(availableResources[4], {
    125    wsMessageType: "frameReceived",
    126    httpChannelId,
    127    data: {
    128      type: "received",
    129      payload: "",
    130      timeStamp: SHOULD_EXIST,
    131      finBit: SHOULD_EXIST,
    132      rsvBit1: SHOULD_EXIST,
    133      rsvBit2: SHOULD_EXIST,
    134      rsvBit3: SHOULD_EXIST,
    135      opCode: SHOULD_EXIST,
    136      mask: SHOULD_EXIST,
    137      maskBit: SHOULD_EXIST,
    138    },
    139  });
    140  assertResource(availableResources[5], {
    141    wsMessageType: "webSocketClosed",
    142    httpChannelId,
    143    code: IS_NUMBER,
    144    reason: "",
    145    wasClean: true,
    146  });
    147 
    148  info("Check existing resources");
    149  const existingResources = [];
    150 
    151  function onExsistingResourceAvailable(resources) {
    152    existingResources.push(...resources);
    153  }
    154 
    155  await resourceCommand.watchResources([resourceCommand.TYPES.WEBSOCKET], {
    156    onAvailable: onExsistingResourceAvailable,
    157  });
    158 
    159  is(
    160    availableResources.length,
    161    existingResources.length,
    162    "Length of existing resources is correct"
    163  );
    164 
    165  for (let i = 0; i < availableResources.length; i++) {
    166    Assert.strictEqual(
    167      availableResources[i],
    168      existingResources[i],
    169      `The ${i}th resource is correct`
    170    );
    171  }
    172 
    173  await resourceCommand.unwatchResources([resourceCommand.TYPES.WEBSOCKET], {
    174    onAvailable: onResourceAvailable,
    175  });
    176 
    177  await resourceCommand.unwatchResources([resourceCommand.TYPES.WEBSOCKET], {
    178    onAvailable: onExsistingResourceAvailable,
    179  });
    180 
    181  targetCommand.destroy();
    182  await client.close();
    183  BrowserTestUtils.removeTab(tab);
    184 }
    185 
    186 /**
    187 * Execute global functions defined in the correct
    188 * target (top-level-window or frames) contexts.
    189 *
    190 * @param {object} tab The current window tab
    191 * @param {string} target A string identify if we want to test the top level document or iframes
    192 * @param {string} funcName The name of the global function which needs to be called.
    193 * @param {*} funcArgs The arguments to pass to the global function
    194 */
    195 async function executeFunctionInContext(tab, target, funcName, ...funcArgs) {
    196  let browsingContext = tab.linkedBrowser.browsingContext;
    197  // If the target is an iframe get its window global
    198  if (target !== targets.TOP_LEVEL_DOCUMENT) {
    199    browsingContext = await SpecialPowers.spawn(
    200      tab.linkedBrowser,
    201      [target],
    202      async _target => {
    203        const iframe = content.document.getElementById(_target);
    204        return iframe.browsingContext;
    205      }
    206    );
    207  }
    208 
    209  return SpecialPowers.spawn(
    210    browsingContext,
    211    [funcName, funcArgs],
    212    async (_funcName, _funcArgs) => {
    213      await content.wrappedJSObject[_funcName](..._funcArgs);
    214    }
    215  );
    216 }
    217 
    218 function assertResource(resource, expected) {
    219  is(
    220    resource.resourceType,
    221    ResourceCommand.TYPES.WEBSOCKET,
    222    "Resource type is correct"
    223  );
    224 
    225  assertObject(resource, expected);
    226 }
    227 
    228 function assertObject(object, expected) {
    229  for (const field in expected) {
    230    if (typeof expected[field] === "object") {
    231      assertObject(object[field], expected[field]);
    232    } else if (expected[field] === SHOULD_EXIST) {
    233      Assert.notStrictEqual(
    234        object[field],
    235        undefined,
    236        `The value of ${field} exists`
    237      );
    238    } else if (expected[field] === IS_NUMBER) {
    239      ok(!isNaN(object[field]), `The value of ${field} is number`);
    240    } else {
    241      is(object[field], expected[field], `The value of ${field} is correct`);
    242    }
    243  }
    244 }