tor-browser

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

browser_wpi_base.js (8402B)


      1 // This test is fission-only! Make that clear before continuing, to avoid
      2 // confusing failures.
      3 ok(
      4  Services.appinfo.fissionAutostart,
      5  "this test requires fission to function!"
      6 );
      7 
      8 requestLongerTimeout(2);
      9 
     10 const WebContentIsolationStrategy = {
     11  IsolateNothing: 0,
     12  IsolateEverything: 1,
     13  IsolateHighValue: 2,
     14 };
     15 
     16 const COM_ORIGIN = "https://example.com";
     17 const ORG_ORIGIN = "https://example.org";
     18 const MOZ_ORIGIN = "https://www.mozilla.org";
     19 
     20 // Helper for building document-builder.sjs URLs which have specific headers &
     21 // HTML content.
     22 function documentURL(origin, headers, html) {
     23  let params = new URLSearchParams();
     24  params.append("html", html.trim());
     25  for (const [key, value] of Object.entries(headers)) {
     26    params.append("headers", `${key}:${value}`);
     27  }
     28  return `${origin}/document-builder.sjs?${params.toString()}`;
     29 }
     30 
     31 async function testTreeRemoteTypes(name, testpage) {
     32  // Use document-builder.sjs to build up the expected document tree.
     33  function buildURL(path, page) {
     34    let html = `<h1>${path}</h1>`;
     35    for (let i = 0; i < page.children.length; ++i) {
     36      const inner = buildURL(`${path}[${i}]`, page.children[i]);
     37      html += `<iframe src=${JSON.stringify(inner)}></iframe>`;
     38    }
     39    return documentURL(page.origin, page.headers, html);
     40  }
     41  const url = buildURL(name, testpage);
     42 
     43  // Load the tab and confirm that properties of the loaded documents match
     44  // expectation.
     45  await BrowserTestUtils.withNewTab(url, async browser => {
     46    let stack = [
     47      {
     48        path: name,
     49        bc: browser.browsingContext,
     50        ...testpage,
     51      },
     52    ];
     53 
     54    while (stack.length) {
     55      const { path, bc, remoteType, children, origin } = stack.pop();
     56      is(
     57        Services.scriptSecurityManager.createContentPrincipal(
     58          bc.currentWindowGlobal.documentURI,
     59          {}
     60        ).originNoSuffix,
     61        origin,
     62        `Frame ${path} has expected originNoSuffix`
     63      );
     64      is(
     65        bc.currentWindowGlobal.domProcess.remoteType,
     66        remoteType,
     67        `Frame ${path} has expected remote type`
     68      );
     69      is(
     70        bc.children.length,
     71        children.length,
     72        `Frame ${path} has the expected number of children`
     73      );
     74      for (let i = 0; i < bc.children.length; ++i) {
     75        stack.push({
     76          path: `${path}[${i}]`,
     77          bc: bc.children[i],
     78          ...children[i],
     79        });
     80      }
     81    }
     82  });
     83 }
     84 
     85 function mkTestPage({
     86  comRemoteType,
     87  orgRemoteType,
     88  mozRemoteType,
     89  topOrigin,
     90  topHeaders = {},
     91  frameHeaders = {},
     92 }) {
     93  const topRemoteType = {
     94    [COM_ORIGIN]: comRemoteType,
     95    [ORG_ORIGIN]: orgRemoteType,
     96    [MOZ_ORIGIN]: mozRemoteType,
     97  }[topOrigin];
     98 
     99  const innerChildren = [
    100    {
    101      origin: COM_ORIGIN,
    102      headers: frameHeaders,
    103      remoteType: comRemoteType,
    104      children: [],
    105    },
    106    {
    107      origin: ORG_ORIGIN,
    108      headers: frameHeaders,
    109      remoteType: orgRemoteType,
    110      children: [],
    111    },
    112    {
    113      origin: MOZ_ORIGIN,
    114      headers: frameHeaders,
    115      remoteType: mozRemoteType,
    116      children: [],
    117    },
    118  ];
    119 
    120  return {
    121    origin: topOrigin,
    122    headers: topHeaders,
    123    remoteType: topRemoteType,
    124    children: [
    125      {
    126        origin: COM_ORIGIN,
    127        headers: frameHeaders,
    128        remoteType: comRemoteType,
    129        children: [...innerChildren],
    130      },
    131      {
    132        origin: ORG_ORIGIN,
    133        headers: frameHeaders,
    134        remoteType: orgRemoteType,
    135        children: [...innerChildren],
    136      },
    137      {
    138        origin: MOZ_ORIGIN,
    139        headers: frameHeaders,
    140        remoteType: mozRemoteType,
    141        children: [...innerChildren],
    142      },
    143    ],
    144  };
    145 }
    146 
    147 const heuristics = [
    148  {
    149    name: "coop",
    150    setup_com: async expected => {
    151      // Set the COOP header, and load
    152      await testTreeRemoteTypes(
    153        "com_set_coop",
    154        mkTestPage({
    155          topOrigin: COM_ORIGIN,
    156          topHeaders: { "Cross-Origin-Opener-Policy": "same-origin" },
    157          comRemoteType: expected.com_high,
    158          orgRemoteType: expected.org_normal,
    159          mozRemoteType: expected.moz_normal,
    160        })
    161      );
    162    },
    163    run_extra_test: async expected => {
    164      // Load with both the COOP and COEP headers set.
    165      await testTreeRemoteTypes(
    166        "com_coop_coep",
    167        mkTestPage({
    168          topOrigin: COM_ORIGIN,
    169          topHeaders: {
    170            "Cross-Origin-Opener-Policy": "same-origin",
    171            "Cross-Origin-Embedder-Policy": "require-corp",
    172          },
    173          frameHeaders: {
    174            "Cross-Origin-Embedder-Policy": "require-corp",
    175            "Cross-Origin-Resource-Policy": "cross-origin",
    176          },
    177          comRemoteType: expected.com_coop_coep,
    178          orgRemoteType: expected.org_coop_coep,
    179          mozRemoteType: expected.moz_coop_coep,
    180        })
    181      );
    182    },
    183  },
    184  {
    185    name: "hasSavedLogin",
    186    setup_com: async () => {
    187      // add .com to the password manager
    188      let LoginInfo = new Components.Constructor(
    189        "@mozilla.org/login-manager/loginInfo;1",
    190        Ci.nsILoginInfo,
    191        "init"
    192      );
    193      await Services.logins.addLoginAsync(
    194        new LoginInfo(COM_ORIGIN, "", null, "username", "password", "", "")
    195      );
    196 
    197      // Init login detection service to trigger fetching logins
    198      let loginDetection = Cc[
    199        "@mozilla.org/login-detection-service;1"
    200      ].createInstance(Ci.nsILoginDetectionService);
    201      loginDetection.init();
    202 
    203      await TestUtils.waitForCondition(() => {
    204        let x = loginDetection.isLoginsLoaded();
    205        return x;
    206      }, "waiting for loading logins from the password manager");
    207    },
    208  },
    209  {
    210    name: "isLoggedIn",
    211    setup_com: async () => {
    212      let p = new Promise(resolve => {
    213        Services.obs.addObserver(function obs() {
    214          Services.obs.removeObserver(
    215            obs,
    216            "passwordmgr-form-submission-detected"
    217          );
    218          resolve();
    219        }, "passwordmgr-form-submission-detected");
    220      });
    221 
    222      const TEST_URL = documentURL(
    223        COM_ORIGIN,
    224        {},
    225        `<form>
    226          <input value="username">
    227          <input type="password" value="password">
    228          <input type="submit">
    229        </form>`
    230      );
    231 
    232      // submit the form to simulate the login behavior
    233      await BrowserTestUtils.withNewTab(TEST_URL, async browser => {
    234        await SpecialPowers.spawn(browser, [], async () => {
    235          content.document.querySelector("form").submit();
    236        });
    237      });
    238      await p;
    239    },
    240  },
    241 ];
    242 
    243 async function do_tests(expected) {
    244  for (let heuristic of heuristics) {
    245    info(`Starting ${heuristic.name} test`);
    246    // Clear all site-specific data, as we don't want to have any high-value site
    247    // permissions from any previous iterations.
    248    Services.logins.removeAllLogins();
    249    await new Promise(resolve =>
    250      Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, resolve)
    251    );
    252 
    253    // Loads for basic URLs with no special headers set.
    254    await testTreeRemoteTypes(
    255      "basic_com",
    256      mkTestPage({
    257        topOrigin: COM_ORIGIN,
    258        comRemoteType: expected.com_normal,
    259        orgRemoteType: expected.org_normal,
    260        mozRemoteType: expected.moz_normal,
    261      })
    262    );
    263 
    264    await testTreeRemoteTypes(
    265      "basic_org",
    266      mkTestPage({
    267        topOrigin: ORG_ORIGIN,
    268        comRemoteType: expected.com_normal,
    269        orgRemoteType: expected.org_normal,
    270        mozRemoteType: expected.moz_normal,
    271      })
    272    );
    273 
    274    info(`Setting up ${heuristic.name} test`);
    275    await heuristic.setup_com(expected);
    276 
    277    // Load again after the heuristic is triggered
    278    info(`Running ${heuristic.name} tests after setup`);
    279    await testTreeRemoteTypes(
    280      `com_after_${heuristic.name}`,
    281      mkTestPage({
    282        topOrigin: COM_ORIGIN,
    283        comRemoteType: expected.com_high,
    284        orgRemoteType: expected.org_normal,
    285        mozRemoteType: expected.moz_normal,
    286      })
    287    );
    288 
    289    // Load again with a .org toplevel
    290    await testTreeRemoteTypes(
    291      `org_after_${heuristic.name}`,
    292      mkTestPage({
    293        topOrigin: ORG_ORIGIN,
    294        comRemoteType: expected.com_high,
    295        orgRemoteType: expected.org_normal,
    296        mozRemoteType: expected.moz_normal,
    297      })
    298    );
    299 
    300    // Run heuristic dependent tests
    301    if (heuristic.run_extra_test) {
    302      info(`Running extra tests for ${heuristic.name}`);
    303      await heuristic.run_extra_test(expected);
    304    }
    305  }
    306 }