diff -r 000000000000 -r 6474c204b198 dom/browser-element/mochitest/browserElement_SetInputMethodActive.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/browser-element/mochitest/browserElement_SetInputMethodActive.js Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,178 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 905573 - Add setInputMethodActive to browser elements to allow gaia +// system set the active IME app. +'use strict'; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +function setup() { + let appInfo = SpecialPowers.Cc['@mozilla.org/xre/app-info;1'] + .getService(SpecialPowers.Ci.nsIXULAppInfo); + if (appInfo.name != 'B2G') { + SpecialPowers.Cu.import("resource://gre/modules/Keyboard.jsm", window); + } + + SpecialPowers.setBoolPref("dom.mozInputMethod.enabled", true); + SpecialPowers.setBoolPref("dom.mozInputMethod.testing", true); + SpecialPowers.addPermission('input-manage', true, document); +} + +function tearDown() { + SpecialPowers.setBoolPref("dom.mozInputMethod.enabled", false); + SpecialPowers.setBoolPref("dom.mozInputMethod.testing", false); + SpecialPowers.removePermission('input-manage', document); + SimpleTest.finish(); +} + +function runTest() { + let path = location.pathname; + let imeUrl = location.protocol + '//' + location.host + + path.substring(0, path.lastIndexOf('/')) + + '/file_inputmethod.html'; + SpecialPowers.pushPermissions([{ + type: 'input', + allow: true, + context: { + url: imeUrl, + appId: SpecialPowers.Ci.nsIScriptSecurityManager.NO_APP_ID, + isInBrowserElement: true + } + }], createFrames); +} + +var gFrames = []; +var gInputFrame; + +function createFrames() { + // Create two input method iframes. + let loadendCount = 0; + let countLoadend = function() { + ok(this.setInputMethodActive, 'Can access setInputMethodActive.'); + + if (this === gInputFrame) { + // The frame script running in the frame where the input is hosted. + let appFrameScript = function appFrameScript() { + let input = content.document.body.firstElementChild; + input.oninput = function() { + sendAsyncMessage('test:InputMethod:oninput', this.value); + }; + + /* + * Bug 957213. Sometimes we need to refocus the input field to avoid + * intermittent test failure. + */ + content.setInterval(function() { + input.focus(); + }, 500); + } + + // Inject frame script to receive input. + let mm = SpecialPowers.getBrowserFrameMessageManager(gInputFrame); + mm.loadFrameScript('data:,(' + appFrameScript.toString() + ')();', false); + mm.addMessageListener("test:InputMethod:oninput", next); + } + + loadendCount++; + if (loadendCount === 3) { + startTest(); + } + }; + + // Create an input field to receive string from input method iframes. + gInputFrame = document.createElement('iframe'); + SpecialPowers.wrap(gInputFrame).mozbrowser = true; + gInputFrame.src = + 'data:text/html,' + + '

This is targetted mozbrowser frame.

'; + document.body.appendChild(gInputFrame); + gInputFrame.addEventListener('mozbrowserloadend', countLoadend); + + for (let i = 0; i < 2; i++) { + let frame = gFrames[i] = document.createElement('iframe'); + SpecialPowers.wrap(gFrames[i]).mozbrowser = true; + // When the input method iframe is activated, it will send the URL + // hash to current focused element. We set different hash to each + // iframe so that iframes can be differentiated by their hash. + frame.src = 'file_inputmethod.html#' + i; + document.body.appendChild(frame); + frame.addEventListener('mozbrowserloadend', countLoadend); + } +} + +function startTest() { + // Set focus to the input field and wait for input methods' inputting. + SpecialPowers.DOMWindowUtils.focus(gInputFrame); + + let req0 = gFrames[0].setInputMethodActive(true); + req0.onsuccess = function() { + ok(true, 'setInputMethodActive succeeded (0).'); + }; + + req0.onerror = function() { + ok(false, 'setInputMethodActive failed (0): ' + this.error.name); + }; +} + +var gTimerId = null; +var gCount = 0; + +function next(msg) { + gCount++; + let wrappedMsg = SpecialPowers.wrap(msg); + let value = wrappedMsg.data; + // The texts sent from the first and the second input method are '#0' and + // '#1' respectively. + switch (gCount) { + case 1: + is(value, '#0hello', + 'Failed to get correct input from the first iframe.'); + let req1 = gFrames[1].setInputMethodActive(true); + req1.onsuccess = function() { + ok(true, 'setInputMethodActive succeeded (1).'); + }; + req1.onerror = function() { + ok(false, 'setInputMethodActive failed (1): ' + this.error.name); + }; + break; + + case 2: + is(value, '#0#1hello', + 'Failed to get correct input from the second iframe.'); + // Do nothing and wait for the next input from the second iframe. + break; + + case 3: + is(value, '#0#1#1hello', + 'Failed to get correct input from the second iframe.'); + // Receive the second input from the second iframe. + // Deactive the second iframe. + let req3 = gFrames[1].setInputMethodActive(false); + req3.onsuccess = function() { + ok(true, 'setInputMethodActive(false) succeeded (3).'); + }; + req3.onerror = function() { + ok(false, 'setInputMethodActive(false) failed (3): ' + this.error.name); + }; + + // Wait for a short while to ensure the second iframe is not active any + // more. + gTimerId = setTimeout(function() { + ok(true, 'Successfully deactivate the second iframe.'); + tearDown(); + }, 1000); + break; + + case 4: + ok(false, 'Failed to deactivate the second iframe in time.'); + clearTimeout(gTimerId); + tearDown(); + break; + } +} + +setup(); +addEventListener('testready', runTest);