tor-browser

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

test_content_javascript_loads.html (4737B)


      1 <!DOCTYPE html>
      2 <html>
      3 <head>
      4  <title>Test for Bug 1647519</title>
      5  <meta charset="utf-8">
      6  <script src="/tests/SimpleTest/SimpleTest.js"></script>
      7  <script src="/tests/SimpleTest/EventUtils.js"></script>
      8  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
      9 </head>
     10 <body>
     11 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1647519">Mozilla Bug 1647519</a>
     12 
     13 <script type="application/javascript">
     14 "use strict";
     15 
     16 function promiseMessage(source, filter = () => true) {
     17  return new Promise(resolve => {
     18    function listener(event) {
     19      if (event.source == source && filter(event)) {
     20        window.removeEventListener("message", listener);
     21        resolve(event);
     22      }
     23    }
     24    window.addEventListener("message", listener);
     25  });
     26 }
     27 
     28 async function runTests(resourcePath) {
     29  /* globals Assert, content */
     30  let doc = content.document;
     31 
     32  // Sends a message to the given target window and waits for a response a few
     33  // times to (more or less) ensure that a `javascript:` load request has had
     34  // time to succeed, if it were going to.
     35  async function doSomeRoundTrips(target) {
     36    for (let i = 0; i < 3; i++) {
     37      // Note: The ping message needs to be sent from a script running in the
     38      // content scope or there will be no source window for the reply to be
     39      // sent to.
     40      await content.wrappedJSObject.ping(target);
     41    }
     42  }
     43 
     44  function promiseEvent(target, name) {
     45    return new Promise(resolve => {
     46      target.addEventListener(name, resolve, { once: true });
     47    });
     48  }
     49 
     50  function createIframe(host, id) {
     51    let iframe = doc.createElement("iframe");
     52    iframe.id = id;
     53    iframe.name = id;
     54    iframe.src = `https://${host}${resourcePath}file_content_javascript_loads_frame.html`;
     55    doc.body.appendChild(iframe);
     56    return promiseEvent(iframe, "load");
     57  }
     58 
     59  const ID_SAME_ORIGIN = "frame-same-origin";
     60  const ID_SAME_BASE_DOMAIN = "frame-same-base-domain";
     61  const ID_CROSS_BASE_DOMAIN = "frame-cross-base-domain";
     62 
     63  await Promise.all([
     64    createIframe("example.com", ID_SAME_ORIGIN),
     65    createIframe("test1.example.com", ID_SAME_BASE_DOMAIN),
     66    createIframe("example.org", ID_CROSS_BASE_DOMAIN),
     67  ]);
     68 
     69  let gotJSLoadFrom = null;
     70  let pendingJSLoadID = null;
     71  content.addEventListener("message", event => {
     72    if ("javascriptLoadID" in event.data) {
     73      Assert.equal(
     74        event.data.javascriptLoadID,
     75        pendingJSLoadID,
     76        "Message from javascript: load should have the expected ID"
     77      );
     78      Assert.equal(
     79        gotJSLoadFrom,
     80        null,
     81        "Should not have seen a previous load message this cycle"
     82      );
     83      gotJSLoadFrom = event.source.name;
     84    }
     85  });
     86 
     87  async function watchForJSLoads(frameName, expected, task) {
     88    let loadId = Math.random();
     89 
     90    let jsURI =
     91      "javascript:" +
     92      encodeURI(`parent.postMessage({ javascriptLoadID: ${loadId} }, "*")`);
     93 
     94    pendingJSLoadID = loadId;
     95    gotJSLoadFrom = null;
     96 
     97    await task(jsURI);
     98 
     99    await doSomeRoundTrips(content.wrappedJSObject[frameName]);
    100 
    101    if (expected) {
    102      Assert.equal(
    103        gotJSLoadFrom,
    104        frameName,
    105        `Should have seen javascript: URI loaded into ${frameName}`
    106      );
    107    } else {
    108      Assert.equal(
    109        gotJSLoadFrom,
    110        null,
    111        "Should not have seen javascript: URI loaded"
    112      );
    113    }
    114  }
    115 
    116  let frames = [
    117    { name: ID_SAME_ORIGIN, expectLoad: true },
    118    { name: ID_SAME_BASE_DOMAIN, expectLoad: false },
    119    { name: ID_CROSS_BASE_DOMAIN, expectLoad: false },
    120  ];
    121  for (let { name, expectLoad } of frames) {
    122    info(`Checking loads for frame "${name}". Expecting loads: ${expectLoad}`);
    123 
    124    info("Checking location setter");
    125    await watchForJSLoads(name, expectLoad, jsURI => {
    126      // Note: We need to do this from the content scope since security checks
    127      // depend on the JS caller scope.
    128      content.wrappedJSObject.setFrameLocation(name, jsURI);
    129    });
    130 
    131    info("Checking targeted <a> load");
    132    await watchForJSLoads(name, expectLoad, jsURI => {
    133      let a = doc.createElement("a");
    134      a.target = name;
    135      a.href = jsURI;
    136      doc.body.appendChild(a);
    137      a.click();
    138      a.remove();
    139    });
    140 
    141    info("Checking targeted window.open load");
    142    await watchForJSLoads(name, expectLoad, jsURI => {
    143      content.wrappedJSObject.open(jsURI, name);
    144    });
    145  }
    146 }
    147 
    148 add_task(async function() {
    149  const resourcePath = location.pathname.replace(/[^\/]+$/, "");
    150 
    151  let win = window.open(
    152    `https://example.com${resourcePath}file_content_javascript_loads_root.html`
    153  );
    154  await promiseMessage(win, event => event.data == "ready");
    155 
    156  await SpecialPowers.spawn(win, [resourcePath], runTests);
    157 
    158  win.close();
    159 });
    160 </script>
    161 
    162 </body>
    163 </html>