file_multipart_testserver.sjs (4594B)
1 // SJS file specifically for the needs of bug 2 // Bug 1416045/Bug 1223743 - CSP: Check baseChannel for CSP when loading multipart channel 3 4 var CSP = "script-src 'unsafe-inline', img-src 'none'"; 5 var rootCSP = "script-src 'unsafe-inline'"; 6 var part1CSP = "img-src *"; 7 var part2CSP = "img-src 'none'"; 8 var BOUNDARY = "fooboundary"; 9 10 // small red image 11 const IMG_BYTES = atob( 12 "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12" + 13 "P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" 14 ); 15 16 var RESPONSE = ` 17 <script> 18 var myImg = new Image; 19 myImg.src = "file_multipart_testserver.sjs?img"; 20 myImg.onerror = function(e) { 21 window.parent.postMessage({"test": "rootCSP_test", 22 "msg": "img-blocked"}, "*"); 23 }; 24 myImg.onload = function() { 25 window.parent.postMessage({"test": "rootCSP_test", 26 "msg": "img-loaded"}, "*"); 27 }; 28 document.body.appendChild(myImg); 29 </script> 30 `; 31 32 var RESPONSE1 = ` 33 <body> 34 <script> 35 var triggerNextPartFrame = document.createElement('iframe'); 36 var myImg = new Image; 37 myImg.src = "file_multipart_testserver.sjs?img"; 38 myImg.onerror = function(e) { 39 window.parent.postMessage({"test": "part1CSP_test", 40 "msg": "part1-img-blocked"}, "*"); 41 triggerNextPartFrame.src = 'file_multipart_testserver.sjs?sendnextpart'; 42 }; 43 myImg.onload = function() { 44 window.parent.postMessage({"test": "part1CSP_test", 45 "msg": "part1-img-loaded"}, "*"); 46 triggerNextPartFrame.src = 'file_multipart_testserver.sjs?sendnextpart'; 47 }; 48 document.body.appendChild(myImg); 49 document.body.appendChild(triggerNextPartFrame); 50 </script> 51 </body> 52 `; 53 54 var RESPONSE2 = ` 55 <body> 56 <script> 57 var myImg = new Image; 58 myImg.src = "file_multipart_testserver.sjs?img"; 59 myImg.onerror = function(e) { 60 window.parent.postMessage({"test": "part2CSP_test", 61 "msg": "part2-img-blocked"}, "*"); 62 }; 63 myImg.onload = function() { 64 window.parent.postMessage({"test": "part2CSP_test", 65 "msg": "part2-img-loaded"}, "*"); 66 }; 67 document.body.appendChild(myImg); 68 </script> 69 </body> 70 `; 71 72 function setGlobalState(data, key) { 73 x = { 74 data, 75 QueryInterface(iid) { 76 return this; 77 }, 78 }; 79 x.wrappedJSObject = x; 80 setObjectState(key, x); 81 } 82 83 function getGlobalState(key) { 84 var data; 85 getObjectState(key, function (x) { 86 data = x && x.wrappedJSObject.data; 87 }); 88 return data; 89 } 90 91 function handleRequest(request, response) { 92 // avoid confusing cache behaviors 93 response.setHeader("Cache-Control", "no-cache", false); 94 95 if (request.queryString == "doc") { 96 response.setHeader("Content-Security-Policy", CSP, false); 97 response.setHeader( 98 "Content-Type", 99 "multipart/x-mixed-replace; boundary=" + BOUNDARY, 100 false 101 ); 102 response.write(BOUNDARY + "\r\n"); 103 response.write(RESPONSE); 104 response.write(BOUNDARY + "\r\n"); 105 return; 106 } 107 108 if (request.queryString == "partcspdoc") { 109 response.setHeader("Content-Security-Policy", rootCSP, false); 110 response.setHeader( 111 "Content-Type", 112 "multipart/x-mixed-replace; boundary=" + BOUNDARY, 113 false 114 ); 115 response.setStatusLine(request.httpVersion, 200, "OK"); 116 response.processAsync(); 117 response.write("--" + BOUNDARY + "\r\n"); 118 sendNextPart(response, 1); 119 return; 120 } 121 122 if (request.queryString == "sendnextpart") { 123 response.setStatusLine(request.httpVersion, 204, "No content"); 124 var blockedResponse = getGlobalState("root-document-response"); 125 if (typeof blockedResponse == "object") { 126 sendNextPart(blockedResponse, 2); 127 sendClose(blockedResponse); 128 } else { 129 dump("Couldn't find the stored response object."); 130 } 131 return; 132 } 133 134 if (request.queryString == "img") { 135 response.setHeader("Content-Type", "image/png"); 136 response.write(IMG_BYTES); 137 return; 138 } 139 140 // we should never get here - return something unexpected 141 response.write("d'oh"); 142 } 143 144 function sendClose(response) { 145 response.write("--" + BOUNDARY + "--\r\n"); 146 response.finish(); 147 } 148 149 function sendNextPart(response, partNumber) { 150 response.write("Content-type: text/html" + "\r\n"); 151 if (partNumber == 1) { 152 response.write("Content-Security-Policy:" + part1CSP + "\r\n"); 153 response.write(RESPONSE1); 154 setGlobalState(response, "root-document-response"); 155 } else { 156 response.write("Content-Security-Policy:" + part2CSP + "\r\n"); 157 response.write(RESPONSE2); 158 } 159 response.write("--" + BOUNDARY + "\r\n"); 160 }