tor-browser

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

browser_windowProxy_transplant.js (6799B)


      1 "use strict";
      2 
      3 const DIRPATH = getRootDirectory(gTestPath).replace(
      4  "chrome://mochitests/content/",
      5  ""
      6 );
      7 const PATH = DIRPATH + "file_postMessage_parent.html";
      8 
      9 const URL1 = `http://mochi.test:8888/${PATH}`;
     10 const URL2 = `http://example.com/${PATH}`;
     11 const URL3 = `http://example.org/${PATH}`;
     12 
     13 // A bunch of boilerplate which needs to be dealt with.
     14 add_task(async function () {
     15  // Open a window with fission force-enabled in it.
     16  let win = await BrowserTestUtils.openNewBrowserWindow({
     17    fission: true,
     18    remote: true,
     19  });
     20  try {
     21    // Get the tab & browser to perform the test in.
     22    let tab = win.gBrowser.selectedTab;
     23    let browser = tab.linkedBrowser;
     24 
     25    // Start loading the original URI, then wait until it is loaded.
     26    BrowserTestUtils.startLoadingURIString(browser, URL1);
     27    await BrowserTestUtils.browserLoaded(browser, false, URL1);
     28 
     29    info("Chrome script has loaded initial URI.");
     30    await SpecialPowers.spawn(
     31      browser,
     32      [{ URL1, URL2, URL3 }],
     33      async ({ URL1, URL2, URL3 }) => {
     34        let iframe = content.document.createElement("iframe");
     35        content.document.body.appendChild(iframe);
     36 
     37        info("Chrome script created iframe");
     38 
     39        // Here and below, we have to store references to things in the
     40        // iframes on the content window, because all chrome references
     41        // to content will be turned into dead wrappers when the iframes
     42        // are closed.
     43        content.win0 = iframe.contentWindow;
     44        content.bc0 = iframe.browsingContext;
     45 
     46        ok(
     47          !Cu.isDeadWrapper(content.win0),
     48          "win0 shouldn't be a dead wrapper before navigation"
     49        );
     50 
     51        // Helper for waiting for a load.
     52        function waitLoad() {
     53          return new Promise(resolve => {
     54            iframe.addEventListener(
     55              "load",
     56              () => {
     57                info("Got an iframe load event!");
     58                resolve();
     59              },
     60              { once: true }
     61            );
     62          });
     63        }
     64 
     65        function askLoad(url) {
     66          info("Chrome script asking for load of " + url);
     67          iframe.contentWindow.postMessage(
     68            {
     69              action: "navigate",
     70              location: url,
     71            },
     72            "*"
     73          );
     74          info("Chrome script done calling PostMessage");
     75        }
     76 
     77        // Check that BC and WindowProxy are preserved across navigations.
     78        iframe.contentWindow.location = URL1;
     79        await waitLoad();
     80 
     81        content.win1 = iframe.contentWindow;
     82        let chromeWin1 = iframe.contentWindow;
     83        let chromeWin1x = Cu.waiveXrays(iframe.contentWindow);
     84        content.win1x = Cu.waiveXrays(iframe.contentWindow);
     85 
     86        Assert.notEqual(
     87          chromeWin1,
     88          chromeWin1x,
     89          "waiving xrays creates a new thing?"
     90        );
     91 
     92        content.bc1 = iframe.browsingContext;
     93 
     94        is(
     95          content.bc0,
     96          content.bc1,
     97          "same to same-origin BrowsingContext match"
     98        );
     99        is(content.win0, content.win1, "same to same-origin WindowProxy match");
    100 
    101        ok(
    102          !Cu.isDeadWrapper(content.win1),
    103          "win1 shouldn't be a dead wrapper before navigation"
    104        );
    105        ok(
    106          !Cu.isDeadWrapper(chromeWin1),
    107          "chromeWin1 shouldn't be a dead wrapper before navigation"
    108        );
    109 
    110        askLoad(URL2);
    111        await waitLoad();
    112 
    113        content.win2 = iframe.contentWindow;
    114        content.bc2 = iframe.browsingContext;
    115 
    116        // When chrome accesses a remote window proxy in content, the result
    117        // should be a remote outer window proxy in the chrome compartment, not an
    118        // Xray wrapper around the content remote window proxy. The former will
    119        // throw a security error, because @@toPrimitive can't be called cross
    120        // process, while the latter will result in an opaque wrapper, because
    121        // XPConnect doesn't know what to do when trying to create an Xray wrapper
    122        // around a remote outer window proxy. See bug 1556845.
    123        Assert.throws(
    124          () => {
    125            dump("content.win1 " + content.win1 + "\n");
    126          },
    127          /SecurityError: Permission denied to access property Symbol.toPrimitive on cross-origin object/,
    128          "Should get a remote outer window proxy when accessing old window proxy"
    129        );
    130        Assert.throws(
    131          () => {
    132            dump("content.win2 " + content.win2 + "\n");
    133          },
    134          /SecurityError: Permission denied to access property Symbol.toPrimitive on cross-origin object/,
    135          "Should get a remote outer window proxy when accessing new window proxy"
    136        );
    137 
    138        // If we fail to transplant existing non-remote outer window proxies, then
    139        // after we navigate the iframe existing chrome references to the window will
    140        // become dead wrappers. Also check content.win1 for thoroughness, though
    141        // we don't nuke content-content references.
    142        ok(
    143          !Cu.isDeadWrapper(content.win1),
    144          "win1 shouldn't be a dead wrapper after navigation"
    145        );
    146        ok(
    147          !Cu.isDeadWrapper(chromeWin1),
    148          "chromeWin1 shouldn't be a dead wrapper after navigation"
    149        );
    150        ok(
    151          Cu.isDeadWrapper(chromeWin1x),
    152          "chromeWin1x should be a dead wrapper after navigation"
    153        );
    154        ok(
    155          Cu.isDeadWrapper(content.win1x),
    156          "content.win1x should be a dead wrapper after navigation"
    157        );
    158 
    159        is(
    160          content.bc1,
    161          content.bc2,
    162          "same to cross-origin navigation BrowsingContext match"
    163        );
    164        is(
    165          content.win1,
    166          content.win2,
    167          "same to cross-origin navigation WindowProxy match"
    168        );
    169 
    170        ok(
    171          !Cu.isDeadWrapper(content.win1),
    172          "win1 shouldn't be a dead wrapper after navigation"
    173        );
    174 
    175        askLoad(URL3);
    176        await waitLoad();
    177 
    178        content.win3 = iframe.contentWindow;
    179        content.bc3 = iframe.browsingContext;
    180 
    181        is(
    182          content.bc2,
    183          content.bc3,
    184          "cross to cross-origin navigation BrowsingContext match"
    185        );
    186        is(
    187          content.win2,
    188          content.win3,
    189          "cross to cross-origin navigation WindowProxy match"
    190        );
    191 
    192        askLoad(URL1);
    193        await waitLoad();
    194 
    195        content.win4 = iframe.contentWindow;
    196        content.bc4 = iframe.browsingContext;
    197 
    198        is(
    199          content.bc3,
    200          content.bc4,
    201          "cross to same-origin navigation BrowsingContext match"
    202        );
    203        is(
    204          content.win3,
    205          content.win4,
    206          "cross to same-origin navigation WindowProxy match"
    207        );
    208      }
    209    );
    210  } finally {
    211    await BrowserTestUtils.closeWindow(win);
    212  }
    213 });