Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
1 /* Any copyright is dedicated to the public domain.
2 http://creativecommons.org/publicdomain/zero/1.0/ */
4 // Bug 905573 - Add setInputMethodActive to browser elements to allow gaia
5 // system set the active IME app.
6 'use strict';
8 SimpleTest.waitForExplicitFinish();
9 browserElementTestHelpers.setEnabledPref(true);
10 browserElementTestHelpers.addPermission();
12 function setup() {
13 let appInfo = SpecialPowers.Cc['@mozilla.org/xre/app-info;1']
14 .getService(SpecialPowers.Ci.nsIXULAppInfo);
15 if (appInfo.name != 'B2G') {
16 SpecialPowers.Cu.import("resource://gre/modules/Keyboard.jsm", window);
17 }
19 SpecialPowers.setBoolPref("dom.mozInputMethod.enabled", true);
20 SpecialPowers.setBoolPref("dom.mozInputMethod.testing", true);
21 SpecialPowers.addPermission('input-manage', true, document);
22 }
24 function tearDown() {
25 SpecialPowers.setBoolPref("dom.mozInputMethod.enabled", false);
26 SpecialPowers.setBoolPref("dom.mozInputMethod.testing", false);
27 SpecialPowers.removePermission('input-manage', document);
28 SimpleTest.finish();
29 }
31 function runTest() {
32 let path = location.pathname;
33 let imeUrl = location.protocol + '//' + location.host +
34 path.substring(0, path.lastIndexOf('/')) +
35 '/file_inputmethod.html';
36 SpecialPowers.pushPermissions([{
37 type: 'input',
38 allow: true,
39 context: {
40 url: imeUrl,
41 appId: SpecialPowers.Ci.nsIScriptSecurityManager.NO_APP_ID,
42 isInBrowserElement: true
43 }
44 }], createFrames);
45 }
47 var gFrames = [];
48 var gInputFrame;
50 function createFrames() {
51 // Create two input method iframes.
52 let loadendCount = 0;
53 let countLoadend = function() {
54 ok(this.setInputMethodActive, 'Can access setInputMethodActive.');
56 if (this === gInputFrame) {
57 // The frame script running in the frame where the input is hosted.
58 let appFrameScript = function appFrameScript() {
59 let input = content.document.body.firstElementChild;
60 input.oninput = function() {
61 sendAsyncMessage('test:InputMethod:oninput', this.value);
62 };
64 /*
65 * Bug 957213. Sometimes we need to refocus the input field to avoid
66 * intermittent test failure.
67 */
68 content.setInterval(function() {
69 input.focus();
70 }, 500);
71 }
73 // Inject frame script to receive input.
74 let mm = SpecialPowers.getBrowserFrameMessageManager(gInputFrame);
75 mm.loadFrameScript('data:,(' + appFrameScript.toString() + ')();', false);
76 mm.addMessageListener("test:InputMethod:oninput", next);
77 }
79 loadendCount++;
80 if (loadendCount === 3) {
81 startTest();
82 }
83 };
85 // Create an input field to receive string from input method iframes.
86 gInputFrame = document.createElement('iframe');
87 SpecialPowers.wrap(gInputFrame).mozbrowser = true;
88 gInputFrame.src =
89 'data:text/html,<input autofocus value="hello" />' +
90 '<p>This is targetted mozbrowser frame.</p>';
91 document.body.appendChild(gInputFrame);
92 gInputFrame.addEventListener('mozbrowserloadend', countLoadend);
94 for (let i = 0; i < 2; i++) {
95 let frame = gFrames[i] = document.createElement('iframe');
96 SpecialPowers.wrap(gFrames[i]).mozbrowser = true;
97 // When the input method iframe is activated, it will send the URL
98 // hash to current focused element. We set different hash to each
99 // iframe so that iframes can be differentiated by their hash.
100 frame.src = 'file_inputmethod.html#' + i;
101 document.body.appendChild(frame);
102 frame.addEventListener('mozbrowserloadend', countLoadend);
103 }
104 }
106 function startTest() {
107 // Set focus to the input field and wait for input methods' inputting.
108 SpecialPowers.DOMWindowUtils.focus(gInputFrame);
110 let req0 = gFrames[0].setInputMethodActive(true);
111 req0.onsuccess = function() {
112 ok(true, 'setInputMethodActive succeeded (0).');
113 };
115 req0.onerror = function() {
116 ok(false, 'setInputMethodActive failed (0): ' + this.error.name);
117 };
118 }
120 var gTimerId = null;
121 var gCount = 0;
123 function next(msg) {
124 gCount++;
125 let wrappedMsg = SpecialPowers.wrap(msg);
126 let value = wrappedMsg.data;
127 // The texts sent from the first and the second input method are '#0' and
128 // '#1' respectively.
129 switch (gCount) {
130 case 1:
131 is(value, '#0hello',
132 'Failed to get correct input from the first iframe.');
133 let req1 = gFrames[1].setInputMethodActive(true);
134 req1.onsuccess = function() {
135 ok(true, 'setInputMethodActive succeeded (1).');
136 };
137 req1.onerror = function() {
138 ok(false, 'setInputMethodActive failed (1): ' + this.error.name);
139 };
140 break;
142 case 2:
143 is(value, '#0#1hello',
144 'Failed to get correct input from the second iframe.');
145 // Do nothing and wait for the next input from the second iframe.
146 break;
148 case 3:
149 is(value, '#0#1#1hello',
150 'Failed to get correct input from the second iframe.');
151 // Receive the second input from the second iframe.
152 // Deactive the second iframe.
153 let req3 = gFrames[1].setInputMethodActive(false);
154 req3.onsuccess = function() {
155 ok(true, 'setInputMethodActive(false) succeeded (3).');
156 };
157 req3.onerror = function() {
158 ok(false, 'setInputMethodActive(false) failed (3): ' + this.error.name);
159 };
161 // Wait for a short while to ensure the second iframe is not active any
162 // more.
163 gTimerId = setTimeout(function() {
164 ok(true, 'Successfully deactivate the second iframe.');
165 tearDown();
166 }, 1000);
167 break;
169 case 4:
170 ok(false, 'Failed to deactivate the second iframe in time.');
171 clearTimeout(gTimerId);
172 tearDown();
173 break;
174 }
175 }
177 setup();
178 addEventListener('testready', runTest);