tor-browser

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

browser_net_frame.js (7503B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 /**
      7 * Tests for all expected requests when an iframe is loading a subdocument.
      8 */
      9 
     10 const TOP_FILE_NAME = "html_frame-test-page.html";
     11 const SUB_FILE_NAME = "html_frame-subdocument.html";
     12 const TOP_URL = EXAMPLE_URL + TOP_FILE_NAME;
     13 const SUB_URL = EXAMPLE_URL + SUB_FILE_NAME;
     14 
     15 const EXPECTED_REQUESTS_TOP = [
     16  {
     17    method: "GET",
     18    url: TOP_URL,
     19    causeType: "document",
     20    causeUri: null,
     21    stack: true,
     22  },
     23  {
     24    method: "GET",
     25    url: EXAMPLE_URL + "stylesheet_request",
     26    causeType: "stylesheet",
     27    causeUri: TOP_URL,
     28    stack: false,
     29  },
     30  {
     31    method: "GET",
     32    url: EXAMPLE_URL + "img_request",
     33    causeType: "img",
     34    causeUri: TOP_URL,
     35    stack: false,
     36  },
     37  {
     38    method: "GET",
     39    url: EXAMPLE_URL + "xhr_request",
     40    causeType: "xhr",
     41    causeUri: TOP_URL,
     42    stack: [{ fn: "performXhrRequest", file: TOP_FILE_NAME, line: 25 }],
     43  },
     44  {
     45    method: "GET",
     46    url: EXAMPLE_URL + "fetch_request",
     47    causeType: "fetch",
     48    causeUri: TOP_URL,
     49    stack: [{ fn: "performFetchRequest", file: TOP_FILE_NAME, line: 29 }],
     50  },
     51  {
     52    method: "GET",
     53    url: EXAMPLE_URL + "promise_fetch_request",
     54    causeType: "fetch",
     55    causeUri: TOP_URL,
     56    stack: [
     57      { fn: "performPromiseFetchRequest", file: TOP_FILE_NAME, line: 41 },
     58      {
     59        fn: null,
     60        file: TOP_FILE_NAME,
     61        line: 40,
     62        asyncCause: "promise callback",
     63      },
     64    ],
     65  },
     66  {
     67    method: "GET",
     68    url: EXAMPLE_URL + "timeout_fetch_request",
     69    causeType: "fetch",
     70    causeUri: TOP_URL,
     71    stack: [
     72      { fn: "performTimeoutFetchRequest", file: TOP_FILE_NAME, line: 43 },
     73      {
     74        fn: "performPromiseFetchRequest",
     75        file: TOP_FILE_NAME,
     76        line: 42,
     77        asyncCause: "setTimeout handler",
     78      },
     79    ],
     80  },
     81  {
     82    method: "POST",
     83    url: EXAMPLE_URL + "beacon_request",
     84    causeType: "beacon",
     85    causeUri: TOP_URL,
     86    stack: [{ fn: "performBeaconRequest", file: TOP_FILE_NAME, line: 33 }],
     87  },
     88 ];
     89 
     90 const EXPECTED_REQUESTS_SUB = [
     91  {
     92    method: "GET",
     93    url: SUB_URL,
     94    causeType: "subdocument",
     95    causeUri: TOP_URL,
     96    stack: false,
     97  },
     98  {
     99    method: "GET",
    100    url: EXAMPLE_URL + "stylesheet_request",
    101    causeType: "stylesheet",
    102    causeUri: SUB_URL,
    103    stack: false,
    104  },
    105  {
    106    method: "GET",
    107    url: EXAMPLE_URL + "img_request",
    108    causeType: "img",
    109    causeUri: SUB_URL,
    110    stack: false,
    111  },
    112  {
    113    method: "GET",
    114    url: EXAMPLE_URL + "xhr_request",
    115    causeType: "xhr",
    116    causeUri: SUB_URL,
    117    stack: [{ fn: "performXhrRequest", file: SUB_FILE_NAME, line: 24 }],
    118  },
    119  {
    120    method: "GET",
    121    url: EXAMPLE_URL + "fetch_request",
    122    causeType: "fetch",
    123    causeUri: SUB_URL,
    124    stack: [{ fn: "performFetchRequest", file: SUB_FILE_NAME, line: 28 }],
    125  },
    126  {
    127    method: "GET",
    128    url: EXAMPLE_URL + "promise_fetch_request",
    129    causeType: "fetch",
    130    causeUri: SUB_URL,
    131    stack: [
    132      { fn: "performPromiseFetchRequest", file: SUB_FILE_NAME, line: 40 },
    133      {
    134        fn: null,
    135        file: SUB_FILE_NAME,
    136        line: 39,
    137        asyncCause: "promise callback",
    138      },
    139    ],
    140  },
    141  {
    142    method: "GET",
    143    url: EXAMPLE_URL + "timeout_fetch_request",
    144    causeType: "fetch",
    145    causeUri: SUB_URL,
    146    stack: [
    147      { fn: "performTimeoutFetchRequest", file: SUB_FILE_NAME, line: 42 },
    148      {
    149        fn: "performPromiseFetchRequest",
    150        file: SUB_FILE_NAME,
    151        line: 41,
    152        asyncCause: "setTimeout handler",
    153      },
    154    ],
    155  },
    156  {
    157    method: "POST",
    158    url: EXAMPLE_URL + "beacon_request",
    159    causeType: "beacon",
    160    causeUri: SUB_URL,
    161    stack: [{ fn: "performBeaconRequest", file: SUB_FILE_NAME, line: 32 }],
    162  },
    163 ];
    164 
    165 const REQUEST_COUNT =
    166  EXPECTED_REQUESTS_TOP.length + EXPECTED_REQUESTS_SUB.length;
    167 
    168 add_task(async function () {
    169  // the initNetMonitor function clears the network request list after the
    170  // page is loaded. That's why we first load a bogus page from SIMPLE_URL,
    171  // and only then load the real thing from TOP_URL - we want to catch
    172  // all the requests the page is making, not only the XHRs.
    173  // We can't use about:blank here, because initNetMonitor checks that the
    174  // page has actually made at least one request.
    175  const { monitor } = await initNetMonitor(SIMPLE_URL, { requestCount: 1 });
    176 
    177  const { document, store, windowRequire, connector } = monitor.panelWin;
    178  const Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
    179  const { getDisplayedRequests, getSortedRequests } = windowRequire(
    180    "devtools/client/netmonitor/src/selectors/index"
    181  );
    182 
    183  store.dispatch(Actions.batchEnable(false));
    184 
    185  const wait = waitForNetworkEvents(monitor, REQUEST_COUNT);
    186  await navigateTo(TOP_URL);
    187  await wait;
    188 
    189  is(
    190    store.getState().requests.requests.length,
    191    REQUEST_COUNT,
    192    "All the page events should be recorded."
    193  );
    194 
    195  // Fetch stack-trace data from the backend and wait till
    196  // all packets are received.
    197  const requests = getSortedRequests(store.getState());
    198  await Promise.all(
    199    requests.map(requestItem =>
    200      connector.requestData(requestItem.id, "stackTrace")
    201    )
    202  );
    203 
    204  // While there is a defined order for requests in each document separately, the requests
    205  // from different documents may interleave in various ways that change per test run, so
    206  // there is not a single order when considering all the requests together.
    207  let currentTop = 0;
    208  let currentSub = 0;
    209  for (let i = 0; i < REQUEST_COUNT; i++) {
    210    const requestItem = getSortedRequests(store.getState())[i];
    211 
    212    const itemUrl = requestItem.url;
    213    const itemCauseUri = requestItem.cause.loadingDocumentUri;
    214    let spec;
    215    if (itemUrl == SUB_URL || itemCauseUri == SUB_URL) {
    216      spec = EXPECTED_REQUESTS_SUB[currentSub++];
    217    } else {
    218      spec = EXPECTED_REQUESTS_TOP[currentTop++];
    219    }
    220    const { method, url, causeType, causeUri, stack } = spec;
    221 
    222    await verifyRequestItemTarget(
    223      document,
    224      getDisplayedRequests(store.getState()),
    225      requestItem,
    226      method,
    227      url,
    228      { cause: { type: causeType, loadingDocumentUri: causeUri } }
    229    );
    230 
    231    const { stacktrace } = requestItem;
    232    const stackLen = stacktrace ? stacktrace.length : 0;
    233 
    234    if (stack) {
    235      ok(stacktrace, `Request #${i} has a stacktrace`);
    236      Assert.greater(
    237        stackLen,
    238        0,
    239        `Request #${i} (${causeType}) has a stacktrace with ${stackLen} items`
    240      );
    241 
    242      // if "stack" is array, check the details about the top stack frames
    243      if (Array.isArray(stack)) {
    244        stack.forEach((frame, j) => {
    245          is(
    246            stacktrace[j].functionName,
    247            frame.fn,
    248            `Request #${i} has the correct function on JS stack frame #${j}`
    249          );
    250          is(
    251            stacktrace[j].filename.split("/").pop(),
    252            frame.file,
    253            `Request #${i} has the correct file on JS stack frame #${j}`
    254          );
    255          is(
    256            stacktrace[j].lineNumber,
    257            frame.line,
    258            `Request #${i} has the correct line number on JS stack frame #${j}`
    259          );
    260          is(
    261            stacktrace[j].asyncCause,
    262            frame.asyncCause,
    263            `Request #${i} has the correct async cause on JS stack frame #${j}`
    264          );
    265        });
    266      }
    267    } else {
    268      is(stackLen, 0, `Request #${i} (${causeType}) has an empty stacktrace`);
    269    }
    270  }
    271 
    272  await teardown(monitor);
    273 });