<html><head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<script type="text/javascript">
var defaultActions = {
  'keydown': true,
  'keypress': true,
  'keyup': true,
  'textInput': true,
};
var keyEventResult = [];
var focusedElement = "";
var lastFocusedElement = "";
var testStarted = false;
var expectedEventCount = 0;
var eventCount = 0;
var keyDownCount = 0;
var keyUpCount = 0;

function init() {
  document.addEventListener("keydown", handleEvent, false);
  document.addEventListener("keypress", handleEvent, false);
  document.addEventListener("keyup", handleEvent, false);
  document.addEventListener("textInput", handleEvent, false);
  window.addEventListener("blur", handleWindowBlur, false);
}

function log(text) {
  document.getElementById('log').innerHTML += text + '<br/>';
}

function setDefaultAction(type, value) {
  defaultActions[type] = value;
  document.getElementById(type).checked = !value;
  return defaultActions[type];
}

function startTest(count) {
  if (!testStarted) {
    clearResult();
    testStarted = true;
    expectedEventCount = count;
    log("Start test.");
    return true;
  }
  return false;
}

function finishTest() {
  testStarted = false;
  window.domAutomationController.send("FINISHED");
  log("Finish test.");
}

function handleEvent(e) {
  var prefixes = {
    'keydown': 'D',
    'keypress': 'P',
    'keyup': 'U',
    'textInput': 'T',
  };

  var evt = e || window.event;
  var result = prefixes[evt.type] + ' ';
  if (evt.type == 'textInput') {
    result += evt.data;
  } else {
    // On Linux, the keydown event of a modifier key doesn't have the
    // corresponding modifier attribute set, while the keyup event does have,
    // eg. pressing and releasing ctrl may generate a keydown event with
    // ctrlKey=false and a keyup event with ctrlKey=true.
    // But Windows and Mac have opposite behavior than Linux.
    // To make the C++ testing code simpler, if it's a modifier key event,
    // then ignores the corresponding modifier attribute by setting it to true.
    var keyId = evt.key;
    result += (evt.keyCode + ' ' + evt.charCode + ' ' +
        (keyId == 'Control' ? true : evt.ctrlKey) + ' ' +
        (keyId == 'Shift' ? true : evt.shiftKey) + ' ' +
        (keyId == 'Alt' ? true : evt.altKey) + ' ' +
        (keyId == 'Meta' ? true : evt.metaKey));
  }
  keyEventResult.push(result);
  log(result);

  if (testStarted) {
    ++eventCount;
    if (evt.type == "keydown") {
      ++keyDownCount;
    } else if (evt.type == "keyup") {
      ++keyUpCount;
      if (keyDownCount == keyUpCount || (eventCount >= expectedEventCount))
        finishTest();
    }
  }

  if (!defaultActions[evt.type]) {
    if (evt.preventDefault) evt.preventDefault();
    if (evt.stopPropagation) evt.stopPropagation();
  }
  return defaultActions[evt.type];
}

function handleWindowBlur() {
  if (testStarted)
    finishTest();
}

function clearResult() {
  keyEventResult = [];
  testStarted = false;
  expectedEventCount = 0;
  eventCount = 0;
  keyDownCount = 0;
  keyUpCount = 0;
  document.getElementById('log').innerHTML = "";
  return true;
}

function setFocusedElement(id) {
  if (id == "" && focusedElement != "") {
    var elem = document.getElementById(focusedElement);
    if (elem) {
      elem.blur();
      return true;
    }
  } else {
    var elem = document.getElementById(id);
    if (elem) {
      elem.focus();
      return true;
    }
  }
  return false;
}

function onFocus(element) {
  focusedElement = element.id;
  log("Focus: " + focusedElement);
}

function onBlur(element) {
  focusedElement = "";
  lastFocusedElement = element.id;
  log("Blur: " + element.id);
}

function onClick(element) {
  if (defaultActions[element.id] != undefined)
    defaultActions[element.id] = !element.checked;
}
</script>
</head>
<body onload="init()">
  <input type="checkbox" id="keydown" onclick="onClick(this)">keydown</input>
  <input type="checkbox" id="keypress" onclick="onClick(this)">keypress</input>
  <input type="checkbox" id="keyup" onclick="onClick(this)">keyup</input>
  <input type="checkbox" id="textInput" onclick="onClick(this)">textInput</input>
  <br/>
  <input type="checkbox" id="1" accesskey='1'
    onfocus="onFocus(this)" onblur="onBlur(this)"/>
  <input type="checkbox" id="2" accesskey='2'
    onfocus="onFocus(this)" onblur="onBlur(this)"/>
  <input type="checkbox" id="3" accesskey='3'
    onfocus="onFocus(this)" onblur="onBlur(this)"/>
  <input type="checkbox" id="D" accesskey='D'
    onfocus="onFocus(this)" onblur="onBlur(this)"/>
  <input type="text" id="A" accesskey="A"
    onfocus="onFocus(this)" onblur="onBlur(this)"/>
  <input type="password" id="B" accesskey="B"
    onfocus="onFocus(this)" onblur="onBlur(this)"/>
  <button id="clear" accesskey='C' onclick="clearResult()">Clear</button>
  <p id="log"></p>
</body>
</html>
