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

This is targetted mozbrowser frame.

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