diff options
Diffstat (limited to 'dom/inputmethod/mochitest/bug1110030_helper.js')
-rw-r--r-- | dom/inputmethod/mochitest/bug1110030_helper.js | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/dom/inputmethod/mochitest/bug1110030_helper.js b/dom/inputmethod/mochitest/bug1110030_helper.js new file mode 100644 index 000000000..54f15825b --- /dev/null +++ b/dom/inputmethod/mochitest/bug1110030_helper.js @@ -0,0 +1,267 @@ +// *********************************** +// * Global variables +// *********************************** +const kIsWin = navigator.platform.indexOf("Win") == 0; + +// Bit value for the keyboard events +const kKeyDown = 0x01; +const kKeyPress = 0x02; +const kKeyUp = 0x04; + +// Pair the event name to its bit value +const kEventCode = { + 'keydown' : kKeyDown, + 'keypress' : kKeyPress, + 'keyup' : kKeyUp +}; + +// Holding the current test case's infomation: +var gCurrentTest; + +// The current used input method of this test +var gInputMethod; + +// *********************************** +// * Utilities +// *********************************** +function addKeyEventListeners(eventTarget, handler) +{ + Object.keys(kEventCode).forEach(function(type) { + eventTarget.addEventListener(type, handler); + }); +} + +function eventToCode(type) +{ + return kEventCode[type]; +} + +// To test key events that will be generated by input method here, +// we need to convert alphabets to native key code. +// (Our input method for testing will handle alphabets) +// On the other hand, to test key events that will not be generated by IME, +// we use 0-9 for such case in our testing. +function guessNativeKeyCode(key) +{ + let nativeCodeName = (kIsWin)? 'WIN_VK_' : 'MAC_VK_ANSI_'; + if (/^[A-Z]$/.test(key)) { + nativeCodeName += key; + } else if (/^[a-z]$/.test(key)) { + nativeCodeName += key.toUpperCase(); + } else if (/^[0-9]$/.test(key)) { + nativeCodeName += key.toString(); + } else { + return 0; + } + + return eval(nativeCodeName); +} + +// *********************************** +// * Frame loader and frame scripts +// *********************************** +function frameScript() +{ + function handler(e) { + sendAsyncMessage("forwardevent", { type: e.type, key: e.key }); + } + function notifyFinish(e) { + if (e.type != 'keyup') return; + sendAsyncMessage("finish"); + } + let input = content.document.getElementById('test-input'); + input.addEventListener('keydown', handler); + input.addEventListener('keypress', handler); + input.addEventListener('keyup', handler); + input.addEventListener('keyup', notifyFinish); +} + +function loadTestFrame(goNext) { + let iframe = document.createElement('iframe'); + iframe.src = 'file_test_empty_app.html'; + iframe.setAttribute('mozbrowser', true); + + iframe.addEventListener("mozbrowserloadend", function onloadend() { + iframe.removeEventListener("mozbrowserloadend", onloadend); + iframe.focus(); + var mm = SpecialPowers.getBrowserFrameMessageManager(iframe); + mm.addMessageListener("forwardevent", function(msg) { + inputtextEventReceiver(msg.json); + }); + mm.addMessageListener("finish", function(msg) { + if(goNext) { + goNext(); + } + }); + mm.loadFrameScript("data:,(" + frameScript.toString() + ")();", false); + return; + }); + + document.body.appendChild(iframe); +} + +// *********************************** +// * Event firer and listeners +// *********************************** +function fireEvent(callback) +{ + let key = gCurrentTest.key; + synthesizeNativeKey(KEYBOARD_LAYOUT_EN_US, guessNativeKeyCode(key), {}, + key, key, (callback) ? callback : null); +} + +function hardwareEventReceiver(evt) +{ + if (!gCurrentTest) { + return; + } + gCurrentTest.hardwareinput.receivedEvents |= eventToCode(evt.type); + gCurrentTest.hardwareinput.receivedKeys += evt.key; +} + +function inputtextEventReceiver(evt) +{ + if (!gCurrentTest) { + return; + } + gCurrentTest.inputtext.receivedEvents |= eventToCode(evt.type); + gCurrentTest.inputtext.receivedKeys += evt.key; +} + +// *********************************** +// * Event verifier +// *********************************** +function verifyResults(test) +{ + // Verify results received from inputcontent.hardwareinput + is(test.hardwareinput.receivedEvents, + test.hardwareinput.expectedEvents, + "received events from inputcontent.hardwareinput are wrong"); + + is(test.hardwareinput.receivedKeys, + test.hardwareinput.expectedKeys, + "received keys from inputcontent.hardwareinput are wrong"); + + // Verify results received from actual input text + is(test.inputtext.receivedEvents, + test.inputtext.expectedEvents, + "received events from input text are wrong"); + + is(test.inputtext.receivedKeys, + test.inputtext.expectedKeys, + "received keys from input text are wrong"); +} + +function areEventsSame(test) +{ + return (test.hardwareinput.receivedEvents == + test.hardwareinput.expectedEvents) && + (test.inputtext.receivedEvents == + test.inputtext.expectedEvents); +} + +// *********************************** +// * Input Method +// *********************************** +// The method input used in this test +// only handles alphabets +function InputMethod(inputContext) +{ + this._inputContext = inputContext; + this.init(); +} + +InputMethod.prototype = { + init: function im_init() { + this._setKepMap(); + }, + + handler: function im_handler(evt) { + // Ignore the key if the event is defaultPrevented + if (evt.defaultPrevented) { + return; + } + + // Finish if there is no _inputContext + if (!this._inputContext) { + return; + } + + // Generate the keyDict for inputcontext.keydown/keyup + let keyDict = this._generateKeyDict(evt); + + // Ignore the key if IME doesn't want to handle it + if (!keyDict) { + return; + } + + // Call preventDefault if the key will be handled. + evt.preventDefault(); + + // Call inputcontext.keydown/keyup + this._inputContext[evt.type](keyDict); + }, + + mapKey: function im_keymapping(key) { + if (!this._mappingTable) { + return; + } + return this._mappingTable[key]; + }, + + _setKepMap: function im_setKeyMap() { + // A table to map characters: + // { + // 'A': 'B' + // 'a': 'b' + // 'B': 'C' + // 'b': 'c' + // .. + // .. + // 'Z': 'A', + // 'z': 'a', + // } + this._mappingTable = {}; + + let rotation = 1; + + for (let i = 0 ; i < 26 ; i++) { + // Convert 'A' to 'B', 'B' to 'C', ..., 'Z' to 'A' + this._mappingTable[String.fromCharCode(i + 'A'.charCodeAt(0))] = + String.fromCharCode((i+rotation)%26 + 'A'.charCodeAt(0)); + + // Convert 'a' to 'b', 'b' to 'c', ..., 'z' to 'a' + this._mappingTable[String.fromCharCode(i + 'a'.charCodeAt(0))] = + String.fromCharCode((i+rotation)%26 + 'a'.charCodeAt(0)); + } + }, + + _generateKeyDict: function im_generateKeyDict(evt) { + + let mappedKey = this.mapKey(evt.key); + + if (!mappedKey) { + return; + } + + let keyDict = { + key: mappedKey, + code: this._guessCodeFromKey(mappedKey), + repeat: evt.repeat, + }; + + return keyDict; + }, + + _guessCodeFromKey: function im_guessCodeFromKey(key) { + if (/^[A-Z]$/.test(key)) { + return "Key" + key; + } else if (/^[a-z]$/.test(key)) { + return "Key" + key.toUpperCase(); + } else if (/^[0-9]$/.test(key)) { + return "Digit" + key.toString(); + } else { + return 0; + } + }, +}; |