test_frameancestors.html (5796B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <title>Test for Content Security Policy Frame Ancestors directive</title> 5 <script src="/tests/SimpleTest/SimpleTest.js"></script> 6 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> 7 </head> 8 <body> 9 <p id="display"></p> 10 <div id="content" style="display: none"> 11 </div> 12 <iframe style="width:100%;height:300px;" id='cspframe'></iframe> 13 <script class="testbody" type="text/javascript"> 14 15 // These are test results: -1 means it hasn't run, 16 // true/false is the pass/fail result. 17 var framesThatShouldLoad = { 18 aa_allow: -1, /* innermost frame allows a * 19 //aa_block: -1, /* innermost frame denies a */ 20 ab_allow: -1, /* innermost frame allows a */ 21 //ab_block: -1, /* innermost frame denies a */ 22 aba_allow: -1, /* innermost frame allows b,a */ 23 //aba_block: -1, /* innermost frame denies b */ 24 //aba2_block: -1, /* innermost frame denies a */ 25 abb_allow: -1, /* innermost frame allows b,a */ 26 //abb_block: -1, /* innermost frame denies b */ 27 //abb2_block: -1, /* innermost frame denies a */ 28 }; 29 30 // we normally expect _6_ violations (6 test cases that cause blocks), but many 31 // of the cases cause violations due to the // origin of the test harness (same 32 // as 'a'). When the violation is cross-origin, the URI passed to the observers 33 // is null (see bug 846978). This means we can't tell if it's part of the test 34 // case or if it is the test harness frame (also origin 'a'). 35 // As a result, we'll get an extra violation for the following cases: 36 // ab_block "frame-ancestors 'none'" (outer frame and test harness) 37 // aba2_block "frame-ancestors b" (outer frame and test harness) 38 // abb2_block "frame-ancestors b" (outer frame and test harness) 39 // 40 // and while we can detect the test harness check for this one case since 41 // the violations are not cross-origin and we get the URI: 42 // aba2_block "frame-ancestors b" (outer frame and test harness) 43 // 44 // we can't for these other ones: 45 // ab_block "frame-ancestors 'none'" (outer frame and test harness) 46 // abb2_block "frame-ancestors b" (outer frame and test harness) 47 // 48 // so that results in 2 extra violation notifications due to the test harness. 49 // expected = 6, total = 8 50 // 51 // Number of tests that pass for this file should be 12 (8 violations 4 loads) 52 var expectedViolationsLeft = 8; 53 54 // CSP frame-ancestor checks happen in the parent, hence we have to 55 // proxy the csp violation notifications. 56 SpecialPowers.registerObservers("csp-on-violate-policy"); 57 58 // This is used to watch the blocked data bounce off CSP and allowed data 59 // get sent out to the wire. 60 function examiner() { 61 SpecialPowers.addObserver(this, "specialpowers-csp-on-violate-policy"); 62 } 63 examiner.prototype = { 64 observe(subject, topic, data) { 65 // subject should be an nsURI... though could be null since CSP 66 // prohibits cross-origin URI reporting during frame ancestors checks. 67 if (subject && !SpecialPowers.can_QI(subject)) 68 return; 69 70 var asciiSpec = subject; 71 72 try { 73 asciiSpec = SpecialPowers.getPrivilegedProps( 74 SpecialPowers.do_QueryInterface(subject, "nsIURI"), 75 "asciiSpec"); 76 77 // skip checks on the test harness -- can't do this skipping for 78 // cross-origin blocking since the observer doesn't get the URI. This 79 // can cause this test to over-succeed (but only in specific cases). 80 if (asciiSpec.includes("test_frameancestors.html")) { 81 return; 82 } 83 } catch (ex) { 84 // was not an nsIURI, so it was probably a cross-origin report. 85 } 86 87 if (topic === "specialpowers-csp-on-violate-policy") { 88 //these were blocked... record that they were blocked 89 window.frameBlocked(asciiSpec, data); 90 } 91 }, 92 93 // must eventually call this to remove the listener, 94 // or mochitests might get borked. 95 remove() { 96 SpecialPowers.removeObserver(this, "specialpowers-csp-on-violate-policy"); 97 } 98 } 99 100 // called when a frame is loaded 101 // -- if it's not enumerated above, it should not load! 102 var frameLoaded = function(testname, uri) { 103 //test already complete.... forget it... remember the first result. 104 if (window.framesThatShouldLoad[testname] != -1) 105 return; 106 107 if (typeof window.framesThatShouldLoad[testname] === 'undefined') { 108 // uh-oh, we're not expecting this frame to load! 109 ok(false, testname + ' framed site should not have loaded: ' + uri); 110 } else { 111 framesThatShouldLoad[testname] = true; 112 ok(true, testname + ' framed site when allowed by csp (' + uri + ')'); 113 } 114 checkTestResults(); 115 } 116 117 // called when a frame is blocked 118 // -- we can't determine *which* frame was blocked, but at least we can count them 119 var frameBlocked = function(uri, policy) { 120 ok(true, 'a CSP policy blocked frame from being loaded: ' + policy); 121 expectedViolationsLeft--; 122 checkTestResults(); 123 } 124 125 126 // Check to see if all the tests have run 127 var checkTestResults = function() { 128 // if any test is incomplete, keep waiting 129 for (var v in framesThatShouldLoad) 130 if(window.framesThatShouldLoad[v] == -1) 131 return; 132 133 if (window.expectedViolationsLeft > 0) 134 return; 135 136 // ... otherwise, finish 137 window.examiner.remove(); 138 SimpleTest.finish(); 139 } 140 141 window.addEventListener("message", receiveMessage); 142 143 function receiveMessage(event) { 144 if (event.data.call && event.data.call == 'frameLoaded') 145 frameLoaded(event.data.testname, event.data.uri); 146 } 147 148 ////////////////////////////////////////////////////////////////////// 149 // set up and go 150 window.examiner = new examiner(); 151 SimpleTest.waitForExplicitFinish(); 152 153 // save this for last so that our listeners are registered. 154 // ... this loads the testbed of good and bad requests. 155 document.getElementById('cspframe').src = 'file_frameancestors_main.html'; 156 157 </script> 158 </pre> 159 </body> 160 </html>