<button onclick="testSyncCookiesNoCredentials();">Start</button>
<pre id="console"></pre>
<script>
if (window.testRunner) {
    testRunner.dumpAsText();
    testRunner.waitUntilDone();
    testRunner.setCanOpenWindows();
    testRunner.setBlockThirdPartyCookies(false);
}

function log(message)
{
    var consoleDiv = document.getElementById('console');
    consoleDiv.appendChild(document.createTextNode(message + '\n'));
}

function resourceURL(resourceName)
{
    return "http://localhost:8000/xmlhttprequest/resources/" + resourceName;
}

function clearCookies()
{
    var xhr = new XMLHttpRequest;
    xhr.open("GET", resourceURL("cross-origin-set-cookies.php?clear=1"), false);
    xhr.withCredentials = true;
    xhr.send("");
}

function endTesting()
{
    clearCookies();
    if (window.testRunner)
        testRunner.notifyDone();
}

function checkForCookie()
{
    var xhr = new XMLHttpRequest;
    xhr.open("GET", resourceURL("cross-origin-check-cookies.php?cookie=WK-xhr-cookie-storage"), false);
    xhr.withCredentials = true;
    try {
        xhr.send();
        return xhr.responseText
    } catch (ex) {
        log("FAIL: Got an exception. " + ex);
    }
}

function testSyncCookiesNoCredentials()
{
    log("Cross-origin XMLHttpRequest (sync), testing that cookies are not set when not sending credentials.");

    clearCookies();

    var req = new XMLHttpRequest;
    req.open("GET", resourceURL("cross-origin-set-cookies.php"), false);
    req.withCredentials = false;
    req.send();
    log("PASS: Finished sync xhr.");

    var response = checkForCookie()
    log(!response.match(/WK\-xhr\-cookie\-storage: MySpecialValue/) ? "PASS: No cookies set." : ("FAIL: " + response));

    testAsyncCookiesNoCredentials();
}

function testAsyncCookiesNoCredentials()
{
    log("Cross-origin XMLHttpRequest (async), testing that cookies are not set when not sending credentials.");

    clearCookies();

    var req = new XMLHttpRequest;
    req.open("GET", resourceURL("cross-origin-set-cookies.php"), true);
    req.withCredentials = false;
    req.send();
    req.onerror = function() {
        log("FAIL: Async xhr to set cookies.");
        endTesting();
    }
    req.onload = function() {
        log("PASS: Finished async xhr.");
        var response = checkForCookie();
        log(!response.match(/WK\-xhr\-cookie\-storage: MySpecialValue/) ? "PASS: No cookies set." : ("FAIL: " + response));
        testSyncCookiesWithCredentials();
    }
}

function testSyncCookiesWithCredentials()
{
    log("Cross-origin XMLHttpRequest (sync), testing that cookies are set when sending credentials.");

    clearCookies();

    var req = new XMLHttpRequest;
    req.open("GET", resourceURL("cross-origin-set-cookies.php"), false);
    req.withCredentials = true;
    req.send();
    log("PASS: Finished sync xhr.");

    var response = checkForCookie();
    log(response.match(/WK\-xhr\-cookie\-storage: MySpecialValue/) ? "PASS: Cookie set." : "FAIL: no cookie set.");
    log("DONE");
    endTesting();
}

if (window.testRunner)
    testSyncCookiesNoCredentials();
</script>
