tor-browser

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

browser_target_command_scope_flag.js (6962B)


      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 TargetCommand API with changes made to devtools.browsertoolbox.scope
      7 
      8 const TEST_URL =
      9  "data:text/html;charset=utf-8," + encodeURIComponent(`<div id="test"></div>`);
     10 
     11 add_task(async function () {
     12  // Disable the preloaded process as it gets created lazily and may interfere
     13  // with process count assertions
     14  await pushPref("dom.ipc.processPrelaunch.enabled", false);
     15  // This preference helps destroying the content process when we close the tab
     16  await pushPref("dom.ipc.keepProcessesAlive.web", 1);
     17 
     18  // First test with multiprocess debugging enabled
     19  await pushPref("devtools.browsertoolbox.scope", "everything");
     20 
     21  const commands = await CommandsFactory.forMainProcess();
     22  const targetCommand = commands.targetCommand;
     23  await targetCommand.startListening();
     24 
     25  // Pass any configuration, in order to ensure attaching all the thread actors
     26  await commands.threadConfigurationCommand.updateConfiguration({
     27    skipBreakpoints: false,
     28  });
     29 
     30  const { TYPES } = targetCommand;
     31 
     32  const targets = new Set();
     33  const destroyedTargetIsModeSwitchingMap = new Map();
     34  const onAvailable = async ({ targetFront }) => {
     35    targets.add(targetFront);
     36  };
     37  const onDestroyed = ({ targetFront, isModeSwitching }) => {
     38    destroyedTargetIsModeSwitchingMap.set(targetFront, isModeSwitching);
     39    targets.delete(targetFront);
     40  };
     41  await targetCommand.watchTargets({
     42    types: [TYPES.PROCESS, TYPES.FRAME],
     43    onAvailable,
     44    onDestroyed,
     45  });
     46  Assert.greater(targets.size, 1, "We get many targets");
     47 
     48  info("Open a tab in a new content process");
     49  await BrowserTestUtils.openNewForegroundTab({
     50    gBrowser,
     51    url: TEST_URL,
     52    forceNewProcess: true,
     53  });
     54 
     55  // Verify that only PROCESS and top target have their thread actor attached.
     56  // We especially care about having the FRAME targets to not be attached,
     57  // otherwise we would have two thread actor debugging the same thread
     58  // with the PROCESS target already debugging all FRAME documents.
     59  for (const target of targets) {
     60    const threadFront = await target.getFront("thread");
     61    const isAttached = await threadFront.isAttached();
     62    if (target.targetType == TYPES.PROCESS) {
     63      ok(isAttached, "All process targets are attached");
     64    } else if (target.isTopLevel) {
     65      ok(isAttached, "The top level target is attached");
     66    } else {
     67      ok(
     68        !isAttached,
     69        "The frame targets should not be attached in multiprocess mode"
     70      );
     71    }
     72  }
     73 
     74  const firstTabProcessID =
     75    gBrowser.selectedTab.linkedBrowser.browsingContext.currentWindowGlobal
     76      .osPid;
     77  const firstTabInnerWindowId =
     78    gBrowser.selectedTab.linkedBrowser.browsingContext.currentWindowGlobal
     79      .innerWindowId;
     80 
     81  info("Wait for the tab content process target");
     82  const processTarget = await waitFor(() =>
     83    [...targets].find(
     84      target =>
     85        target.targetType == TYPES.PROCESS &&
     86        target.processID == firstTabProcessID
     87    )
     88  );
     89 
     90  info("Wait for the tab window global target");
     91  const windowGlobalTarget = await waitFor(() =>
     92    [...targets].find(
     93      target =>
     94        target.targetType == TYPES.FRAME &&
     95        target.innerWindowId == firstTabInnerWindowId
     96    )
     97  );
     98 
     99  info("Disable multiprocess debugging");
    100  await pushPref("devtools.browsertoolbox.scope", "parent-process");
    101 
    102  info("Wait for all targets but top level and workers to be destroyed");
    103  await waitFor(() =>
    104    [...targets].every(
    105      target =>
    106        target == targetCommand.targetFront || target.targetType == TYPES.WORKER
    107    )
    108  );
    109 
    110  ok(processTarget.isDestroyed(), "The process target is destroyed");
    111  ok(
    112    destroyedTargetIsModeSwitchingMap.get(processTarget),
    113    "isModeSwitching was passed to onTargetDestroyed and is true for the process target"
    114  );
    115  ok(windowGlobalTarget.isDestroyed(), "The window global target is destroyed");
    116  ok(
    117    destroyedTargetIsModeSwitchingMap.get(windowGlobalTarget),
    118    "isModeSwitching was passed to onTargetDestroyed and is true for the window global target"
    119  );
    120 
    121  info("Open a second tab in a new content process");
    122  const parentProcessTargetCount = targets.size;
    123  await BrowserTestUtils.openNewForegroundTab({
    124    gBrowser,
    125    url: TEST_URL,
    126    forceNewProcess: true,
    127  });
    128  const secondTabProcessID =
    129    gBrowser.selectedTab.linkedBrowser.browsingContext.currentWindowGlobal
    130      .osPid;
    131  const secondTabInnerWindowId =
    132    gBrowser.selectedTab.linkedBrowser.browsingContext.currentWindowGlobal
    133      .innerWindowId;
    134 
    135  await wait(1000);
    136  is(
    137    parentProcessTargetCount,
    138    targets.size,
    139    "The new tab process should be ignored and no target be created"
    140  );
    141 
    142  info("Re-enable multiprocess debugging");
    143  await pushPref("devtools.browsertoolbox.scope", "everything");
    144 
    145  await waitFor(() => {
    146    return [...targets].some(
    147      target =>
    148        target.targetType == TYPES.PROCESS &&
    149        target.processID == firstTabProcessID
    150    );
    151  }, "Wait for the first tab content process target to be available again");
    152 
    153  await waitFor(() => {
    154    return [...targets].some(
    155      target =>
    156        target.targetType == TYPES.FRAME &&
    157        target.innerWindowId == firstTabInnerWindowId
    158    );
    159  }, "Wait for the first tab frame target to be available again");
    160 
    161  await waitFor(() => {
    162    return [...targets].some(
    163      target =>
    164        target.targetType == TYPES.PROCESS &&
    165        target.processID == secondTabProcessID
    166    );
    167  }, "Wait for the second tab content process target to be available again");
    168 
    169  await waitFor(() => {
    170    return [...targets].some(
    171      target =>
    172        target.targetType == TYPES.FRAME &&
    173        target.innerWindowId == secondTabInnerWindowId
    174    );
    175  }, "Wait for the second tab frame target to be available again");
    176 
    177  info("Open a third tab in a new content process");
    178  await BrowserTestUtils.openNewForegroundTab({
    179    gBrowser,
    180    url: TEST_URL,
    181    forceNewProcess: true,
    182  });
    183 
    184  const thirdTabProcessID =
    185    gBrowser.selectedTab.linkedBrowser.browsingContext.currentWindowGlobal
    186      .osPid;
    187  const thirdTabInnerWindowId =
    188    gBrowser.selectedTab.linkedBrowser.browsingContext.currentWindowGlobal
    189      .innerWindowId;
    190 
    191  info("Wait for the third tab content process target");
    192  await waitFor(() =>
    193    [...targets].find(
    194      target =>
    195        target.targetType == TYPES.PROCESS &&
    196        target.processID == thirdTabProcessID
    197    )
    198  );
    199 
    200  info("Wait for the third tab window global target");
    201  await waitFor(() =>
    202    [...targets].find(
    203      target =>
    204        target.targetType == TYPES.FRAME &&
    205        target.innerWindowId == thirdTabInnerWindowId
    206    )
    207  );
    208 
    209  targetCommand.destroy();
    210 
    211  // Wait for all the targets to be fully attached so we don't have pending requests.
    212  await Promise.all(
    213    targetCommand.getAllTargets(targetCommand.ALL_TYPES).map(t => t.initialized)
    214  );
    215 
    216  await commands.destroy();
    217 });