tor-browser

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

browser_session_data.js (7782B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 const { MessageHandlerRegistry } = ChromeUtils.importESModule(
      7  "chrome://remote/content/shared/messagehandler/MessageHandlerRegistry.sys.mjs"
      8 );
      9 const { RootMessageHandler } = ChromeUtils.importESModule(
     10  "chrome://remote/content/shared/messagehandler/RootMessageHandler.sys.mjs"
     11 );
     12 const { SessionData } = ChromeUtils.importESModule(
     13  "chrome://remote/content/shared/messagehandler/sessiondata/SessionData.sys.mjs"
     14 );
     15 
     16 const TEST_PAGE = "http://example.com/document-builder.sjs?html=tab";
     17 
     18 add_task(async function test_sessionData() {
     19  info("Navigate the initial tab to the test URL");
     20  const tab1 = gBrowser.selectedTab;
     21  await loadURL(tab1.linkedBrowser, TEST_PAGE);
     22 
     23  const sessionId = "sessionData-test";
     24 
     25  const rootMessageHandlerRegistry = new MessageHandlerRegistry(
     26    RootMessageHandler.type
     27  );
     28 
     29  const rootMessageHandler =
     30    rootMessageHandlerRegistry.getOrCreateMessageHandler(sessionId);
     31  ok(rootMessageHandler, "Valid ROOT MessageHandler created");
     32 
     33  const sessionData = rootMessageHandler.sessionData;
     34  ok(
     35    sessionData instanceof SessionData,
     36    "ROOT MessageHandler has a valid sessionData"
     37  );
     38 
     39  let sessionDataSnapshot = await getSessionDataFromContent();
     40  is(sessionDataSnapshot.size, 0, "session data is empty");
     41 
     42  info("Store a string value in session data");
     43  sessionData.updateSessionData([
     44    {
     45      method: "add",
     46      moduleName: "fakemodule",
     47      category: "testCategory",
     48      contextDescriptor: contextDescriptorAll,
     49      values: ["value-1"],
     50    },
     51  ]);
     52 
     53  sessionDataSnapshot = await getSessionDataFromContent();
     54  is(sessionDataSnapshot.size, 1, "session data contains 1 session");
     55  ok(sessionDataSnapshot.has(sessionId));
     56  let snapshot = sessionDataSnapshot.get(sessionId);
     57  ok(Array.isArray(snapshot));
     58  is(snapshot.length, 1);
     59 
     60  const stringDataItem = snapshot[0];
     61  checkSessionDataItem(
     62    stringDataItem,
     63    "fakemodule",
     64    "testCategory",
     65    ContextDescriptorType.All,
     66    "value-1"
     67  );
     68 
     69  info("Store a number value in session data");
     70  sessionData.updateSessionData([
     71    {
     72      method: "add",
     73      moduleName: "fakemodule",
     74      category: "testCategory",
     75      contextDescriptor: contextDescriptorAll,
     76      values: [12],
     77    },
     78  ]);
     79  snapshot = (await getSessionDataFromContent()).get(sessionId);
     80  is(snapshot.length, 2);
     81 
     82  const numberDataItem = snapshot[1];
     83  checkSessionDataItem(
     84    numberDataItem,
     85    "fakemodule",
     86    "testCategory",
     87    ContextDescriptorType.All,
     88    12
     89  );
     90 
     91  info("Store a boolean value in session data");
     92  sessionData.updateSessionData([
     93    {
     94      method: "add",
     95      moduleName: "fakemodule",
     96      category: "testCategory",
     97      contextDescriptor: contextDescriptorAll,
     98      values: [true],
     99    },
    100  ]);
    101  snapshot = (await getSessionDataFromContent()).get(sessionId);
    102  is(snapshot.length, 3);
    103 
    104  const boolDataItem = snapshot[2];
    105  checkSessionDataItem(
    106    boolDataItem,
    107    "fakemodule",
    108    "testCategory",
    109    ContextDescriptorType.All,
    110    true
    111  );
    112 
    113  info("Remove one value");
    114  sessionData.updateSessionData([
    115    {
    116      method: "remove",
    117      moduleName: "fakemodule",
    118      category: "testCategory",
    119      contextDescriptor: contextDescriptorAll,
    120      values: [12],
    121    },
    122  ]);
    123  snapshot = (await getSessionDataFromContent()).get(sessionId);
    124  is(snapshot.length, 2);
    125  checkSessionDataItem(
    126    snapshot[0],
    127    "fakemodule",
    128    "testCategory",
    129    ContextDescriptorType.All,
    130    "value-1"
    131  );
    132  checkSessionDataItem(
    133    snapshot[1],
    134    "fakemodule",
    135    "testCategory",
    136    ContextDescriptorType.All,
    137    true
    138  );
    139 
    140  info("Remove all values");
    141  sessionData.updateSessionData([
    142    {
    143      method: "remove",
    144      moduleName: "fakemodule",
    145      category: "testCategory",
    146      contextDescriptor: contextDescriptorAll,
    147      values: ["value-1", true],
    148    },
    149  ]);
    150  snapshot = (await getSessionDataFromContent()).get(sessionId);
    151  is(snapshot.length, 0, "Session data is now empty");
    152 
    153  info("Add another value before destroy");
    154  sessionData.updateSessionData([
    155    {
    156      method: "add",
    157      moduleName: "fakemodule",
    158      category: "testCategory",
    159      contextDescriptor: contextDescriptorAll,
    160      values: ["value-2"],
    161    },
    162  ]);
    163  snapshot = (await getSessionDataFromContent()).get(sessionId);
    164  is(snapshot.length, 1);
    165  checkSessionDataItem(
    166    snapshot[0],
    167    "fakemodule",
    168    "testCategory",
    169    ContextDescriptorType.All,
    170    "value-2"
    171  );
    172 
    173  sessionData.destroy();
    174  sessionDataSnapshot = await getSessionDataFromContent();
    175  is(sessionDataSnapshot.size, 0, "session data should be empty again");
    176 });
    177 
    178 add_task(async function test_sessionDataRootOnlyModule() {
    179  const sessionId = "sessionData-test-rootOnly";
    180 
    181  const rootMessageHandler = createRootMessageHandler(sessionId);
    182  ok(rootMessageHandler, "Valid ROOT MessageHandler created");
    183 
    184  BrowserTestUtils.startLoadingURIString(
    185    gBrowser.selectedBrowser,
    186    "https://example.com/document-builder.sjs?html=tab"
    187  );
    188 
    189  const windowGlobalCreated = rootMessageHandler.once(
    190    "window-global-handler-created"
    191  );
    192 
    193  info("Test that adding SessionData items works the root module");
    194  // Updating the session data on the root message handler should not cause
    195  // failures for other message handlers if the module only exists for root.
    196  await rootMessageHandler.addSessionDataItem({
    197    moduleName: "rootOnly",
    198    category: "session_data_root_only",
    199    contextDescriptor: {
    200      type: ContextDescriptorType.All,
    201    },
    202    values: [true],
    203  });
    204 
    205  await windowGlobalCreated;
    206  ok(true, "Window global has been initialized");
    207 
    208  let sessionDataReceivedByRoot = await rootMessageHandler.handleCommand({
    209    moduleName: "rootOnly",
    210    commandName: "getSessionDataReceived",
    211    destination: {
    212      type: RootMessageHandler.type,
    213    },
    214  });
    215 
    216  is(sessionDataReceivedByRoot.length, 1);
    217  is(sessionDataReceivedByRoot[0].category, "session_data_root_only");
    218  is(sessionDataReceivedByRoot[0].added.length, 1);
    219  is(sessionDataReceivedByRoot[0].added[0], true);
    220  is(
    221    sessionDataReceivedByRoot[0].contextDescriptor.type,
    222    ContextDescriptorType.All
    223  );
    224 
    225  info("Now test that removing items also works on the root module");
    226  await rootMessageHandler.removeSessionDataItem({
    227    moduleName: "rootOnly",
    228    category: "session_data_root_only",
    229    contextDescriptor: {
    230      type: ContextDescriptorType.All,
    231    },
    232    values: [true],
    233  });
    234 
    235  sessionDataReceivedByRoot = await rootMessageHandler.handleCommand({
    236    moduleName: "rootOnly",
    237    commandName: "getSessionDataReceived",
    238    destination: {
    239      type: RootMessageHandler.type,
    240    },
    241  });
    242 
    243  is(sessionDataReceivedByRoot.length, 2);
    244  is(sessionDataReceivedByRoot[1].category, "session_data_root_only");
    245  is(sessionDataReceivedByRoot[1].removed.length, 1);
    246  is(sessionDataReceivedByRoot[1].removed[0], true);
    247  is(
    248    sessionDataReceivedByRoot[1].contextDescriptor.type,
    249    ContextDescriptorType.All
    250  );
    251 
    252  rootMessageHandler.destroy();
    253 });
    254 
    255 function checkSessionDataItem(item, moduleName, category, contextType, value) {
    256  is(item.moduleName, moduleName, "Data item has the expected module name");
    257  is(item.category, category, "Data item has the expected category");
    258  is(
    259    item.contextDescriptor.type,
    260    contextType,
    261    "Data item has the expected context type"
    262  );
    263  is(item.value, value, "Data item has the expected value");
    264 }
    265 
    266 function getSessionDataFromContent() {
    267  return SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => {
    268    const { readSessionData } = ChromeUtils.importESModule(
    269      "chrome://remote/content/shared/messagehandler/sessiondata/SessionDataReader.sys.mjs"
    270    );
    271    return readSessionData();
    272  });
    273 }