test_postMessage_special.xhtml (8113B)
1 <!DOCTYPE html> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <!-- 4 https://bugzilla.mozilla.org/show_bug.cgi?id=postMessage 5 --> 6 <head> 7 <title>postMessage from about:blank, data URLs</title> 8 <script src="/tests/SimpleTest/SimpleTest.js"></script> 9 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> 10 </head> 11 <body> 12 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=postMessage">Mozilla Bug 387706</a> 13 <p id="display"></p> 14 <div id="content" style="display: none"></div> 15 16 <pre id="test"> 17 <script class="testbody" type="application/javascript"><![CDATA[ 18 /** Test for Bug 387706 */ 19 20 SimpleTest.waitForExplicitFinish(); 21 22 var B64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 23 24 /** 25 * Encodes an array of bytes into a string using the base 64 encoding scheme. 26 * 27 * @param bytes 28 * An array of bytes to encode. 29 */ 30 function b64(str) 31 { 32 var byteArray = new Array(str.length); 33 for (var i = 0, sz = str.length; i < sz; i++) 34 byteArray[i] = str.charCodeAt(i); 35 36 var index = 0; 37 function get3Bytes() 38 { 39 if (byteArray.length - index < 3) 40 return null; // Less than three bytes remaining 41 42 // Return the next three bytes in the array, and increment index for our 43 // next invocation 44 return byteArray.slice(index, index += 3); 45 } 46 47 var out = ""; 48 var bytes = null; 49 while ((bytes = get3Bytes())) 50 { 51 var bits = 0; 52 for (var i = 0; i < 3; i++) 53 bits = (bits << 8) | bytes[i]; 54 for (var j = 18; j >= 0; j -= 6) 55 out += B64_CHARS[(bits>>j) & 0x3F]; 56 } 57 58 // Get the remaining bytes 59 bytes = byteArray.slice(index); 60 61 switch (bytes.length) 62 { 63 case 2: 64 out += B64_CHARS[(bytes[0]>>2) & 0x3F] + 65 B64_CHARS[((bytes[0] & 0x03) << 4) | ((bytes[1] >> 4) & 0x0F)] + 66 B64_CHARS[((bytes[1] & 0x0F) << 2)] + 67 "="; 68 break; 69 case 1: 70 out += B64_CHARS[(bytes[0]>>2) & 0x3F] + 71 B64_CHARS[(bytes[0] & 0x03) << 4] + 72 "=="; 73 break; 74 } 75 76 return out; 77 } 78 79 80 var aboutBlankWindow = null; 81 var aboutBlank2Window = null; 82 var dataWindow = null; 83 84 /** Convert a nullable string to a pretty representation */ 85 function sourceify(v) 86 { 87 if (typeof v == "string") 88 return "'" + v + "'"; 89 return String(v); 90 } 91 92 /** Receives MessageEvents to this window. */ 93 function messageReceiver(evt) 94 { 95 // It's not clear what the security model is for data: URLs and whether they 96 // can access their parents; WebKit denies access, while Gecko currently 97 // allows it. We work around this problem by using postMessage (surprise!) 98 // to start the round of tests when each iframe loads. 99 if (evt.data === "next-test") 100 { 101 setTimeout(nextTest, 0); 102 return; 103 } 104 105 106 try 107 { 108 ok(evt instanceof MessageEvent, "umm, how did we get this?"); 109 is(evt.type, "message", "expected events of type 'message'"); 110 ok(evt.isTrusted === true, "should have been a trusted event"); 111 112 if (evt.data === "about:blank-response") 113 { 114 // This isn't clarified in HTML5 yet, but the origin for a document which 115 // has been open()ed is the origin of the calling code, somewhat loosely 116 // speaking. For the specific case of about:blank it's also possible 117 // that the origin is determined by the code that opens the window. It's 118 // not codified yet which of these two causes the identifier tokens on 119 // the event generated by the new window to be those of this window, but 120 // in either case this is what they should be. 121 is(evt.origin, "http://mochi.test:8888", 122 "wrong origin for event from about:blank"); 123 is(evt.source, aboutBlankWindow, "wrong source"); 124 125 // ...and onto the next test 126 setupBlank2(); 127 } 128 else if (evt.data === "about:blank2-response") 129 { 130 is(evt.origin, "http://mochi.test:8888", 131 "wrong origin for event from about:blank #2"); 132 is(evt.source, aboutBlank2Window, "wrong source"); 133 134 setupData(); 135 } 136 else if (evt.data === "data-response") 137 { 138 is(evt.origin, "null", 139 "wrong origin for event from data URL (should be the origin of the " + 140 "window/script that opened the URL, in this case the origin of this " + 141 "file)"); 142 is(evt.source, dataWindow, "wrong source"); 143 144 finish(); 145 } 146 else 147 { 148 ok(false, "unexpected message: " + evt.data); 149 } 150 } 151 catch (e) 152 { 153 ok(false, "error processing event with data '" + evt.data + "': " + e); 154 } 155 } 156 157 function getContents(description, responseText) 158 { 159 var contents = 160 "<!DOCTYPE html>\n" + 161 "<html>\n" + 162 "<head>\n" + 163 " <title>about:blank</title>\n" + 164 " <script type='application/javascript'>\n" + 165 "function receive(evt)\n" + 166 "{\n" + 167 " var response = '" + responseText + "';\n" + 168 "\n" + 169 " if (evt.source !== window.parent)\n" + 170 " response += ' wrong-source';\n" + 171 " if (evt.origin !== 'http://mochi.test:8888')\n" + 172 " response += ' wrong-origin(' + evt.origin + ')';\n" + 173 " if (evt.data !== 'from-opener')\n" + 174 " response += ' wrong-data(' + evt.data + ')';\n" + 175 "\n" + 176 " window.parent.postMessage(response, 'http://mochi.test:8888');\n" + 177 "}\n" + 178 "\n" + 179 "function ready()\n" + 180 "{\n" + 181 " window.parent.postMessage('next-test', 'http://mochi.test:8888');\n" + 182 "}\n" + 183 "\n" + 184 "window.addEventListener('load', ready, false);\n" + 185 "window.addEventListener('message', receive, false);\n" + 186 " </script>\n" + 187 "</head>\n" + 188 "<body><p>" + description + "</p></body>\n" + 189 "</html>"; 190 191 return contents; 192 } 193 194 function finish() 195 { 196 SimpleTest.finish(); 197 } 198 199 var xhtmlns = "http://www.w3.org/1999/xhtml"; 200 201 function insert(el) 202 { 203 var content = $("content"); 204 content.parentNode.insertBefore(el, content); 205 } 206 207 function setupBlank() 208 { 209 var aboutBlankFrame = document.createElementNS(xhtmlns, "iframe"); 210 aboutBlankFrame.setAttribute("src", "about:blank"); 211 insert(aboutBlankFrame); 212 213 aboutBlankWindow = aboutBlankFrame.contentWindow; 214 var doc = aboutBlankWindow.document; 215 doc.open(); 216 doc.write(getContents("This was about:blank #1", "about:blank-response")); 217 doc.close(); 218 219 // I don't believe anything guarantees sync parsing, so we have to wait for 220 // the new window to poke us to actually do the test. :-\ 221 } 222 223 function setupBlank2() 224 { 225 var aboutBlank2Frame = document.createElementNS(xhtmlns, "iframe"); 226 aboutBlank2Frame.addEventListener("load", nextTest); 227 aboutBlank2Frame.setAttribute("src", "about:blank"); 228 229 insert(aboutBlank2Frame); 230 } 231 232 // Could use window.btoa here, but that's not standardized, and we want to be 233 // able to run these tests against browsers that don't support it. 234 var dataURI = "data:text/html;base64," + 235 b64(getContents("A data: URL", "data-response")); 236 237 function setupData() 238 { 239 var dataFrame = document.createElementNS(xhtmlns, "iframe"); 240 dataFrame.setAttribute("src", dataURI); 241 insert(dataFrame); 242 243 dataWindow = dataFrame.contentWindow; 244 245 // ...and wait again for the window to load... 246 } 247 248 var count = 0; 249 function nextTest() 250 { 251 switch (count++) 252 { 253 case 0: 254 testBlank(); 255 break; 256 257 case 1: 258 testBlank2(); 259 break; 260 261 case 2: 262 testData(); 263 break; 264 265 default: 266 ok(false, "unreached"); 267 break; 268 } 269 } 270 271 function testBlank() 272 { 273 aboutBlankWindow.postMessage("from-opener", "http://mochi.test:8888"); 274 } 275 276 function testBlank2() 277 { 278 // For some reason we can't access this across browsers prior to the iframe 279 // loading, so set its value here. 280 aboutBlank2Window = window.frames[1]; 281 282 var doc = aboutBlank2Window.document; 283 284 doc.body.textContent = "This was about:blank #2"; 285 286 var script = doc.createElement("script"); 287 script.textContent = 288 "window.parent.postMessage('about:blank2-response', " + 289 " 'http://mochi.test:8888');"; 290 doc.body.appendChild(script); 291 } 292 293 function testData() 294 { 295 dataWindow.postMessage("from-opener", "*"); 296 } 297 298 window.addEventListener("message", messageReceiver); 299 300 addLoadEvent(setupBlank); 301 ]]></script> 302 </pre> 303 </body> 304 </html>