tor-browser

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

frame-ancestors-test.sub.js (5722B)


      1 var SAME_ORIGIN = true;
      2 var CROSS_ORIGIN = false;
      3 
      4 var EXPECT_BLOCK = true;
      5 var EXPECT_LOAD = false;
      6 
      7 var SAMEORIGIN_ORIGIN = "{{location[scheme]}}://{{location[host]}}";
      8 var CROSSORIGIN_ORIGIN = "http://{{domains[www1]}}:{{ports[http][1]}}";
      9 
     10 var test;
     11 
     12 function endTest(failed, message) {
     13    if (typeof test === 'undefined') return;
     14 
     15    if (failed) {
     16        test.step(function() {
     17            assert_unreached(message);
     18            test.done();
     19        });
     20    }
     21    else test.done({message: message});
     22 }
     23 
     24 window.addEventListener("message", function (e) {
     25    if (window.parent != window)
     26        window.parent.postMessage(e.data, "*");
     27    else
     28        if (e.data.type === 'test_result')
     29            endTest(e.data.failed, "Inner IFrame msg: " + e.data.message);
     30 });
     31 
     32 function injectNestedIframe(policy, parent, child, expectation, isSandboxed) {
     33    var iframe = document.createElement("iframe");
     34 
     35    var url = "/content-security-policy/frame-ancestors/support/frame-in-frame.sub.html"
     36              + "?policy=" + policy
     37              + "&parent=" + parent
     38              + "&child=" + child
     39              + "&expectation=" + expectation;
     40    url = (parent == "same" ? SAMEORIGIN_ORIGIN : CROSSORIGIN_ORIGIN) + url;
     41 
     42    iframe.src = url;
     43 
     44    if (isSandboxed)
     45        iframe.sandbox = 'allow-scripts';
     46 
     47    document.body.appendChild(iframe);
     48 }
     49 
     50 let timer;
     51 function pollForLoadCompletion({iframe, expectBlock}) {
     52    let fn = iframeLoaded({expectBlock, isPoll: true});
     53    timer = test.step_timeout(() => fn({target: iframe}), 10);
     54 }
     55 
     56 function injectIFrame(policy, sameOrigin, expectBlock) {
     57    var iframe = document.createElement("iframe");
     58    iframe.addEventListener("load", iframeLoaded({expectBlock, isPoll: false}));
     59    iframe.addEventListener("error", iframeLoaded({expectBlock, isPoll: false}));
     60 
     61    var url = "/content-security-policy/frame-ancestors/support/frame-ancestors.sub.html?policy=" + policy;
     62    if (sameOrigin)
     63        url = SAMEORIGIN_ORIGIN + url;
     64    else
     65        url = CROSSORIGIN_ORIGIN + url;
     66 
     67    iframe.src = url;
     68    document.body.appendChild(iframe);
     69    pollForLoadCompletion({iframe, expectBlock});
     70 }
     71 
     72 function iframeLoaded({isPoll, expectBlock}) {
     73    return function(ev) {
     74        clearTimeout(timer);
     75        var failed = true;
     76        var message = "";
     77        try {
     78            let url = ev.target.contentWindow.location.href;
     79            if (isPoll && (url === "about:blank" || ev.target.contentDocument.readyState !== "complete")) {
     80                pollForLoadCompletion({iframe: ev.target, expectBlock});
     81                return;
     82            }
     83            if (expectBlock) {
     84                message = "The IFrame should have been blocked (or cross-origin). It wasn't.";
     85                failed = true;
     86            } else {
     87                message = "The IFrame should not have been blocked. It wasn't.";
     88                failed = false;
     89            }
     90        } catch (ex) {
     91            if (expectBlock) {
     92                message = "The IFrame should have been blocked (or cross-origin). It was.";
     93                failed = false;
     94            } else {
     95                message = "The IFrame should not have been blocked. It was.";
     96                failed = true;
     97            }
     98        }
     99        if (window.parent != window)
    100            window.parent.postMessage({type: 'test_result', failed: failed, message: message}, '*');
    101        else
    102            endTest(failed, message);
    103    };
    104 }
    105 
    106 function originFrameShouldBe(child, expectation, policy) {
    107    if (child == "cross" && expectation == "blocked") crossOriginFrameShouldBeBlocked(policy);
    108    if (child == "same" && expectation == "blocked") sameOriginFrameShouldBeBlocked(policy);
    109    if (child == "cross" && expectation == "allowed") crossOriginFrameShouldBeAllowed(policy);
    110    if (child == "same" && expectation == "allowed") sameOriginFrameShouldBeAllowed(policy);
    111 }
    112 
    113 function crossOriginFrameShouldBeBlocked(policy) {
    114    window.onload = function () {
    115        injectIFrame(policy, CROSS_ORIGIN, EXPECT_BLOCK);
    116    };
    117 }
    118 
    119 function crossOriginFrameShouldBeAllowed(policy) {
    120    window.onload = function () {
    121        injectIFrame(policy, CROSS_ORIGIN, EXPECT_LOAD);
    122    };
    123 }
    124 
    125 function sameOriginFrameShouldBeBlocked(policy) {
    126    window.onload = function () {
    127        injectIFrame(policy, SAME_ORIGIN, EXPECT_BLOCK);
    128    };
    129 }
    130 
    131 function sameOriginFrameShouldBeAllowed(policy) {
    132    window.onload = function () {
    133        injectIFrame(policy, SAME_ORIGIN, EXPECT_LOAD);
    134    };
    135 }
    136 
    137 function testNestedIFrame(policy, parent, child, expectation) {
    138    window.onload = function () {
    139        injectNestedIframe(policy, parent == SAME_ORIGIN ? "same" : "cross", child == SAME_ORIGIN ? "same" : "cross", expectation == EXPECT_LOAD ? "allowed" : "blocked", false /* isSandboxed */);
    140    };
    141 }
    142 
    143 function testNestedSandboxedIFrame(policy, parent, child, expectation) {
    144    window.onload = function () {
    145        injectNestedIframe(policy, parent == SAME_ORIGIN ? "same" : "cross", child == SAME_ORIGIN ? "same" : "cross", expectation == EXPECT_LOAD ? "allowed" : "blocked", true /* isSandboxed */);
    146    };
    147 }
    148 
    149 function testUrlWithPathIgnored() {
    150    window.onload = function () {
    151        // A policy with a URL with a path should block the load, because no
    152        // origin matches against a source expression with a path. See
    153        // https://issues.chromium.org/issues/40779556#comment12 and
    154        // https://w3c.github.io/webappsec-csp/#frame-ancestors-navigation-response
    155        // steps 6.2 and 6.3.
    156        injectIFrame(SAMEORIGIN_ORIGIN + "/test", SAME_ORIGIN, EXPECT_BLOCK);
    157        // The same policy with no path should allow the load (smoke test).
    158        injectIFrame(SAMEORIGIN_ORIGIN, SAME_ORIGIN, EXPECT_LOAD);
    159    };
    160 }