tor-browser

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

test_block_toplevel_data_navigation.html (4836B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <head>
      4  <meta charset="utf-8">
      5  <title>Bug 1331351 - Block top level window data: URI navigations</title>
      6  <!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
      7  <script src="/tests/SimpleTest/SimpleTest.js"></script>
      8  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
      9 </head>
     10 <body>
     11 <script class="testbody" type="text/javascript">
     12 
     13 async function expectBlockedToplevelData() {
     14  await SpecialPowers.spawnChrome([], async () => {
     15    let progressListener;
     16    let bid = await new Promise(resolve => {
     17      let bcs = [];
     18      progressListener = {
     19        QueryInterface: ChromeUtils.generateQI(["nsIWebProgressListener", "nsISupportsWeakReference"]),
     20        onStateChange(webProgress, request, stateFlags, status) {
     21          if (!(request instanceof Ci.nsIChannel) || !webProgress.isTopLevel ||
     22              !(stateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW) ||
     23              !(stateFlags & Ci.nsIWebProgressListener.STATE_STOP)) {
     24            return;
     25          }
     26 
     27          if (!["NS_ERROR_DOM_BAD_URI", "NS_ERROR_CORRUPTED_CONTENT", "NS_ERROR_ABORT"].includes(ChromeUtils.getXPCOMErrorName(status))) {
     28            info(ChromeUtils.getXPCOMErrorName(status));
     29            isnot(request.URI.scheme, "data");
     30            return;
     31          }
     32 
     33          // We can't check for the scheme to be "data" because in the case of a
     34          // redirected load, we'll get a `NS_ERROR_DOM_BAD_URI` load error
     35          // before observing the redirect, cancelling the load. Instead we just
     36          // wait for any load to error with `NS_ERROR_DOM_BAD_URI`.
     37          for (let bc of bcs) {
     38            try {
     39              bc.webProgress.removeProgressListener(progressListener);
     40            } catch(e) { }
     41          }
     42          bcs = [];
     43          Services.obs.removeObserver(observer, "browsing-context-attached");
     44          resolve(webProgress.browsingContext.browserId);
     45        }
     46      };
     47 
     48      function observer(subject) {
     49        if (!bcs.includes(subject.webProgress)) {
     50          bcs.push(subject.webProgress);
     51          subject.webProgress.addProgressListener(progressListener, Ci.nsIWebProgress.NOTIFY_ALL);
     52        }
     53      }
     54      Services.obs.addObserver(observer, "browsing-context-attached");
     55    });
     56    return bid;
     57  });
     58 }
     59 
     60 async function expectBlockedURIWarning() {
     61  await SpecialPowers.spawnChrome([], async () => {
     62    return new Promise(resolve => {
     63      Services.console.registerListener(function onConsoleMessage(msg) {
     64        info("Seeing console message: " + msg.message);
     65        if (!(msg instanceof Ci.nsIScriptError)) {
     66          return;
     67        }
     68        if (msg.category != "DATA_URI_BLOCKED") {
     69          return;
     70        }
     71 
     72        Services.console.unregisterListener(onConsoleMessage);
     73        resolve();
     74      });
     75    });
     76  });
     77 }
     78 
     79 async function expectBrowserDiscarded(browserId) {
     80  await SpecialPowers.spawnChrome([browserId], async (browserId) => {
     81    return new Promise(resolve => {
     82      function check() {
     83        if (!BrowsingContext.getCurrentTopByBrowserId(browserId)) {
     84          ok(true, `BrowserID ${browserId} discarded`);
     85          resolve();
     86          Services.obs.removeObserver(check, "browsing-context-discarded");
     87        }
     88      }
     89      Services.obs.addObserver(check, "browsing-context-discarded");
     90      check();
     91    });
     92  });
     93 }
     94 
     95 async function popupTest(uri, expectClose) {
     96  info(`Running expect blocked test for ${uri}`);
     97  let reqBlockedPromise = expectBlockedToplevelData();
     98  let warningPromise = expectBlockedURIWarning();
     99  let win = window.open(uri);
    100  let browserId = await reqBlockedPromise;
    101  await warningPromise;
    102  if (expectClose) {
    103    await expectBrowserDiscarded(browserId);
    104  }
    105  win.close();
    106 }
    107 
    108 add_task(async function() {
    109  await SpecialPowers.pushPrefEnv({
    110    set: [["security.data_uri.block_toplevel_data_uri_navigations", true]],
    111  });
    112 
    113  // simple data: URI click navigation should be prevented
    114  await popupTest("file_block_toplevel_data_navigation.html", false);
    115 
    116  // data: URI in iframe which opens data: URI in _blank should be blocked
    117  await popupTest("file_block_toplevel_data_navigation2.html", false);
    118 
    119  // navigating to a data: URI using window.location.href should be blocked
    120  await popupTest("file_block_toplevel_data_navigation3.html", false);
    121 
    122  // navigating to a data: URI using window.open() should be blocked
    123  await popupTest("data:text/html,<body>toplevel data: URI navigations should be blocked</body>", false);
    124 
    125  // navigating to a URI which redirects to a data: URI using window.open() should be blocked
    126  await popupTest("file_block_toplevel_data_redirect.sjs", false);
    127 
    128  // navigating to a data: URI without a Content Type should be blocked
    129  await popupTest("data:,DataURIsWithNoContentTypeShouldBeBlocked", false);
    130 });
    131 
    132 </script>
    133 </body>
    134 </html>