<html> 
<head> 
<title>Hash Change with an Open XHR should not stop database transactions</title>

<script type="text/javascript"> 
 
var DB_UPDATE_INTERVAL = 100;
var SEND_XHR_INTERVAL = 100;
var BACK_INTERVAL = 100;
var CREATE_HEALTH_TABLE = 'CREATE TABLE IF NOT EXISTS health (key VARCHAR(16) PRIMARY KEY);';
var UPDATE_DATA = 'REPLACE INTO health VALUES("health-check-key");';
 
var db = window.openDatabase('bug25710', '1.0', 'LayoutTest for bug 25710', 102400);
var backIterations;
var msgDiv;
var xhrFctIntervalId;
var backFctIntervalId;
var successCheckIntervalId;
var dbFctIntervalId;
var successes;
var databaseUpdates;
var stoppedIntervals;
 
function log(msg)
{
    var newMsg = document.createElement('div');
    newMsg.innerText = msg;
    msgDiv.appendChild(newMsg);
}

function stopIntervals()
{
    stoppedIntervals = true;
    window.clearInterval(dbFctIntervalId);
    window.clearInterval(xhrFctIntervalId);
    window.clearInterval(backFctIntervalId);
}

function stopTest(message)
{
    if (!stoppedIntervals)
        stopIntervals();

    log(message);

    if (window.layoutTestController)
        layoutTestController.notifyDone();
}
    
function updateDatabase()
{
    databaseUpdates++;  
    db.transaction(function(transaction) {
        transaction.executeSql(UPDATE_DATA, [], function() {}, errorHandler);
    }, errorHandler, function() {
        successes++;
    });
}

function checkForSuccess()
{
    if (successes == databaseUpdates) {
        stopTest('Test Complete, SUCCESS');
        window.clearInterval(successCheckIntervalId);
    }
}
 
function errorHandler(tx, error)
{
    log('DB error, code: ' + error.code + ', msg: ' + error.message);
    stopTest('Test Complete, FAILED');
}
 
function sendXhr()
{
    xhr = new XMLHttpRequest();
    xhr.open('GET', location.href, true);
    xhr.send('');
}
 
function invokeBack()
{
    backIterations--;
    if (backIterations) {
        history.back();
    } else {
        stopIntervals();
        // Allow a little time for all the database transactions to complete now we've stopped making them.
        successCheckIntervalId = window.setInterval(checkForSuccess, 250);
        // If we don't finish before this time, then we consider the test failed.
        window.setTimeout(function() { stopTest('Timed out waiting for transactions to complete. FAILED'); }, 20000);
        
    }
}

function runTest()
{
    if (window.layoutTestController) {
        layoutTestController.dumpAsText();
        layoutTestController.waitUntilDone();
    }
  
    msgDiv = document.getElementById('msgs');

    msgDiv.innerHTML = '';
    backIterations = 10;
    consecutiveFailures = 0;
    successes = 0;
    databaseUpdates = 0;
    stoppedIntervals = false;

    // Create some hashes so we can call history.back().
    log('Changing the hash to create history entries.');
    for (var i = 0; i < backIterations; i++) {
        location.hash = i;
    }

    // Init the database.
    db.transaction(function(transaction) {
        transaction.executeSql(CREATE_HEALTH_TABLE, [], function() {}, errorHandler);
    }, errorHandler, function() {
        // Give a little for the database to 'warm up' before making xhr requests
        // and calling history.back().
        window.setTimeout(function() {
            log('Db is warmed up');

            // NOTE: If we don't make any xhr requests, then the test
            // successfully passes (comment this line out).
            xhrFctIntervalId = window.setInterval(sendXhr, SEND_XHR_INTERVAL);
            backFctIntervalId = window.setInterval(invokeBack, BACK_INTERVAL);
            dbFctIntervalId = window.setInterval(updateDatabase, DB_UPDATE_INTERVAL);
        }, 500);
    });
}
</script> 
</head> 
<body onload="runTest()"> 
<div id="msgs"></div> 
</body> 
</html>