1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/tests/mochitest/whatwg/test_postMessage_special.xhtml Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,311 @@ 1.4 +<!DOCTYPE html> 1.5 +<html xmlns="http://www.w3.org/1999/xhtml"> 1.6 +<!-- 1.7 +https://bugzilla.mozilla.org/show_bug.cgi?id=postMessage 1.8 +--> 1.9 +<head> 1.10 + <title>postMessage from about:blank, data URLs</title> 1.11 + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> 1.12 + <script type="text/javascript" src="browserFu.js"></script> 1.13 + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> 1.14 +</head> 1.15 +<body> 1.16 +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=postMessage">Mozilla Bug 387706</a> 1.17 +<p id="display"></p> 1.18 +<div id="content" style="display: none"></div> 1.19 + 1.20 +<pre id="test"> 1.21 +<script class="testbody" type="application/javascript"><![CDATA[ 1.22 +/** Test for Bug 387706 **/ 1.23 + 1.24 +SimpleTest.waitForExplicitFinish(); 1.25 + 1.26 +var B64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 1.27 + 1.28 +/** 1.29 + * Encodes an array of bytes into a string using the base 64 encoding scheme. 1.30 + * 1.31 + * @param bytes 1.32 + * An array of bytes to encode. 1.33 + */ 1.34 +function b64(str) 1.35 +{ 1.36 + var byteArray = new Array(str.length); 1.37 + for (var i = 0, sz = str.length; i < sz; i++) 1.38 + byteArray[i] = str.charCodeAt(i); 1.39 + 1.40 + var index = 0; 1.41 + function get3Bytes() 1.42 + { 1.43 + if (byteArray.length - index < 3) 1.44 + return null; // Less than three bytes remaining 1.45 + 1.46 + // Return the next three bytes in the array, and increment index for our 1.47 + // next invocation 1.48 + return byteArray.slice(index, index += 3); 1.49 + } 1.50 + 1.51 + var out = ""; 1.52 + var bytes = null; 1.53 + while ((bytes = get3Bytes())) 1.54 + { 1.55 + var bits = 0; 1.56 + for (var i = 0; i < 3; i++) 1.57 + bits = (bits << 8) | bytes[i]; 1.58 + for (var j = 18; j >= 0; j -= 6) 1.59 + out += B64_CHARS[(bits>>j) & 0x3F]; 1.60 + } 1.61 + 1.62 + // Get the remaining bytes 1.63 + bytes = byteArray.slice(index); 1.64 + 1.65 + switch (bytes.length) 1.66 + { 1.67 + case 2: 1.68 + out += B64_CHARS[(bytes[0]>>2) & 0x3F] + 1.69 + B64_CHARS[((bytes[0] & 0x03) << 4) | ((bytes[1] >> 4) & 0x0F)] + 1.70 + B64_CHARS[((bytes[1] & 0x0F) << 2)] + 1.71 + "="; 1.72 + break; 1.73 + case 1: 1.74 + out += B64_CHARS[(bytes[0]>>2) & 0x3F] + 1.75 + B64_CHARS[(bytes[0] & 0x03) << 4] + 1.76 + "=="; 1.77 + break; 1.78 + } 1.79 + 1.80 + return out; 1.81 +} 1.82 + 1.83 + 1.84 +var aboutBlankWindow = null; 1.85 +var aboutBlank2Window = null; 1.86 +var dataWindow = null; 1.87 + 1.88 +/** Convert a nullable string to a pretty representation */ 1.89 +function sourceify(v) 1.90 +{ 1.91 + if (typeof v == "string") 1.92 + return "'" + v + "'"; 1.93 + return String(v); 1.94 +} 1.95 + 1.96 +/** Receives MessageEvents to this window. */ 1.97 +function messageReceiver(evt) 1.98 +{ 1.99 + // It's not clear what the security model is for data: URLs and whether they 1.100 + // can access their parents; WebKit denies access, while Gecko currently 1.101 + // allows it. We work around this problem by using postMessage (surprise!) 1.102 + // to start the round of tests when each iframe loads. 1.103 + if (evt.data === "next-test") 1.104 + { 1.105 + setTimeout(nextTest, 0); 1.106 + return; 1.107 + } 1.108 + 1.109 + 1.110 + try 1.111 + { 1.112 + ok(evt instanceof MessageEvent, "umm, how did we get this?"); 1.113 + is(evt.type, "message", "expected events of type 'message'"); 1.114 + 1.115 + if (isMozilla) 1.116 + { 1.117 + ok(evt.isTrusted === false, "shouldn't have been a trusted event"); 1.118 + } 1.119 + 1.120 + if (evt.data === "about:blank-response") 1.121 + { 1.122 + // This isn't clarified in HTML5 yet, but the origin for a document which 1.123 + // has been open()ed is the origin of the calling code, somewhat loosely 1.124 + // speaking. For the specific case of about:blank it's also possible 1.125 + // that the origin is determined by the code that opens the window. It's 1.126 + // not codified yet which of these two causes the identifier tokens on 1.127 + // the event generated by the new window to be those of this window, but 1.128 + // in either case this is what they should be. 1.129 + is(evt.origin, "http://mochi.test:8888", 1.130 + "wrong origin for event from about:blank"); 1.131 + is(evt.source, aboutBlankWindow, "wrong source"); 1.132 + 1.133 + // ...and onto the next test 1.134 + setupBlank2(); 1.135 + } 1.136 + else if (evt.data === "about:blank2-response") 1.137 + { 1.138 + is(evt.origin, "http://mochi.test:8888", 1.139 + "wrong origin for event from about:blank #2"); 1.140 + is(evt.source, aboutBlank2Window, "wrong source"); 1.141 + 1.142 + setupData(); 1.143 + } 1.144 + else if (evt.data === "data-response") 1.145 + { 1.146 + // HTML5 defines the origin of a data: URI as the origin of the window or 1.147 + // script that opened the data: URI. 1.148 + is(evt.origin, "http://mochi.test:8888", 1.149 + "wrong origin for event from data URL (should be the origin of the " + 1.150 + "window/script that opened the URL, in this case the origin of this " + 1.151 + "file)"); 1.152 + is(evt.source, dataWindow, "wrong source"); 1.153 + 1.154 + finish(); 1.155 + } 1.156 + else 1.157 + { 1.158 + ok(false, "unexpected message: " + evt.data); 1.159 + } 1.160 + } 1.161 + catch (e) 1.162 + { 1.163 + ok(false, "error processing event with data '" + evt.data + "': " + e); 1.164 + } 1.165 +} 1.166 + 1.167 +function getContents(description, responseText) 1.168 +{ 1.169 + var contents = 1.170 + "<!DOCTYPE html>\n" + 1.171 + "<html>\n" + 1.172 + "<head>\n" + 1.173 + " <title>about:blank</title>\n" + 1.174 + " <script type='application/javascript'>\n" + 1.175 + "function receive(evt)\n" + 1.176 + "{\n" + 1.177 + " var response = '" + responseText + "';\n" + 1.178 + "\n" + 1.179 + " if (evt.source !== window.parent)\n" + 1.180 + " response += ' wrong-source';\n" + 1.181 + " if (evt.origin !== 'http://mochi.test:8888')\n" + 1.182 + " response += ' wrong-origin(' + evt.origin + ')';\n" + 1.183 + " if (evt.data !== 'from-opener')\n" + 1.184 + " response += ' wrong-data(' + evt.data + ')';\n" + 1.185 + "\n" + 1.186 + " window.parent.postMessage(response, 'http://mochi.test:8888');\n" + 1.187 + "}\n" + 1.188 + "\n" + 1.189 + "function ready()\n" + 1.190 + "{\n" + 1.191 + " window.parent.postMessage('next-test', 'http://mochi.test:8888');\n" + 1.192 + "}\n" + 1.193 + "\n" + 1.194 + "window.addEventListener('load', ready, false);\n" + 1.195 + "window.addEventListener('message', receive, false);\n" + 1.196 + " </script>\n" + 1.197 + "</head>\n" + 1.198 + "<body><p>" + description + "</p></body>\n" + 1.199 + "</html>"; 1.200 + 1.201 + return contents; 1.202 +} 1.203 + 1.204 +function finish() 1.205 +{ 1.206 + SimpleTest.finish(); 1.207 +} 1.208 + 1.209 +var xhtmlns = "http://www.w3.org/1999/xhtml"; 1.210 + 1.211 +function insert(el) 1.212 +{ 1.213 + var content = $("content"); 1.214 + content.parentNode.insertBefore(el, content); 1.215 +} 1.216 + 1.217 +function setupBlank() 1.218 +{ 1.219 + var aboutBlankFrame = document.createElementNS(xhtmlns, "iframe"); 1.220 + aboutBlankFrame.setAttribute("src", "about:blank"); 1.221 + insert(aboutBlankFrame); 1.222 + 1.223 + aboutBlankWindow = aboutBlankFrame.contentWindow; 1.224 + var doc = aboutBlankWindow.document; 1.225 + doc.open(); 1.226 + doc.write(getContents("This was about:blank #1", "about:blank-response")); 1.227 + doc.close(); 1.228 + 1.229 + // I don't believe anything guarantees sync parsing, so we have to wait for 1.230 + // the new window to poke us to actually do the test. :-\ 1.231 +} 1.232 + 1.233 +function setupBlank2() 1.234 +{ 1.235 + var aboutBlank2Frame = document.createElementNS(xhtmlns, "iframe"); 1.236 + aboutBlank2Frame.addEventListener("load", nextTest, false); 1.237 + aboutBlank2Frame.setAttribute("src", "about:blank"); 1.238 + 1.239 + insert(aboutBlank2Frame); 1.240 +} 1.241 + 1.242 +// Could use window.btoa here, but that's not standardized, and we want to be 1.243 +// able to run these tests against browsers that don't support it. 1.244 +var dataURI = "data:text/html;base64," + 1.245 + b64(getContents("A data: URL", "data-response")); 1.246 + 1.247 +function setupData() 1.248 +{ 1.249 + var dataFrame = document.createElementNS(xhtmlns, "iframe"); 1.250 + dataFrame.setAttribute("src", dataURI); 1.251 + insert(dataFrame); 1.252 + 1.253 + dataWindow = dataFrame.contentWindow; 1.254 + 1.255 + // ...and wait again for the window to load... 1.256 +} 1.257 + 1.258 +var count = 0; 1.259 +function nextTest() 1.260 +{ 1.261 + switch (count++) 1.262 + { 1.263 + case 0: 1.264 + testBlank(); 1.265 + break; 1.266 + 1.267 + case 1: 1.268 + testBlank2(); 1.269 + break; 1.270 + 1.271 + case 2: 1.272 + testData(); 1.273 + break; 1.274 + 1.275 + default: 1.276 + ok(false, "unreached"); 1.277 + break; 1.278 + } 1.279 +} 1.280 + 1.281 +function testBlank() 1.282 +{ 1.283 + aboutBlankWindow.postMessage("from-opener", "http://mochi.test:8888"); 1.284 +} 1.285 + 1.286 +function testBlank2() 1.287 +{ 1.288 + // For some reason we can't access this across browsers prior to the iframe 1.289 + // loading, so set its value here. 1.290 + aboutBlank2Window = window.frames[1]; 1.291 + 1.292 + var doc = aboutBlank2Window.document; 1.293 + 1.294 + doc.body.textContent = "This was about:blank #2"; 1.295 + 1.296 + var script = doc.createElement("script"); 1.297 + script.textContent = 1.298 + "window.parent.postMessage('about:blank2-response', " + 1.299 + " 'http://mochi.test:8888');"; 1.300 + doc.body.appendChild(script); 1.301 +} 1.302 + 1.303 +function testData() 1.304 +{ 1.305 + dataWindow.postMessage("from-opener", "http://mochi.test:8888"); 1.306 +} 1.307 + 1.308 +window.addEventListener("message", messageReceiver, false); 1.309 + 1.310 +addLoadEvent(setupBlank); 1.311 +]]></script> 1.312 +</pre> 1.313 +</body> 1.314 +</html>