<html>
<head>
<title>Test XmlHttpRequest response encoding handling</title>
<meta http-equiv="content-type" content="text/html;charset=koi8-r">
<body>
<p>Test for <a href="http://bugs.webkit.org/show_bug.cgi?id=5744">bug 5744</a>
- correctly determine the encoding of XMLHttpRequest responses.</p>
<script>

    if (window.layoutTestController)
        layoutTestController.dumpAsText();

    var console_messages = document.createElement("ol");
    document.body.appendChild(console_messages);
    
    var asyncStep = 1;
    
    function log(message)
    {
        var item = document.createElement("li");
        item.appendChild(document.createTextNode(message));
        console_messages.appendChild(item);
    }
    
    function get(url, async)
    {
        if (window.XMLHttpRequest) {
            req = new XMLHttpRequest();
        } else {
            try {
                req = new ActiveXObject("Msxml2.XMLHTTP");
            } catch (ex) {
                req = new ActiveXObject("Microsoft.XMLHTTP");
            }
        }
        
        if (async)
            req.onreadystatechange = processStateChange;
        
        req.open('GET', url, async);
        req.send(null);

        if (!async && req.status != 200)
            throw ("HTTP request failed, status: " + req.status);
        
        return req;
    }

    function getWithOverride(url, contentType, async)
    {
        if (window.XMLHttpRequest) {
            req = new XMLHttpRequest();
        } else {
            try {
                req = new ActiveXObject("Msxml2.XMLHTTP");
            } catch (ex) {
                req = new ActiveXObject("Microsoft.XMLHTTP");
            }
        }

        if (async)
            req.onreadystatechange = processStateChange;

        req.open('GET', url, async);
        req.overrideMimeType(contentType);
        req.send(null);

        if (!async && req.status != 200)
            throw ("HTTP request failed, status: " + req.status);
        
        return req;
    }
    
    function processStateChange(){
      if (req.readyState == 4){
        if (req.status == 200){
           if (asyncStep == 1) {
             asyncStep = 2;
             log("Async: Plain text, UTF-8 as default: " + req.responseText);
             get('resources/reply2.txt', true);
           } else if (asyncStep == 2) {
             asyncStep = 3;
             log("Async: Plain text, windows-1251 specified in HTTP headers: " + req.responseText);
             getWithOverride('resources/reply3.txt', 'text/plain; charset=windows-1251', true);
           } else if (asyncStep == 3) {
             asyncStep = 4;
             log("Async: Plain text, windows-1251 specified in overrideMimeType: " + req.responseText);
             getWithOverride('resources/reply4.txt', 'text/plain; charset=windows-1251', true);
           } else if (asyncStep == 4) {
             asyncStep = 5;
             log("Async: Plain text, koi8-r specified in HTTP headers, but overridden by windows-1251 in overrideMimeType: " + req.responseText);
             get('resources/reply4.xml', true);
           } else if (asyncStep == 5) {
             asyncStep = 6;
             log("Async: XML, UTF-8 as default: " + req.responseXML.getElementsByTagName('node')[0].childNodes[0].nodeValue + ". responseText: " + req.responseText);
             get('resources/reply.xml', true);
           } else if (asyncStep == 6) {
             asyncStep = 7;
             log("Async: XML, windows-1251 specified in XML declaration: " + req.responseXML.getElementsByTagName('node')[0].childNodes[0].nodeValue + ". responseText: " + req.responseText);
             get('resources/reply2.xml', true);
           } else if (asyncStep == 7) {
             asyncStep = 8;
             log("Async: XML, koi8-r specified in XML declaration, but overridden by windows-1251 in HTTP headers: " + req.responseXML.getElementsByTagName('node')[0].childNodes[0].nodeValue + ". responseText: " + req.responseText);
             getWithOverride('resources/reply3.xml', 'text/xml; charset=windows-1251', true);
           } else if (asyncStep == 8) {
             asyncStep = 9;
             log("Async: XML, koi8-r specified in XML declaration, but overridden by windows-1251 in overrideMimeType: " + 
                 (req.responseXML ? req.responseXML.getElementsByTagName('node')[0].childNodes[0].nodeValue  : "<No responseXML>") + ". responseText: " + req.responseText);
             get('resources/reply5.txt', true);
           } else if (asyncStep == 9) {
             asyncStep = 10;
             log("Async: XML transferred as text/plain, UTF-8 as default (ignore XML text declaration): " + req.responseText);
             get('resources/1251.html', true);
           } else if (asyncStep == 10) {
             log("Async: HTML, charset determined by a META: " + req.responseText.replace(/\s/g, "").replace(/.*<body>(.*)<\/body>.*/, "$1"));
           }
        } else {
           log("Error loading URL: status " + req.status);
        }
      }
    }

    // sync code
    
    // 1
    try {
        req = get('resources/reply.txt', false);
        log("Plain text, UTF-8 as default: " + req.responseText);
    } catch (ex) {
        log("Exception: " + ex.description);
    }

    // 2
    try {
        req = get('resources/reply2.txt', false);
        log("Plain text, windows-1251 specified in HTTP headers: " + req.responseText);
    } catch (ex) {
        log("Exception: " + ex.description);
    }

    // 3
    try {
        req = getWithOverride('resources/reply3.txt', 'text/plain; charset=windows-1251', false);
        log("Plain text, windows-1251 specified in overrideMimeType: " + req.responseText);
    } catch (ex) {
        log("Exception: " + ex.description);
    }

    // 4
    try {
        req = getWithOverride('resources/reply4.txt', 'text/plain; charset=windows-1251', false);
        log("Plain text, koi8-r specified in HTTP headers, but overridden by windows-1251 in overrideMimeType: " + req.responseText);
    } catch (ex) {
        log("Exception: " + ex.description);
    }
        
    // 5
    try {
        req = get('resources/reply4.xml', false);
        log("XML, UTF-8 as default: " + req.responseXML.getElementsByTagName('node')[0].childNodes[0].nodeValue + ". responseText: " + req.responseText);
    } catch (ex) {
        log("Exception: " + ex.description);
    }
        
    // 6
    try {
        req = get('resources/reply.xml', false);
        log("XML, windows-1251 specified in XML declaration: " + req.responseXML.getElementsByTagName('node')[0].childNodes[0].nodeValue + ". responseText: " + req.responseText);
    } catch (ex) {
        log("Exception: " + ex.description);
    }
    
    // 7
    try {
        req = get('resources/reply2.xml', false);
        log("XML, koi8-r specified in XML declaration, but overridden by windows-1251 in HTTP headers: " + req.responseXML.getElementsByTagName('node')[0].childNodes[0].nodeValue + ". responseText: " + req.responseText);
    } catch (ex) {
        log("Exception: " + ex.description);
    }
        
    // 8
    try {
        req = getWithOverride('resources/reply3.xml', 'text/xml; charset=windows-1251', false);
        log("XML, koi8-r specified in XML declaration, but overridden by windows-1251 in overrideMimeType: " + req.responseXML.getElementsByTagName('node')[0].childNodes[0].nodeValue + ". responseText: " + req.responseText);
    } catch (ex) {
        log("Exception: " + ex.description);
    }
    
    // 9
    try {
        req =  get('resources/reply5.txt', false);
        log("XML transferred as text/plain, UTF-8 as default (ignore XML text declaration): " + req.responseText);
    } catch (ex) {
        log("Exception: " + ex.description);
    }
    
    // 10
    try {
        req =  get('resources/1251.html', false);
        log("HTML, charset determined by a META: " + req.responseText.replace(/\s/g, "").replace(/.*<body>(.*)<\/body>.*/, "$1"));
    } catch (ex) {
        log("Exception: " + ex.description);
    }

    // start async steps
    get('resources/reply.txt', true);
    
//    var console = document.createElement("p");
//    console.appendChild(console_messages);
//    document.body.appendChild(console);

</script>
</body>
</html>
