merge testJam branch to default
authorGopal Raghavan <gopal.raghavan@nokia.com>
Sun, 23 Sep 2012 18:51:05 -0700
changeset 72 b78c75181d7f
parent 71 746643cbf781 (current diff)
parent 64 a0c38d9d0489 (diff)
child 73 728f2932fb9e
merge testJam branch to default
--- a/tests/cors/submitted/bhill2/redir-test.html	Fri Aug 24 11:03:38 2012 +0200
+++ b/tests/cors/submitted/bhill2/redir-test.html	Sun Sep 23 18:51:05 2012 -0700
@@ -11,7 +11,7 @@
 		<script>
 			function dirname(path) { return path.replace(/\/[^\/]*$/,'/') }
 
-			var crossdomain = dirname(location.href).replace('://www.','://www3.');
+			var crossdomain = dirname(location.href).replace('://www.','://www2.');
 
 			var t = async_test("Test async CORS request modifies Origin on cross-domain redirection to prevent reflection/redirection attacks.");
 		</script>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/cors1.0/MANIFEST	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,5 @@
+access-control-basic-allow.html
+access-control-basic-allow-star.html
+access-control-basic-denied.html
+access-control-basic-allow-access-control-origin-header.html
+access-control-basic-non-simple-allow.html
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/cors1.0/access-control-basic-allow-access-control-origin-header.html	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,50 @@
+<html>
+<body>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+<pre id='console'></pre>
+<div  id=log></div>
+
+
+<script type="text/javascript">
+function log(message)
+{
+    document.getElementById('console').appendChild(document.createTextNode(message + "\n"));
+}
+
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+
+var accessControlBasicAllowAccessControlOriginHeader = function() {
+    var xhr = new XMLHttpRequest;
+    var path = "/webappsec/tests/cors/submitted/cors1.0";
+
+    try {
+        xhr.open("GET", "http://www1.w3c-test.org" + path + "/resources/access-control-basic-allow-access-control-origin-header.php", false);
+    } catch(e) {
+        log("FAIL: Exception thrown. Cross-domain access is not allowed in 'open'. [" + e.message + "].");
+        assert_true(false);
+        return;
+    }
+
+    try {
+        xhr.send();
+	assert_true(true);
+    } catch(e) {
+        log("FAIL: Exception thrown. Cross-domain access is not allowed in 'send'. [" + e.message + "].");
+        assert_true(false);
+        return;
+    }
+
+    //log(xhr.responseText);
+};
+
+test(accessControlBasicAllowAccessControlOriginHeader, "access-control-basic-allow-access-control-origin-header")
+
+
+if (window.layoutTestController)
+    layoutTestController.notifyDone();  
+</script>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/cors1.0/access-control-basic-allow-access-control-origin-header.js	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,25 @@
+var accessControlBasicAllowAccessControlOriginHeader = function() {
+    var xhr = new XMLHttpRequest;
+    var path = "/webappsec/tests/cors/submitted/webkit";
+
+    try {
+        xhr.open("GET", "http://www1.w3c-test.org" + path + "/resources/access-control-basic-allow-access-control-origin-header.php", false);
+    } catch(e) {
+        log("FAIL: Exception thrown. Cross-domain access is not allowed in 'open'. [" + e.message + "].");
+        assert_true(false);
+        return;
+    }
+
+    try {
+        xhr.send();
+	assert_true(true);
+    } catch(e) {
+        log("FAIL: Exception thrown. Cross-domain access is not allowed in 'send'. [" + e.message + "].");
+        assert_true(false);
+        return;
+    }
+
+    //log(xhr.responseText);
+};
+
+test(accessControlBasicAllowAccessControlOriginHeader, "access-control-basic-allow-access-control-origin-header")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/cors1.0/access-control-basic-allow-star.html	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,52 @@
+<html>
+<body>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+<pre id='console'></pre>
+<div  id=log></div>
+
+
+<script type="text/javascript">
+function log(message)
+{
+    document.getElementById('console').appendChild(document.createTextNode(message + "\n"));
+}
+
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+
+
+var accessControlBasicAllowStar = function() {
+    var xhr = new XMLHttpRequest;
+    var path = "/webappsec/tests/cors/submitted/cors1.0";
+
+    try {
+        xhr.open("GET", "http://www1.w3c-test.org" + path + "/resources/access-control-basic-allow-star.php", false);
+
+    } catch(e) {
+        log("FAIL: Exception thrown. Cross-domain access is not allowed in 'open'. [" + e.message + "].");
+        return;
+    }
+
+    try {
+        xhr.send();
+        console.log(xhr.responseText);
+        assert_equals(xhr.responseText,"PASS: Cross-domain access allowed.", "test for cross domain" );
+    } catch(e) {
+        log("FAIL: Exception thrown. Cross-domain access is not allowed in 'send'. [" + e.message + "].");
+        assert_true(false);
+        return;
+    }
+
+    //log(xhr.responseText);
+};
+
+test(accessControlBasicAllowStar, "access-control-basic-allow-star")
+
+
+if (window.layoutTestController)
+    layoutTestController.notifyDone();  
+</script>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/cors1.0/access-control-basic-allow-star.js	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,27 @@
+var accessControlBasicAllowStar = function() {
+    var xhr = new XMLHttpRequest;
+    var path = "/webappsec/tests/cors/submitted/webkit";
+
+    try {
+        xhr.open("GET", "http://www1.w3c-test.org" + path + "/resources/access-control-basic-allow-star.php", false);
+
+    } catch(e) {
+        log("FAIL: Exception thrown. Cross-domain access is not allowed in 'open'. [" + e.message + "].");
+        return;
+    }
+
+    try {
+        xhr.send();
+        console.log(xhr.responseText);
+        assert_equals(xhr.responseText,"PASS: Cross-domain access allowed.", "test for cross domain" );
+    } catch(e) {
+        log("FAIL: Exception thrown. Cross-domain access is not allowed in 'send'. [" + e.message + "].");
+        assert_true(false);
+        return;
+    }
+
+    //log(xhr.responseText);
+};
+
+test(accessControlBasicAllowStar, "access-control-basic-allow-star")
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/cors1.0/access-control-basic-allow.html	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,51 @@
+<html>
+<body>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+<pre id='console'></pre>
+<div  id=log></div>
+
+<script type="text/javascript">
+function log(message)
+{
+    document.getElementById('console').appendChild(document.createTextNode(message + "\n"));
+}
+
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+
+var accessControlBasicAllow = function() {
+    var xhr = new XMLHttpRequest;
+    var path = "/webappsec/tests/cors/submitted/cors1.0";
+
+    try {
+        xhr.open("GET", "http://www1.w3c-test.org" + path + "/resources/access-control-basic-allow.php", false);
+
+    } catch(e) {
+        log("FAIL: Exception thrown. Cross-domain access is not allowed in 'open'. [" + e.message + "].");
+        assert_true(false);
+        return;
+    }
+
+    try {
+        xhr.send();
+        console.log(xhr.responseText);
+        assert_equals(xhr.responseText,"PASS: Cross-domain access allowed.", "test for cross domain" );
+    } catch(e) {
+        log("FAIL: Exception thrown. Cross-domain access is not allowed in 'send'. [" + e.message + "].");
+        assert_true(false);
+        return;
+    }
+
+    //log(xhr.responseText);
+};
+
+test(accessControlBasicAllow, "access-control-basic-allow")
+
+
+if (window.layoutTestController)
+    layoutTestController.notifyDone();  
+</script>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/cors1.0/access-control-basic-allow.js	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,28 @@
+var accessControlBasicAllow = function() {
+    var xhr = new XMLHttpRequest;
+    var path = "/webappsec/tests/cors/submitted/webkit";
+
+    try {
+        xhr.open("GET", "http://www1.w3c-test.org" + path + "/resources/access-control-basic-allow.php", false);
+
+    } catch(e) {
+        log("FAIL: Exception thrown. Cross-domain access is not allowed in 'open'. [" + e.message + "].");
+        assert_true(false);
+        return;
+    }
+
+    try {
+        xhr.send();
+        console.log(xhr.responseText);
+        assert_equals(xhr.responseText,"PASS: Cross-domain access allowed.", "test for cross domain" );
+    } catch(e) {
+        log("FAIL: Exception thrown. Cross-domain access is not allowed in 'send'. [" + e.message + "].");
+        assert_true(false);
+        return;
+    }
+
+    //log(xhr.responseText);
+};
+
+test(accessControlBasicAllow, "access-control-basic-allow")
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/cors1.0/access-control-basic-denied.html	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,50 @@
+<html>
+<body>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+<pre id='console'></pre>
+<div  id=log></div>
+
+
+<script type="text/javascript">
+function log(message)
+{
+    document.getElementById('console').appendChild(document.createTextNode(message + "\n"));
+}
+
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+
+
+var accessControlBasicDenied = function() {
+    var xhr = new XMLHttpRequest;
+    var path = "/webappsec/tests/cors/submitted/cors1.0";
+
+    try {
+        xhr.open("GET", "http://www1.w3c-test.org" + path + "/resources/access-control-basic-denied.php", false);
+    } catch(e) {
+        log("FAIL: Exception thrown. Cross-domain access is not allowed in 'open'. [" + e.message + "].");
+        assert_true(false);
+        return;
+    }
+
+    try {
+        xhr.send();
+        assert_true(false);
+    } catch(e) {
+        assert_true(true);
+        //log("PASS: Exception thrown. Cross-domain access was denied in 'send'. [" + e.message + "].");
+        return;
+    }
+
+    log(xhr.responseText);
+};
+
+test(accessControlBasicDenied, "access-control-basic-denied")
+
+if (window.layoutTestController)
+    layoutTestController.notifyDone();  
+</script>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/cors1.0/access-control-basic-denied.js	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,25 @@
+var accessControlBasicDenied = function() {
+    var xhr = new XMLHttpRequest;
+    var path = "/webappsec/tests/cors/submitted/webkit";
+
+    try {
+        xhr.open("GET", "http://www1.w3c-test.org" + path + "/resources/access-control-basic-denied.php", false);
+    } catch(e) {
+        log("FAIL: Exception thrown. Cross-domain access is not allowed in 'open'. [" + e.message + "].");
+        assert_true(false);
+        return;
+    }
+
+    try {
+        xhr.send();
+        assert_true(false);
+    } catch(e) {
+        assert_true(true);
+        //log("PASS: Exception thrown. Cross-domain access was denied in 'send'. [" + e.message + "].");
+        return;
+    }
+
+    log(xhr.responseText);
+};
+
+test(accessControlBasicDenied, "access-control-basic-denied")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/cors1.0/access-control-basic-non-simple-allow.html	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,43 @@
+<html>
+<body>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+<pre id='console'></pre>
+<div  id=log></div>
+<script type="text/javascript">
+function log(message)
+{
+    document.getElementById('console').appendChild(document.createTextNode(message + "\n"));
+}
+
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+
+var accessControlBasicNonSimpleAllow = function() {
+    var xhr = new XMLHttpRequest;
+    var path = "/webappsec/tests/cors/submitted/cors1.0";
+
+    try {
+        xhr.open("PUT", "http://www1.w3c-test.org" + path + "/resources/access-control-basic-non-get-allow.php", false);
+    } catch(e) {
+        log("FAIL: Exception thrown. Cross-domain access is not allowed in 'open'. [" + e.message + "].");
+        return;
+    }
+
+    xhr.setRequestHeader("Content-Type", "text/plain; charset=UTF-8");
+
+    try {
+        xhr.send("PASS: PUT data received");
+    } catch(e) {
+        log("FAIL: Exception thrown. Cross-domain access is not allowed in 'send'. [" + e.message + "].");
+        return;
+    }
+
+    //log(xhr.responseText);
+};
+test(accessControlBasicNonSimpleAllow, "access-control-basic-non-simple-allow")
+
+</script>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/cors1.0/cors-tests.html	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,17 @@
+<html>
+<body>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+<pre id='console'></pre>
+ <script src="/webappsec/tests/cors/submitted/webkit/log.js"></script>
+<h2>W3C WebAppSec Cross-Origin Resource Sharing</h2>
+<a href="http://www.w3.org/TR/cors"> http://www.w3.org/TR/cors/</a>
+<!-- <h3>Test suite compliant with working draft 3 April 2012</h3> -->
+ <script src="/webappsec/tests/cors/submitted/webkit/access-control-basic-allow.js"></script>
+ <script src="/webappsec/tests/cors/submitted/webkit/access-control-basic-allow-star.js"></script>
+ <script src="/webappsec/tests/cors/submitted/webkit/access-control-basic-denied.js"></script>
+ <script src="/webappsec/tests/cors/submitted/webkit/access-control-basic-allow-access-control-origin-header.js"></script>
+<div  id=log></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/cors1.0/log.js	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,5 @@
+function log(message)
+{
+    document.getElementById('console').appendChild(document.createTextNode(message + "\n"));
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/cors1.0/resources/access-control-basic-allow-access-control-origin-header.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,7 @@
+<?php
+header("Content-Type: text/plain");
+header("Cache-Control: no-cache, no-store\n");
+header("Access-Control-Allow-Origin: *\n\n");
+echo "PASS: Cross-domain access allowed.";
+echo "HTTP_ORIGIN: " . $ENV{"HTTP_ORIGIN"} . "\n";
+?>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/cors1.0/resources/access-control-basic-allow-star.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,5 @@
+<?php
+header("Content-Type: text/plain");
+header("Access-Control-Allow-Origin: *\n\n");
+echo "PASS: Cross-domain access allowed.";
+?>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/cors1.0/resources/access-control-basic-allow.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,6 @@
+<?php
+header("Content-Type: text/plain");
+header("Access-Control-Allow-Credentials: true");
+header("Access-Control-Allow-Origin: http://www.w3c-test.org\n\n");
+echo "PASS: Cross-domain access allowed.";
+?>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/cors1.0/resources/access-control-basic-denied.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,4 @@
+<?php
+header("Content-Type: text/plain");
+echo "FAIL: Cross-domain access allowed.";
+?>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/cors1.0/resources/access-control-basic-non-get-allow.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,21 @@
+<?PHP
+
+if ($_SERVER['REQUEST_METHOD'] == "OPTIONS") {
+    header("Content-Type: text/plain");
+    header("Access-Control-Allow-Credentials: true");
+    header("Access-Control-Allow-Methods: PUT");
+    header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);
+} elseif ($_SERVER['REQUEST_METHOD'] == "PUT") {
+    header("Content-Type: text/plain");
+    header("Access-Control-Allow-Credentials: true");
+    header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);
+
+    echo "PASS: Cross-domain access allowed.\n";
+    $request_body = @file_get_contents('php://input');
+    echo $request_body ;
+} else {
+    header("Content-Type: text/plain");
+    echo "Wrong method: " . $_SERVER['REQUEST_METHOD'] . "\n";
+}
+
+?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/webkit/resources/access-control-basic-allow-access-control-origin-header.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,11 @@
+<?php
+
+header("Content-Type: text/plain");
+header("Cache-Control: no-cache, no-store");
+header("Access-Control-Allow-Origin: *");
+
+echo "PASS: Cross-domain access allowed.\n";
+echo "HTTP_ORIGIN: " .  $_SERVER["HTTP_ORIGIN"] . "\n"
+
+?>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/webkit/resources/access-control-basic-allow-print-headers.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,10 @@
+<?php
+    header("Content-Type: text/plain");
+    header("Cache-Control: no-store");
+    header("Access-Control-Allow-Origin: *");
+
+    foreach($_SERVER as $h=>$v)
+     if(ereg('HTTP_(.+)',$h,$hp))
+       echo "$h = $v\n";
+
+?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/webkit/resources/access-control-basic-allow-star.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,7 @@
+<?php
+
+header("Content-Type: text/plain");
+header("Access-Control-Allow-Origin: *");
+
+echo "PASS: Cross-domain access allowed.";
+?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/webkit/resources/access-control-basic-allow.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,10 @@
+<?php
+
+header("Content-Type: text/plain");
+header("Access-Control-Allow-Credentials: true");
+header("Access-Control-Allow-Origin:" . $_SERVER['HTTP_ORIGIN']);
+
+echo "PASS: Cross-domain access allowed.";
+
+?>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/webkit/resources/access-control-basic-denied.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,5 @@
+<?php
+    header("Content-Type: text/plain");
+
+    echo "FAIL: Cross-domain access allowed.";
+?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/webkit/resources/access-control-basic-whitelist-request-headers.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,17 @@
+<?php
+    header("Cache-Control: no-store");
+
+    if ($_SERVER['REQUEST_METHOD'] == "POST") {
+    	header("Access-Control-Allow-Credentials: true");
+    	header("Access-Control-Allow-Origin: http://127.0.0.1:80");
+
+    	header("Accept: " . $_SERVER['HTTP_ACCEPT']);
+    	header("Accept-Language: " . $_SERVER['HTTP_ACCEPT_LANGUAGE']);
+    	header("Content-Language: " . $_SERVER['HTTP_CONTENT_LANGUAGE']);
+    	header("Content-Type: " . $_SERVER['CONTENT_TYPE']);
+
+    } else {
+    	echo "\n";
+    }
+?>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/webkit/resources/access-control-basic-whitelist-response-headers.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,18 @@
+<?php
+
+#in whitelist
+header("content-type: text/plain");
+header("cache-control: no cache");
+header("content-language: en");
+header("expires: Fri, 30 Oct 1998 14:19:41 GMT");
+header("last-modified: Tue, 15 Nov 1994 12:45:26 GMT");
+header("pragma: no-cache");
+
+#not in whitelist
+header("x-webkit: foobar");
+
+header("Access-Control-Allow-Origin: *");
+
+echo "PASS: Cross-domain access allowed.";
+?>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/webkit/resources/access-control-sandboxed-iframe-allow.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,9 @@
+<?php
+
+header("Content-Type: text/plain");
+header("Access-Control-Allow-Credentials: true");
+header("Access-Control-Allow-Origin: *");
+
+echo "PASS: Sandboxed iframe XHR access allowed.";
+?>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/webkit/resources/access-control-sandboxed-iframe-denied-without-wildcard.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,8 @@
+<?php
+    header("Content-Type: text/plain");
+    header("Access-Control-Allow-Credentials: true");
+    header("Access-Control-Allow-Origin: http://127.0.0.1:80");
+
+    echo "FAIL: Sandboxed iframe XHR access allowed.";
+
+?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cors/submitted/webkit/resources/access-control-sandboxed-iframe-denied.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,7 @@
+<?php
+
+header("Content-Type: text/plain");
+
+echo "FAIL: Sandboxed iframe XHR access allowed.";
+
+?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/csp/redir-test.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,6 @@
+<?php
+
+TODO: get url, change host to www2, keep path and use "getOrigin.php"
+
+header("Location: ");
+?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/csp/submitted/bhill2/CSP_001.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,24 @@
+<?php
+header("Content-Security-Policy: default-src *");
+header("X-Content-Security-Policy: default-src *");
+header("X-WebKit-CSP: default-src *");
+?>
+<!DOCTYPE html>
+<html>
+	<head>
+		<title>CSP Test: default-src: *</title>
+		<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+		<meta descriptionn="Content-Security-Policy Test: default-src: *" />
+		<link rel="author" title="bhill@paypal-inc.com" />
+		<script src="http://www.w3c-test.org/resources/testharness.js"></script>
+		<script src="http://www.w3c-test.org/resources/testharnessreport.js"></script>
+		<script src="CSP_passTest001.php"></script>
+	</head>
+	<body>
+		<div id=log></div>
+	</body>
+
+	<script>
+		test(function() {assert_true(false)}, "assert_true with false from unsafe inline script");
+	</script>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/csp/submitted/bhill2/CSP_002.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,24 @@
+<?php
+header("Content-Security-Policy: default-src 'self'");
+header("X-Content-Security-Policy: default-src 'self'");
+header("X-WebKit-CSP: default-src 'self'");
+?>
+<!DOCTYPE html>
+<html>
+	<head>
+		<title>CSP Test: default-src: 'self'</title>
+		<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+		<meta description="Content-Security-Policy Test: default-src: 'self'" />
+		<link rel="author" title="bhill@paypal-inc.com" />
+		<script src="/resources/testharness.js"></script>
+		<script src="/resources/testharnessreport.js"></script>
+		<script src="CSP_passTest001.php"></script>
+	</head>
+	<body>
+		<div id=log></div>
+	</body>
+
+	<script>
+		test(function() {assert_true(false)}, "assert_true with false from unsafe inline script");
+	</script>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/csp/submitted/bhill2/CSP_003.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,35 @@
+<?php
+header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'");
+header("X-Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'");
+header("X-WebKit-CSP: default-src 'self'; script-src 'self' 'unsafe-inline'");
+?>
+<!DOCTYPE html>
+<html>
+	<head>
+		<title>CSP Test: default-src: 'self'; script-src 'self' 'unsafe-inline'</title>
+		<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+		<meta description="Content-Security-Policy Test: default-src: 'self'; script-src 'self' 'unsafe-inline'" />
+		<link rel="author" title="bhill@paypal-inc.com" />
+		<script src="/resources/testharness.js"></script>
+		<script src="/resources/testharnessreport.js"></script>
+	</head>
+	<body>
+		<div id=log></div>
+	</body>
+	<!--
+		This test demonstrates how to test something that shouldn't happen, or 
+		fail when something that should happend doesn't.  Use script with
+		conditional execution based on the policy being tested to set a variable,
+		then use script we know will execute by policy to check if it is set.
+		
+		Some limitations on this approach, obviously, if policy enforcement is
+		very broken - when we can't count on any script to execute - but this
+		is a start, at least.
+	-->	
+
+	<script>
+		var unsafeScript = true;
+	</script>
+
+	<script src="assertTrue.php?varName=unsafeScript"></script>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/csp/submitted/bhill2/CSP_passTest001.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,7 @@
+<?php
+header("Content-type: text/javascript");
+?>
+(function ()
+{
+	test(function() {assert_true(true)}, "assert_true with true");
+})();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/csp/submitted/bhill2/assertTrue.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,15 @@
+<?php
+
+//Prevent Caching
+header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
+header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
+header("Cache-Control: no-store, no-cache, must-revalidate");
+header("Cache-Control: post-check=0, pre-check=0", false);
+header("Pragma: no-cache");
+header("Content-Type: text/javascript");
+
+
+print("(function () { test(function() {assert_true(" . $_GET["varName"] . ")}, \"assert_true with varName\"); })();");
+
+?>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/csp/submitted/mozilla/assertTrue.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,18 @@
+<?php
+
+//Prevent Caching
+header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
+header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
+header("Cache-Control: no-store, no-cache, must-revalidate");
+header("Cache-Control: post-check=0, pre-check=0", false);
+header("Pragma: no-cache");
+header("Content-Type: text/javascript");
+
+	print("(function () { if(typeof " . $_GET["varName"] . "=='undefined') {
+				 test(function() {assert_true(true)}, \"assert_true with unsafeScript\"); 
+		        	} else{
+				   test(function() {assert_true(" . $_GET["varName"] . ")}, \"assert_true with unsafeScript defined when it shouldn't be\"); 
+				}  })();");
+
+?>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/csp/submitted/mozilla/csp-inline-script.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,22 @@
+<?php
+	header("X-WebKit-CSP: default-src 'self'");
+	header("X-Content-Security-Policy: default-src 'self'");
+	header("Content-Security-Policy: default-src 'self'");
+?>
+<html>
+<head>
+	<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+	<meta description="Content-Security-Policy Test: default-src: *" />
+	<link rel="author" title="tanvi@mozilla.com" />
+	<title> No inline script </title>
+	<script src="http://www.w3c-test.org/resources/testharness.js"></script>
+	<script src="http://www.w3c-test.org/resources/testharnessreport.js"></script>
+</head>
+
+<body>
+	<div id=log></div>
+	<script>
+		unsafeScript=false;
+	</script>
+	<script src="assertTrue.php?varName=unsafeScript"></script>
+</body>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/csp/submitted/webkit/CSP_default-src-inline-allowed.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,25 @@
+<?php
+header("Content-Security-Policy: default-src 'self' about: 'unsafe-inline'");
+header("X-Content-Security-Policy: default-src 'self' about: 'unsafe-inline'");
+header("X-WebKit-CSP: default-src 'self' about: 'unsafe-inline'");
+?>
+<!DOCTYPE html>
+<html>
+<head>
+<title>CSP Test: default-src 'self' about: 'unsafe-inline'</title>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+<meta descriptionn="Content-Security-Policy Test: default-src 'self' about: 'unsafe-inline'" />
+<link rel="author" title="abarth" />
+<script src="http://www.w3c-test.org/resources/testharness.js"></script>
+<script src="http://www.w3c-test.org/resources/testharnessreport.js"></script>
+</head>
+<div id="log"></div>
+<script>
+test(function() {assert_true(true)}, 'Inline scripts run (1 of 3)');
+</script>
+<iframe style="display:none" src="javascript:parent.test(function() {parent.assert_true(true)}, 'JavaScript URLs run (2 of 3)');"></iframe>
+<img style="display:none"
+     onerror="test(function() {assert_true(true)}, 'Inline event handlers run (3 of 3)')"
+     src="about:blank">
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/csp/submitted/webkit/CSP_default-src-inline-blocked.php	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,26 @@
+<?php
+header("Content-Security-Policy: default-src 'self'");
+header("X-Content-Security-Policy: default-src 'self'");
+header("X-WebKit-CSP: default-src 'self'");
+?>
+<!DOCTYPE html>
+<html>
+<head>
+<title>CSP Test: default-src 'self' about: 'unsafe-inline'</title>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+<meta descriptionn="Content-Security-Policy Test: default-src 'self' about: 'unsafe-inline'" />
+<link rel="author" title="abarth" />
+<script src="http://www.w3c-test.org/resources/testharness.js"></script>
+<script src="http://www.w3c-test.org/resources/testharnessreport.js"></script>
+</head>
+<div id="log"></div>
+<script src="resources/pass.js"></script>
+<script>
+test(function() {assert_true(false)}, 'Inline scripts run (1 of 3)');
+</script>
+<iframe style="display:none" src="javascript:parent.test(function() {parent.assert_true(false)}, 'JavaScript URLs run (2 of 3)');"></iframe>
+<img style="display:none"
+     onerror="test(function() {assert_true(false)}, 'Inline event handlers run (3 of 3)')"
+     src="about:blank">
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/testRunner/checkManifests.py	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,46 @@
+# Copyright (C) 2011-2012 Ms2ger
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy of
+# this software and associated documentation files (the "Software"), to deal in
+# the Software without restriction, including without limitation the rights to
+# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+# of the Software, and to permit persons to whom the Software is furnished to do
+# so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+import os, sys
+import parseManifest
+
+def getDirsAndFiles(root):
+  files = ["MANIFEST"]
+  dirs, autotests, reftests, othertests, supportfiles = parseManifest.parseManifestFile(root + "/MANIFEST")
+  files.extend(autotests)
+  for r in reftests:
+    files.extend([r[1], r[2]])
+  files.extend(othertests)
+  files.extend(supportfiles)
+  return set(dirs), set(files)
+
+def checkDir(path):
+  for root, dirs, files in os.walk(path):
+    print "Checking " + root
+    mdirs, mfiles = getDirsAndFiles(root)
+    for real in dirs:
+      if not real in mdirs:
+        raise Exception(real + " not listed.")
+    for real in files:
+      if not real in mfiles:
+        raise Exception(real + " not listed.")
+
+if __name__ == "__main__":
+  checkDir(sys.argv[1])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/testRunner/index.html	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html lang=en>
+<meta charset=UTF-8>
+<title>Web tests</title>
+<link rel=stylesheet href=runner.css>
+<script src=runner.js></script>
+<p><button value=/webappsec/tests/cors/submitted/cors1.0/>Run CORS 1.0 tests</button>
+<button value=/webappsec/tests/cors/submitted/opera/js/>Run CORS Opera tests</button>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/testRunner/manifests.txt	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,10 @@
+This code relies on the existence of MANIFEST files to list the tests within
+a directory.  These files consist of LF-separated lines, each of which falls
+in one of categories:
+
+* Directory: "dir foo"
+* Support files: "support foo.html"
+* Reftests: "foo.html == foo-ref.html == foo-ref2.html != foo-notref.html"
+* Automated tests (testharness.js): "foo.html"
+* Manual tests: "manual foo.html"
+* HTML parser data files: "parser foo.dat"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/testRunner/parseManifest.py	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,64 @@
+# Copyright (C) 2011-2012 Ms2ger
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy of
+# this software and associated documentation files (the "Software"), to deal in
+# the Software without restriction, including without limitation the rights to
+# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+# of the Software, and to permit persons to whom the Software is furnished to do
+# so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+def parseManifest(fd):
+  def parseReftestLine(chunks):
+    assert len(chunks) % 2 == 0
+    reftests = []
+    for i in range(2, len(chunks), 2):
+      if not chunks[i] in ["==", "!="]:
+        raise Exception("Misformatted reftest line " + line)
+      reftests.append([chunks[i], chunks[1], chunks[i + 1]])
+    return reftests
+
+  dirs = []
+  autotests = []
+  reftests = []
+  othertests = []
+  supportfiles = []
+  for fullline in fd:
+    line = fullline.strip()
+    if not line:
+      continue
+
+    chunks = line.split(" ")
+
+    if chunks[0] == "MANIFEST":
+      raise Exception("MANIFEST listed on line " + line)
+
+    if chunks[0] == "dir" or (chunks[0] == "support" and chunks[1] == "dir"):
+      dirs.append(chunks[1]);
+    elif chunks[0] == "ref":
+      if len(chunks) % 2:
+        raise Exception("Missing chunk in line " + line)
+      reftests.extend(parseReftestLine(chunks))
+    elif chunks[0] == "support":
+      supportfiles.append(chunks[1])
+    elif chunks[0] in ["manual", "parser"]:
+      othertests.append(chunks[1])
+    else: # automated
+      autotests.append(chunks[0])
+  return dirs, autotests, reftests, othertests, supportfiles
+
+def parseManifestFile(path):
+  fp = open(path)
+  dirs, autotests, reftests, othertests, supportfiles = parseManifest(fp)
+  fp.close()
+  return dirs, autotests, reftests, othertests, supportfiles
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/testRunner/reftest.html	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,91 @@
+<!doctype html>
+<title>Reftest harness</title>
+<style>
+iframe { width: 95%; height: 20em; }
+#test { border-color: blue; }
+#ref { border-color: green; }
+</style>
+<h1>Reftests</h1>
+<script>
+"use strict";
+function report(aResult, aMessage) {
+  pass &= aResult
+  var res = { status: +!aResult,
+              nodes: aResult ? [] : [document.createTextNode(aMessage)] }
+  results.push(res)
+  parent.result_callback(res)
+}
+function nextTest() {
+  if (!tests.length) {
+    parent.completion_callback(results, { status: +!pass })
+    return;
+  }
+  var test = tests.shift()
+  msgs.textContent = "These pages should " +
+                     (test[0] === "==" ? "match" : "not match") +
+                     "."
+  iframetest.src = path + test[1]
+  iframeref.src = path + test[2]
+}
+var pass = true
+var results = []
+var t = JSON.parse(decodeURIComponent(location.search.substring(1))), path = t[0], tests = t[1]
+var msgs = document.body.appendChild(document.createElement("p"))
+var p = document.body.appendChild(document.createElement("p"));
+p.textContent = "Look at the "
+var tButton = document.createElement("button")
+tButton.textContent = "Test"
+tButton.disabled = true
+tButton.onclick = function() {
+  tButton.disabled = true
+  rButton.disabled = false
+  iframetest.style.display = "inline"
+  iframeref.style.display = "none"
+}
+p.appendChild(tButton);
+p.appendChild(document.createTextNode(" "));
+var rButton = document.createElement("button")
+rButton.textContent = "Reference"
+rButton.onclick = function() {
+  rButton.disabled = true
+  tButton.disabled = false
+  iframetest.style.display = "none"
+  iframeref.style.display = "inline"
+}
+p.appendChild(rButton);
+
+var iframetest = document.body.appendChild(document.createElement("p"))
+                              .appendChild(document.createElement("iframe"))
+iframetest.id = "test"
+iframetest.style.display = "inline"
+var iframeref = document.body.lastChild
+                             .appendChild(document.createElement("iframe"))
+iframeref.id = "ref"
+iframeref.style.display = "none"
+
+p = document.body.appendChild(document.createElement("p"));
+p.textContent = "This test has: "
+var button = document.createElement("button")
+button.textContent = "Passed"
+button.onclick = function() {
+  report(true, "Tester clicked \"Pass\"");
+  nextTest()
+}
+p.appendChild(button);
+p.appendChild(document.createTextNode(" "));
+button = document.createElement("button")
+button.textContent = "Failed"
+button.onclick = function() {
+  report(false, "Tester clicked \"Fail\"");
+  nextTest()
+}
+p.appendChild(button);
+p.appendChild(document.createTextNode(" "));
+button = document.createElement("button")
+button.textContent = "Skip"
+button.onclick = function() {
+  nextTest()
+}
+p.appendChild(button);
+nextTest()
+</script>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/testRunner/runner.css	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,81 @@
+@charset "UTF-8";
+html { margin: 0 8px; }
+body { margin: 0; }
+html.done { border: 2px solid limegreen; margin: 3px; padding: 3px; }
+
+html:not(.done) { height: 100%; }
+html:not(.done) body { height: 100%; }
+
+header { display: block; font-weight: bold; }
+html.done header { font-size: 1.5em; margin: 0 0 .66em; }
+html.done header p { height: 5em; margin: 0; }
+
+html:not(.done) header { border: thin solid; height: 1.5em;
+                         -moz-box-sizing: border-box;
+                         -webkit-box-sizing: border-box;
+                         box-sizing: border-box; }
+html:not(.done) header p { height: 100%; width: 15em; margin: 0; float: right; }
+
+header meter { display: block; height: 100%; width: 100%; }
+header dl, header dt, header dd { margin: 0; padding: 0; }
+header dt, header dd { display: inline; }
+header dt:after { content: ": "; }
+html.done header dd:after { content: "\a"; white-space: pre-line; }
+html:not(.done) header dd:after { content: "; "; }
+html:not(.done) header dd:last-child:after { content: "."; }
+html:not(.done) header dl { line-height: 1.5; }
+
+html:not(.done) #wrapper { height: 100%; margin-top: -1.5em; padding-top: 1.5em;
+                           -moz-box-sizing: border-box;
+                           -webkit-box-sizing: border-box;
+                           box-sizing: border-box; }
+
+html:not(.done) #results { width: 15em; height: 100%; float:left;
+                           overflow-x: hidden; overflow-y: scroll; }
+
+section { display: block; border: thin solid black; padding: 0.5em 0; }
+section h1 { margin: 0; font-size: 1em; }
+html.done section h1 { text-align: center; }
+section ol { padding: 0; margin: 0; list-style-position: inside; }
+html.done section ol { -moz-column-count: 3; -webkit-column-count: 3; column-count: 3; }
+section li { padding: 0.1em 0.5em; }
+section li.pass:nth-child(odd)  { background: #E5FFE5; }
+section li.pass:nth-child(even) { background: #DEF8DE; }
+section li.fail:nth-child(odd)  { background: #FFE5E5; }
+section li.fail:nth-child(even) { background: #F8DEDE; }
+section p { margin: 0; }
+html:not(.done) section { border-top: none; }
+html.done section + section { border-top: none; }
+
+html:not(.done) #iframewrapper { margin: 0 0 0 15em; padding: 2px 2px 3px; height: 100%;
+                                 -moz-box-sizing: border-box;
+                                 -webkit-box-sizing: border-box;
+                                 box-sizing: border-box; }
+html:not(.done) iframe { width: 100%; height: 100%; border-width: 2px; margin: -2px; }
+
+html:not(.done) body.manual #iframewrapper { height: 90%; }
+html:not(.done) body.manual #manualUI { display: block; margin: 0 0 0 15em;
+                                        height: 10%; }
+#manualUI { display: none; }
+
+body > p { text-align: center; }
+body > p > textarea { width: 90%; height: 20em; }
+
+meter::-webkit-meter-horizontal-bar {
+  background: -webkit-gradient(linear, 0% 0%, 0% 100%,
+                               from(#F77),
+                               color-stop(0.2, #FCC),
+                               color-stop(0.45, #D44),
+                               color-stop(0.55, #D44),
+                               to(#F77));
+}
+meter::-webkit-meter-horizontal-optimum-value,
+meter::-webkit-meter-horizontal-suboptimal-value,
+meter::-webkit-meter-horizontal-even-less-good-value {
+  background: -webkit-gradient(linear, 0% 0%, 0% 100%,
+                               from(#AD7),
+                               color-stop(0.2, #CEA),
+                               color-stop(0.45, #7A3),
+                               color-stop(0.55, #7A3),
+                               to(#AD7));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/testRunner/runner.js	Sun Sep 23 18:51:05 2012 -0700
@@ -0,0 +1,530 @@
+"use strict";
+var runner;
+
+function Runner(aPath) {
+  this.mStartTime = (new Date()).getTime();
+  this.mPath = aPath;
+  this.mTimeouts = 0;
+  this.mToBeProcessed = 1;
+  this.mPasses = 0;
+  this.mFails = 0;
+  this.mIframe = document.createElement("iframe");
+  this.mMeter = null;
+  this.mScoreNode = null
+  this.mPassNode = null
+  this.mFailNode = null
+  this.mWrapper = null;
+  this.mSectionWrapper = null;
+  this.mSection = null;
+  this.mOl = null;
+  this.mTests = [];
+  this.mTestCount = -1;
+  this.mSkipManual = false;
+};
+Runner.prototype = {
+  "sTimeout": 10000, //ms
+
+  "sOrigTitle": document.title,
+
+  "sSupportsMeter": "value" in document.createElement("meter"),
+
+  "currentTest": function Runner_currentTest() {
+    return this.mTests[this.mTestCount];
+  },
+
+  "start": function Runner_start() {
+    var options = parseOptions();
+    this.mSkipManual = "skipmanual" in options && options["skipmanual"] === "1";
+
+    document.title = this.sOrigTitle;
+    document.documentElement.className = "";
+
+    clearBody();
+
+    var header = document.body.appendChild(document.createElement("header"));
+    this.mMeter = header.appendChild(document.createElement("p"))
+                        .appendChild(document.createElement("meter"));
+
+    if (!this.sSupportsMeter) {
+      this.mMeter.parentNode.style.background = "red";
+      this.mMeter.style.background = "limegreen";
+      this.mMeter.style.width = "67%";
+    }
+
+    var dl = header.appendChild(document.createElement("dl"));
+    dl.appendChild(document.createElement("dt"))
+      .appendChild(document.createTextNode("Score"));
+    this.mScoreNode = dl.appendChild(document.createElement("dd"))
+                        .appendChild(document.createTextNode("0%"));
+    dl.appendChild(document.createElement("dt"))
+      .appendChild(document.createTextNode("Pass"));
+    this.mPassNode = dl.appendChild(document.createElement("dd"))
+                       .appendChild(document.createTextNode("0"));
+    dl.appendChild(document.createElement("dt"))
+      .appendChild(document.createTextNode("Fail"));
+    this.mFailNode = dl.appendChild(document.createElement("dd"))
+                       .appendChild(document.createTextNode("0"));
+
+    this.mWrapper =
+      document.body.appendChild(document.createElement("div"));
+    this.mWrapper.id = "wrapper";
+
+    this.mSectionWrapper =
+      this.mWrapper.appendChild(document.createElement("div"));
+    this.mSectionWrapper.id = "results";
+
+    var p = this.mWrapper.appendChild(document.createElement("p"));
+    p.id = "iframewrapper";
+    p.appendChild(this.mIframe);
+
+    if (!this.mSkipManual) {
+      p = this.mWrapper.appendChild(document.createElement("p"));
+      p.id = "manualUI";
+      p.textContent = "This test has: "
+
+      var button = document.createElement("button")
+      button.textContent = "Passed"
+      button.onclick = function() {
+        report(true, "Tester clicked \"Pass\"");
+        runner.currentTest().passes = 1;
+        runner.finishTest();
+      }
+      p.appendChild(button);
+      p.appendChild(document.createTextNode(" "));
+      button = document.createElement("button")
+      button.textContent = "Failed"
+      button.onclick = function() {
+        report(false, "Tester clicked \"Fail\"");
+        runner.currentTest().fails = 1;
+        runner.finishTest();
+      }
+      p.appendChild(button);
+      p.appendChild(document.createTextNode(" "));
+      button = document.createElement("button")
+      button.textContent = "Skip"
+      button.onclick = function() {
+        runner.finishTest();
+      }
+      p.appendChild(button);
+    }
+
+    var xhr = new XMLHttpRequest(), self = this;
+    xhr.onreadystatechange = function onrsc() {
+      if (this.readyState !== 4 || !(this.status === 200 || this.status === 0))
+        return;
+      self.process(this.responseText, "");
+    };
+    xhr.open("GET", this.mPath + "MANIFEST");
+    xhr.send(null);//Fx 3
+  },
+
+  "process": function Runner_process(aManifest, aPath) {
+    --this.mToBeProcessed;
+    var dirs = this.parseManifest(aManifest.split("\n"), aPath);
+    for (var k = 0, kl = dirs.length; k < kl; ++k) {
+      var dir = dirs[k] + "/";
+      ++this.mToBeProcessed;
+      var xhr = new XMLHttpRequest(), self = this;
+      xhr.dataDir = dir;
+      xhr.onreadystatechange = function() {
+        if (this.readyState !== 4 || !(this.status === 200 || this.status === 0))
+          return;
+
+        self.process(this.responseText, this.dataDir);
+      };
+      xhr.open("GET", this.mPath + dir + "MANIFEST");
+      xhr.send(null);//Fx 3
+    }
+
+    if (!this.mToBeProcessed) {
+      this.runNextTest()
+    }
+  },
+
+  "parseManifest": function Runner_parseManifest(aLines, aPath) {
+    var dirs = [];
+    for (var i = 0, il = aLines.length; i < il; ++i) {
+      if (!aLines[i]) {
+        continue;
+      }
+
+      var chunks = aLines[i].split(" ");
+
+      switch (chunks[0]) {
+      case "support":
+      case "list":
+        break;
+
+      case "dir":
+        if (chunks[1]) {
+          dirs.push(aPath + chunks[1]);
+        }
+        break;
+
+      case "manual":
+        if (chunks[1]) {
+          this.mTests.push({ url: aPath + chunks[1], passes: 0, fails: 0, type: "manual" });
+        }
+        break;
+
+      case "ref":
+        if (chunks.length % 2) {
+          break;
+        }
+        var reftests = [];
+        for (var j = 2, jl = chunks.length; j < jl; j += 2) {
+          reftests.push([chunks[j], aPath + chunks[1], aPath + chunks[j + 1]]);
+        }
+        this.mTests.push({ type: "reftest", url: aPath + chunks[1], passes: 0, fails: 0, tests: reftests })
+        break;
+
+      default:
+        if (chunks.length > 1) {
+          break;
+        }
+        this.mTests.push({ url: aPath + chunks[0], passes: 0, fails: 0, type: "automated" });
+      }
+    }
+    return dirs;
+  },
+
+  /* ***** Running the test suite ***** */
+  "_report": function Runner__report(aPass, aMessageNodes) {
+    var li = document.createElement("li");
+    li.className = aPass ? "pass" : "fail";
+    li.appendChild(document.createTextNode(aPass ? "Pass" : "Fail: "));
+    for (var i = 0, il = aMessageNodes.length; i < il; ++i) {
+      li.appendChild(aMessageNodes[i]);
+    }
+    this.mOl.appendChild(li);
+  },
+
+  "fail": function Runner_fail(aMsg) {
+    ++this.mFails;
+    this._report(false, [document.createTextNode(aMsg)]);
+  },
+
+  "timedOut": function Runner_timedOut() {
+    this.fail("Timed out.");
+    ++this.mTimeouts;
+    clearTimeout(this.currentTest().timeout);
+    this.runNextTest();
+  },
+
+  "updateResults": function Runner_updateResults() {
+    if (!this.mPasses && !this.mFails)
+      return;
+    var score = this.mPasses / (this.mPasses + this.mFails);
+    var scorestr = (100 * score).toFixed(2) + "%";
+    if (this.sSupportsMeter)
+      this.mMeter.value = score;
+    else
+      this.mMeter.style.width = scorestr;
+    this.mScoreNode.data = scorestr;
+    this.mPassNode.data = this.mPasses;
+    this.mFailNode.data = this.mFails;
+
+    var metadata = this.mIframe && this.mIframe.contentWindow &&
+      this.mIframe.contentWindow.Test && this.mIframe.contentWindow.Test.meta;
+    if (!metadata)
+      return;
+
+    var p = this.mSection.appendChild(document.createElement("p"));
+
+    this.appendList("Created by", metadata.authors, p);
+    this.appendList("Reviewed by", metadata.reviewers, p);
+    this.appendList("Help:", metadata.helps, p);
+
+    if (metadata.assert) {
+      p.appendChild(document.createTextNode("Asserting that " + metadata.assert +
+                                            "."));
+    }
+  },
+
+  "createLink": function Runner_createLink(aLink) {
+    var a = document.createElement("a");
+    a.href = aLink.href;
+    a.appendChild(document.createTextNode(aLink.text));
+    return a;
+  },
+
+  "appendList": function Runner_appendList(aLabel, aList, aEl) {
+    if (!aList.length)
+      return;
+
+    aEl.appendChild(document.createTextNode(aLabel + " "));
+    for (var i = 0, il = aList.length; i < il; ++i) {
+      if (i)
+        aEl.appendChild(document.createTextNode(", "));
+      aEl.appendChild(this.createLink(aList[i]));
+    }
+    aEl.appendChild(document.createTextNode(". "));
+  },
+
+  "addTitle": function Runner_addTitle() {
+    this.mSection = document.createElement("section");
+    this.mSectionWrapper.appendChild(this.mSection);
+
+    var a = document.createElement("a");
+    a.appendChild(document.createTextNode(this.currentTest().url));
+    a.href = this.mPath + this.currentTest().url;
+
+    var h1 = document.createElement("h1");
+    h1.appendChild(a);
+    this.mSection.appendChild(h1);
+
+    this.mOl = this.mSection.appendChild(document.createElement("ol"));
+  },
+
+  "hideManualUI": function() {
+    document.body.className = ""
+  },
+
+  "showManualUI": function() {
+    document.body.className = "manual"
+  },
+
+  "runNextTest": function Runner_runNextTest() {
+    ++this.mTestCount;
+    if (!this.currentTest()) {
+      this.finish();
+      return;
+    }
+
+    this.addTitle();
+
+    switch (this.currentTest().type) {
+    case "automated":
+      if (!this.mSkipManual) {
+        this.hideManualUI()
+      }
+      this.currentTest().timeout =
+        setTimeout(function() { runner.timedOut() }, this.sTimeout);
+      this.mIframe.src = this.mPath + this.currentTest().url;
+      break;
+
+    case "reftest":
+      if (!this.mSkipManual) {
+        this.hideManualUI()
+      }
+      this.mIframe.src = "reftest.html?" +
+        JSON.stringify([this.mPath, this.currentTest().tests]);
+      break;
+
+    case "manual":
+      if (!this.mSkipManual) {
+        this.showManualUI()
+        this.mIframe.src = this.mPath + this.currentTest().url;
+      } else {
+        this.finishTest();
+      }
+      break;
+
+    default:
+      throw "Unrecognized test type";
+    }
+  },
+
+  "finishTest": function Report_finishTest() {
+    this.mPasses += this.currentTest().passes;
+    this.mFails += this.currentTest().fails;
+    this.updateResults();
+    clearTimeout(this.currentTest().timeout);
+    this.runNextTest();
+  },
+
+  /* ***** Finishing up ***** */
+  "getXMLReport": function Runner_getXMLReport() {
+    var container = document.createElement("div");
+    var tests = container
+      .appendChild(document.createElementNS(null, "testresults"))
+        .appendChild(document.createTextNode("\n "))
+      .parentNode
+        .appendChild(document.createElementNS(null, "browser"))
+          .appendChild(document.createTextNode("\n  "))
+        .parentNode
+          .appendChild(document.createElementNS(null, "ua"))
+            .appendChild(document.createTextNode(navigator.userAgent))
+        .parentNode.parentNode
+          .appendChild(document.createTextNode("\n  "))
+        .parentNode
+          .appendChild(document.createElementNS(null, "browsername"))
+            .appendChild(document.createTextNode("REPLACE WITH BROWSERNAME BEFORE PUSHING TO HG"))
+        .parentNode.parentNode
+          .appendChild(document.createTextNode("\n  "))
+        .parentNode
+          .appendChild(document.createElementNS(null, "dateran"))
+            .appendChild(document.createTextNode(Date()))
+        .parentNode.parentNode
+          .appendChild(document.createTextNode("\n "))
+      .parentNode.parentNode
+        .appendChild(document.createTextNode("\n "))
+      .parentNode
+        .appendChild(document.createElementNS(null, "tests"));
+
+    for (var i = 0, il = this.mTests.length; i < il; ++i) {
+      if (this.mTests[i].passes || this.mTests[i].fails) {
+        tests.appendChild(document.createTextNode("\n  "));
+        tests
+          .appendChild(document.createElementNS(null, "test"))
+            .appendChild(document.createTextNode("\n   "))
+          .parentNode
+            .appendChild(document.createElementNS(null, "uri"))
+              .appendChild(document.createTextNode(this.mTests[i].url))
+          .parentNode.parentNode
+            .appendChild(document.createTextNode("\n   "))
+          .parentNode
+            .appendChild(document.createElementNS(null, "result"))
+              .appendChild(document.createTextNode(
+                !this.mTests[i].fails ? "Pass" : "Fail"))
+          .parentNode.parentNode
+            .appendChild(document.createTextNode("\n  "));
+      }
+    }
+    container
+      .firstChild
+        .lastChild
+          .appendChild(document.createTextNode("\n "))
+      .parentNode.parentNode
+        .appendChild(document.createTextNode("\n"));
+    return container.innerHTML;
+  },
+
+  "finish": function Runner_finish() {
+    this.mWrapper.removeChild(this.mIframe.parentNode);
+    this.updateResults();
+    var time = (((new Date()).getTime() - this.mStartTime) / 1000).toFixed(0);
+    document.body.appendChild(document.createElement("p"))
+                 .appendChild(document.createTextNode("Application ran for "
+                                                      + time + " seconds."));
+    document.body.appendChild(document.createElement("p"))
+                 .appendChild(document.createTextNode(this.mTimeouts + " timeouts."));
+    var button = document.body.appendChild(document.createElement("p"))
+                              .appendChild(document.createElement("button"));
+    button.appendChild(document.createTextNode("Run again"));
+    button.value = this.mPath;
+    button.onclick = startRunning;
+    this.mMeter.onclick = function(e) {
+      if (e.altKey) {
+        document.open();
+        document.write("<pre>");
+        document.writeln("  &lt;dt>" + navigator.userAgent);
+        document.writeln("  &lt;dd>Pass " + this.mPasses);
+        document.writeln("  &lt;dd>Fail " + this.mFails);
+        document.writeln("  &lt;dd>Score "
+                         + (100 * this.mPasses / (this.mPasses + this.mFails)).toFixed(2) + "%");
+        document.write("</pre>");
+        document.close();
+      }
+    };
+    document.body.appendChild(document.createElement("p"))
+                 .appendChild(document.createElement("textarea"))
+                 .appendChild(document.createTextNode(this.getXMLReport()));
+    document.title = "Done \u2013 " + document.title;
+    document.documentElement.className = "done";
+  }
+};
+
+
+/* ***** Preparation ***** */
+function parseOptions() {
+  var optionstrings = location.search.substring(1).split("&");
+  var options = {};
+  for (var i = 0, il = optionstrings.length; i < il; ++i) {
+    var opt = optionstrings[i];
+    options[opt.substring(0, opt.indexOf("="))] =
+      opt.substring(opt.indexOf("=") + 1);
+  }
+  return options;
+}
+
+function setup() {
+  var options = parseOptions();
+  if (options["autorun"] === "1") {
+    runner = new Runner(options["path"] || "../html5/");
+    runner.start();
+    return;
+  }
+
+  if (options["path"]) {
+    clearBody();
+    var button = document.body.appendChild(document.createElement("p"))
+                              .appendChild(document.createElement("button"));
+    button.appendChild(document.createTextNode("Run tests"));
+    button.value = options["path"];
+    button.onclick = startRunning;
+    return;
+  }
+    
+  var buttons = document.getElementsByTagName("button");
+  for (var i = 0, il = buttons.length; i < il; ++i) {
+    buttons[i].onclick = startRunning;
+  }
+}
+
+function startRunning() {
+  runner = new Runner(this.value);
+  runner.start();
+}
+
+
+function report(aPass, aMessage) {
+  var nodes = [];
+  if (!aPass)
+    nodes.push(document.createTextNode(aMessage));
+  runner._report(aPass, nodes);
+}
+
+function result_callback(aTest) {
+  if (runner.currentTest().type === "manual" && aTest.status === aTest.TIMEOUT) {
+    return;
+  }
+  var nodes = [];
+  if (aTest.message) {
+    if (typeof aTest.message === "string") {
+      nodes = [document.createTextNode(aTest.message)];
+    } else {
+      var rendered = runner.mIframe.contentWindow.template.render(aTest.message);
+      if (rendered.length) {
+        nodes = nodes.concat(rendered);
+      } else {
+        nodes.push(rendered);
+      }
+    }
+  } else if (aTest.nodes) {
+    nodes = aTest.nodes;
+  }
+  runner._report(!aTest.status, nodes);
+  !aTest.status ? runner.currentTest().passes++ : runner.currentTest().fails++;
+}
+
+function separate() {
+}
+
+
+function finishTest() {
+  runner.currentTest().passes = runner.mIframe.contentWindow.Test.results.passes;
+  runner.currentTest().fails = runner.mIframe.contentWindow.Test.results.fails;
+  runner.finishTest();
+}
+
+function completion_callback(aTests, aStatus) {
+  if (runner.currentTest().type === "manual") {
+    for (var i = 0, il = aTests.length; i < il; ++i) {
+      var test = aTests[i];
+      if (test.status == test.TIMEOUT) {
+        return;
+      }
+    }
+  }
+  runner.finishTest();
+}
+
+function clearBody() {
+  var i = document.body.childNodes.length;
+  while (i--) {
+    document.body.removeChild(document.body.childNodes[i]);
+  }
+}
+
+window.onload = setup;