|
1 /* Any copyright is dedicated to the public domain. |
|
2 http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 |
|
4 // Bug 905573 - Add setInputMethodActive to browser elements to allow gaia |
|
5 // system set the active IME app. |
|
6 'use strict'; |
|
7 |
|
8 SimpleTest.waitForExplicitFinish(); |
|
9 browserElementTestHelpers.setEnabledPref(true); |
|
10 browserElementTestHelpers.addPermission(); |
|
11 |
|
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 } |
|
18 |
|
19 SpecialPowers.setBoolPref("dom.mozInputMethod.enabled", true); |
|
20 SpecialPowers.setBoolPref("dom.mozInputMethod.testing", true); |
|
21 SpecialPowers.addPermission('input-manage', true, document); |
|
22 } |
|
23 |
|
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 } |
|
30 |
|
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 } |
|
46 |
|
47 var gFrames = []; |
|
48 var gInputFrame; |
|
49 |
|
50 function createFrames() { |
|
51 // Create two input method iframes. |
|
52 let loadendCount = 0; |
|
53 let countLoadend = function() { |
|
54 ok(this.setInputMethodActive, 'Can access setInputMethodActive.'); |
|
55 |
|
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 }; |
|
63 |
|
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 } |
|
72 |
|
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 } |
|
78 |
|
79 loadendCount++; |
|
80 if (loadendCount === 3) { |
|
81 startTest(); |
|
82 } |
|
83 }; |
|
84 |
|
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); |
|
93 |
|
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 } |
|
105 |
|
106 function startTest() { |
|
107 // Set focus to the input field and wait for input methods' inputting. |
|
108 SpecialPowers.DOMWindowUtils.focus(gInputFrame); |
|
109 |
|
110 let req0 = gFrames[0].setInputMethodActive(true); |
|
111 req0.onsuccess = function() { |
|
112 ok(true, 'setInputMethodActive succeeded (0).'); |
|
113 }; |
|
114 |
|
115 req0.onerror = function() { |
|
116 ok(false, 'setInputMethodActive failed (0): ' + this.error.name); |
|
117 }; |
|
118 } |
|
119 |
|
120 var gTimerId = null; |
|
121 var gCount = 0; |
|
122 |
|
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; |
|
141 |
|
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; |
|
147 |
|
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 }; |
|
160 |
|
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; |
|
168 |
|
169 case 4: |
|
170 ok(false, 'Failed to deactivate the second iframe in time.'); |
|
171 clearTimeout(gTimerId); |
|
172 tearDown(); |
|
173 break; |
|
174 } |
|
175 } |
|
176 |
|
177 setup(); |
|
178 addEventListener('testready', runTest); |