gecko/dom/tests/mochitest/whatwg/test_postMessage_special.xhtml

357 lines
9.3 KiB
HTML

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=postMessage
-->
<head>
<title>postMessage from about:blank, data URLs</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="browserFu.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=postMessage">Mozilla Bug 387706</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
<script class="testbody" type="application/javascript"><![CDATA[
/** Test for Bug 387706 **/
SimpleTest.waitForExplicitFinish();
var B64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/**
* Encodes an array of bytes into a string using the base 64 encoding scheme.
*
* @param bytes
* An array of bytes to encode.
*/
function b64(str)
{
var byteArray = new Array(str.length);
for (var i = 0, sz = str.length; i < sz; i++)
byteArray[i] = str.charCodeAt(i);
var index = 0;
function get3Bytes()
{
if (byteArray.length - index < 3)
return null; // Less than three bytes remaining
// Return the next three bytes in the array, and increment index for our
// next invocation
return byteArray.slice(index, index += 3);
}
var out = "";
var bytes = null;
while ((bytes = get3Bytes()))
{
var bits = 0;
for (var i = 0; i < 3; i++)
bits = (bits << 8) | bytes[i];
for (var j = 18; j >= 0; j -= 6)
out += B64_CHARS[(bits>>j) & 0x3F];
}
// Get the remaining bytes
bytes = byteArray.slice(index);
switch (bytes.length)
{
case 2:
out += B64_CHARS[(bytes[0]>>2) & 0x3F] +
B64_CHARS[((bytes[0] & 0x03) << 4) | ((bytes[1] >> 4) & 0x0F)] +
B64_CHARS[((bytes[1] & 0x0F) << 2)] +
"=";
break;
case 1:
out += B64_CHARS[(bytes[0]>>2) & 0x3F] +
B64_CHARS[(bytes[0] & 0x03) << 4] +
"==";
break;
}
return out;
}
var aboutBlankWindow = null;
var aboutBlank2Window = null;
var dataWindow = null;
var aboutBlankResponseReceived = false;
var aboutBlank2ResponseReceived = false;
var dataResponseReceived = false;
var finished = false;
/** Convert a nullable string to a pretty representation */
function sourceify(v)
{
if (typeof v == "string")
return "'" + v + "'";
return String(v);
}
/** Receives MessageEvents to this window. */
function messageReceiver(evt)
{
// It's not clear what the security model is for data: URLs and whether they
// can access their parents; WebKit denies access, while Gecko currently
// allows it. We work around this problem by using postMessage (surprise!)
// to start the round of tests when each iframe loads.
if (evt.data === "next-test")
{
setTimeout(nextTest, 0);
return;
}
try
{
ok(evt instanceof MessageEvent, "umm, how did we get this?");
is(evt.type, "message", "expected events of type 'message'");
if (isMozilla)
{
ok(evt.isTrusted === false, "shouldn't have been a trusted event");
}
if (evt.data === "about:blank-response")
{
// This isn't clarified in HTML5 yet, but the origin for a document which
// has been open()ed is the origin of the calling code, somewhat loosely
// speaking. For the specific case of about:blank it's also possible
// that the origin is determined by the code that opens the window. It's
// not codified yet which of these two causes the identifier tokens on
// the event generated by the new window to be those of this window, but
// in either case this is what they should be.
is(evt.origin, "http://localhost:8888",
"wrong origin for event from about:blank");
is(evt.source, aboutBlankWindow, "wrong source");
// ...and onto the next test
aboutBlankResponseReceived = true;
setupBlank2();
}
else if (evt.data === "about:blank2-response")
{
is(evt.origin, "http://localhost:8888",
"wrong origin for event from about:blank #2");
is(evt.source, aboutBlank2Window, "wrong source");
aboutBlank2ResponseReceived = true;
setupData();
}
else if (evt.data === "data-response")
{
// HTML5 defines the origin of a data: URI as the origin of the window or
// script that opened the data: URI.
is(evt.origin, "http://localhost:8888",
"wrong origin for event from data URL (should be the origin of the " +
"window/script that opened the URL, in this case the origin of this " +
"file)");
is(evt.source, dataWindow, "wrong source");
dataResponseReceived = true;
finish();
}
else
{
ok(false, "unexpected message: " + evt.data);
}
}
catch (e)
{
ok(false, "error processing event with data '" + evt.data + "': " + e);
}
}
function getContents(description, responseText)
{
var contents =
"<!DOCTYPE html>\n" +
"<html>\n" +
"<head>\n" +
" <title>about:blank</title>\n" +
" <script type='application/javascript'>\n" +
"function receive(evt)\n" +
"{\n" +
" var response = '" + responseText + "';\n" +
"\n" +
" if (evt.source !== window.parent)\n" +
" response += ' wrong-source';\n" +
" if (evt.origin !== 'http://localhost:8888')\n" +
" response += ' wrong-origin(' + evt.origin + ')';\n" +
" if (evt.data !== 'from-opener')\n" +
" response += ' wrong-data(' + evt.data + ')';\n" +
"\n" +
" window.parent.postMessage(response, 'http://localhost:8888');\n" +
"}\n" +
"\n" +
"function ready()\n" +
"{\n" +
" window.parent.postMessage('next-test', 'http://localhost:8888');\n" +
"}\n" +
"\n" +
"window.addEventListener('load', ready, false);\n" +
"window.addEventListener('message', receive, false);\n" +
" </script>\n" +
"</head>\n" +
"<body><p>" + description + "</p></body>\n" +
"</html>";
return contents;
}
/** Finish the test, but don't finish twice if we timed out. */
function finish()
{
if (!finished)
{
finished = true;
SimpleTest.finish();
}
}
var xhtmlns = "http://www.w3.org/1999/xhtml";
function insert(el)
{
var content = $("content");
content.parentNode.insertBefore(el, content);
}
var LOAD_TIMEOUT = 5000;
function setupBlank()
{
var aboutBlankFrame = document.createElementNS(xhtmlns, "iframe");
aboutBlankFrame.setAttribute("src", "about:blank");
insert(aboutBlankFrame);
aboutBlankWindow = aboutBlankFrame.contentWindow;
var doc = aboutBlankWindow.document;
doc.open();
doc.write(getContents("This was about:blank #1", "about:blank-response"));
doc.close();
// I don't believe anything guarantees sync parsing, so we have to wait for
// the new window to poke us to actually do the test. :-\
// Catch recalcitrant browsers that fail inside the iframe document code.
setTimeout(blankFailed, LOAD_TIMEOUT);
}
function blankFailed()
{
if (!aboutBlankResponseReceived && !finished)
{
ok(false,
"test timed out (postMessage not accessible on window.parent in " +
"the first about:blank iframe?)");
finish();
}
}
function setupBlank2()
{
var aboutBlank2Frame = document.createElementNS(xhtmlns, "iframe");
aboutBlank2Frame.addEventListener("load", nextTest, false);
aboutBlank2Frame.setAttribute("src", "about:blank");
insert(aboutBlank2Frame);
}
// Could use window.btoa here, but that's not standardized, and we want to be
// able to run these tests against browsers that don't support it.
var dataURI = "data:text/html;base64," +
b64(getContents("A data: URL", "data-response"));
function setupData()
{
var dataFrame = document.createElementNS(xhtmlns, "iframe");
dataFrame.setAttribute("src", dataURI);
insert(dataFrame);
dataWindow = dataFrame.contentWindow;
// ...and wait again for the window to load...
// Catch recalcitrant browsers that fail inside the iframe document code.
setTimeout(dataFailed, LOAD_TIMEOUT);
}
function dataFailed()
{
if (!dataResponseReceived && !finished)
{
ok(false,
"test timed out (postMessage not accessible on window.parent in " +
"the data: iframe?)");
finish();
}
}
var count = 0;
function nextTest()
{
switch (count++)
{
case 0:
testBlank();
break;
case 1:
testBlank2();
break;
case 2:
testData();
break;
default:
ok(false, "unreached");
break;
}
}
function testBlank()
{
aboutBlankWindow.postMessage("from-opener", "http://localhost:8888");
}
function testBlank2()
{
// For some reason we can't access this across browsers prior to the iframe
// loading, so set its value here.
aboutBlank2Window = window.frames[1];
var doc = aboutBlank2Window.document;
doc.body.textContent = "This was about:blank #2";
var script = doc.createElement("script");
script.textContent =
"window.parent.postMessage('about:blank2-response', " +
" 'http://localhost:8888');";
doc.body.appendChild(script);
}
function testData()
{
dataWindow.postMessage("from-opener", "http://localhost:8888");
}
window.addEventListener("message", messageReceiver, false);
addLoadEvent(setupBlank);
]]></script>
</pre>
</body>
</html>