mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
357 lines
9.3 KiB
HTML
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>
|