Bumping manifests a=b2g-bump
[gecko.git] / widget / tests / window_imestate_iframes.html
blob064cf19a5f66d054d58dab165465d72d28b858a9
1 <html>
2 <head>
3 <title>Test for IME state controling and focus moving for iframes</title>
4 <script type="text/javascript"
5 src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
6 <link rel="stylesheet" type="text/css"
7 href="chrome://mochikit/content/tests/SimpleTest/test.css" />
8 <style type="text/css">
9 iframe {
10 border: none;
11 height: 100px;
13 </style>
14 </head>
15 <body onunload="onUnload();">
16 <p id="display">
17 <!-- Use input[readonly] because it isn't affected by the partial focus
18 movement on Mac -->
19 <input id="prev" readonly><br>
20 <iframe id="iframe_not_editable"
21 src="data:text/html,&lt;html&gt;&lt;body&gt;&lt;input id='editor'&gt;&lt;/body&gt;&lt;/html&gt;"></iframe><br>
23 <!-- Testing IME state and focus movement, the anchor elements cannot get focus -->
24 <iframe id="iframe_html"
25 src="data:text/html,&lt;html id='editor' contenteditable='true'&gt;&lt;body&gt;&lt;a href='about:blank'&gt;about:blank;&lt;/a&gt;&lt;/body&gt;&lt;/html&gt;"></iframe><br>
26 <iframe id="iframe_designMode"
27 src="data:text/html,&lt;body id='editor' onload='document.designMode=&quot;on&quot;;'&gt;&lt;a href='about:blank'&gt;about:blank;&lt;/a&gt;&lt;/body&gt;"></iframe><br>
28 <iframe id="iframe_body"
29 src="data:text/html,&lt;body id='editor' contenteditable='true'&gt;&lt;a href='about:blank'&gt;about:blank;&lt;/a&gt;&lt;/body&gt;"></iframe><br>
30 <iframe id="iframe_p"
31 src="data:text/html,&lt;body&gt;&lt;p id='editor' contenteditable='true'&gt;&lt;a href='about:blank'&gt;about:blank;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;"></iframe><br>
33 <input id="next" readonly><br>
34 </p>
35 <script class="testbody" type="application/javascript">
37 window.opener.wrappedJSObject.SimpleTest.waitForFocus(runTests, window);
39 function ok(aCondition, aMessage)
41 window.opener.wrappedJSObject.SimpleTest.ok(aCondition, aMessage);
44 function is(aLeft, aRight, aMessage)
46 window.opener.wrappedJSObject.SimpleTest.is(aLeft, aRight, aMessage);
49 function onUnload()
51 window.opener.wrappedJSObject.onFinish();
54 var gFocusObservingElement = null;
55 var gBlurObservingElement = null;
57 function onFocus(aEvent)
59 if (aEvent.target != gFocusObservingElement) {
60 return;
62 ok(gFocusObservingElement.willFocus,
63 "focus event is fired on unexpected element");
64 gFocusObservingElement.willFocus = false;
67 function onBlur(aEvent)
69 if (aEvent.target != gBlurObservingElement) {
70 return;
72 ok(gBlurObservingElement.willBlur,
73 "blur event is fired on unexpected element");
74 gBlurObservingElement.willBlur = false;
77 function observeFocusBlur(aNextFocusedNode, aWillFireFocusEvent,
78 aNextBlurredNode, aWillFireBlurEvent)
80 if (gFocusObservingElement) {
81 if (gFocusObservingElement.willFocus) {
82 ok(false, "focus event was never fired on " + gFocusObservingElement);
84 gFocusObservingElement.removeEventListener("focus", onFocus, true);
85 gFocusObservingElement.willFocus = NaN;
86 gFocusObservingElement = null;
88 if (gBlurObservingElement) {
89 if (gBlurObservingElement.willBlur) {
90 ok(false, "blur event was never fired on " + gBlurObservingElement);
92 gBlurObservingElement.removeEventListener("blur", onBlur, true);
93 gBlurObservingElement.willBlur = NaN;
94 gBlurObservingElement = null;
96 if (aNextFocusedNode) {
97 gFocusObservingElement = aNextFocusedNode;
98 gFocusObservingElement.willFocus = aWillFireFocusEvent;
99 gFocusObservingElement.addEventListener("focus", onFocus, true);
101 if (aNextBlurredNode) {
102 gBlurObservingElement = aNextBlurredNode;
103 gBlurObservingElement.willBlur = aWillFireBlurEvent;
104 gBlurObservingElement.addEventListener("blur", onBlur, true);
108 function runTests()
110 var utils =
111 window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
112 .getInterface(Components.interfaces.nsIDOMWindowUtils);
113 var fm =
114 Components.classes["@mozilla.org/focus-manager;1"]
115 .getService(Components.interfaces.nsIFocusManager);
117 var iframe, editor, root, input;
118 var prev = document.getElementById("prev");
119 var next = document.getElementById("next");
120 var html = document.documentElement;
122 function resetFocusToInput(aDescription)
124 observeFocusBlur(null, false, null, false);
125 prev.focus();
126 is(fm.focusedElement, prev,
127 "input#prev[readonly] element didn't get focus: " + aDescription);
128 is(utils.IMEStatus, utils.IME_STATUS_DISABLED,
129 "IME enabled on input#prev[readonly]: " + aDescription);
132 function resetFocusToParentHTML(aDescription)
134 observeFocusBlur(null, false, null, false);
135 html.focus();
136 is(fm.focusedElement, html,
137 "Parent html element didn't get focus: " + aDescription);
138 is(utils.IMEStatus, utils.IME_STATUS_DISABLED,
139 "IME enabled on parent html element: " + aDescription);
142 function testTabKey(aForward,
143 aNextFocusedNode, aWillFireFocusEvent,
144 aNextBlurredNode, aWillFireBlurEvent,
145 aIMEShouldBeEnabled, aTestingCaseDescription)
147 observeFocusBlur(aNextFocusedNode, aWillFireFocusEvent,
148 aNextBlurredNode, aWillFireBlurEvent);
149 synthesizeKey("VK_TAB", { shiftKey: !aForward });
150 var description = "Tab key test: ";
151 if (!aForward) {
152 description = "Shift-" + description;
154 description += aTestingCaseDescription + ": ";
155 is(fm.focusedElement, aNextFocusedNode,
156 description + "didn't move focus as expected");
157 is(utils.IMEStatus,
158 aIMEShouldBeEnabled ?
159 utils.IME_STATUS_ENABLED : utils.IME_STATUS_DISABLED,
160 description + "didn't set IME state as expected");
163 function testMouseClick(aNextFocusedNode, aWillFireFocusEvent,
164 aWillAllNodeLostFocus,
165 aNextBlurredNode, aWillFireBlurEvent,
166 aIMEShouldBeEnabled, aTestingCaseDescription)
168 observeFocusBlur(aNextFocusedNode, aWillFireFocusEvent,
169 aNextBlurredNode, aWillFireBlurEvent);
170 // We're relying on layout inside the iframe being up to date, so make it so
171 iframe.contentDocument.documentElement.getBoundingClientRect();
172 synthesizeMouse(iframe, 10, 80, { });
173 var description = "Click test: " + aTestingCaseDescription + ": ";
174 is(fm.focusedElement, !aWillAllNodeLostFocus ? aNextFocusedNode : null,
175 description + "didn't move focus as expected");
176 is(utils.IMEStatus,
177 aIMEShouldBeEnabled ?
178 utils.IME_STATUS_ENABLED : utils.IME_STATUS_DISABLED,
179 description + "didn't set IME state as expected");
182 function testOnEditorFlagChange(aDescription, aIsInDesignMode)
184 const kReadonly =
185 Components.interfaces.nsIPlaintextEditor.eEditorReadonlyMask;
186 var description = "testOnEditorFlagChange: " + aDescription;
187 resetFocusToParentHTML(description);
188 var htmlEditor =
189 iframe.contentWindow.
190 QueryInterface(Components.interfaces.nsIInterfaceRequestor).
191 getInterface(Components.interfaces.nsIWebNavigation).
192 QueryInterface(Components.interfaces.nsIDocShell).editor;
193 var e = aIsInDesignMode ? root : editor;
194 e.focus();
195 is(fm.focusedElement, e,
196 description + ": focus() of editor didn't move focus as expected");
197 is(utils.IMEStatus, utils.IME_STATUS_ENABLED,
198 description + ": IME isn't enabled when the editor gets focus");
199 var flags = htmlEditor.flags;
200 htmlEditor.flags |= kReadonly;
201 is(fm.focusedElement, e,
202 description + ": when editor becomes readonly, focus moved unexpectedly");
203 is(utils.IMEStatus, utils.IME_STATUS_DISABLED,
204 description + ": when editor becomes readonly, IME is still enabled");
205 htmlEditor.flags = flags;
206 is(fm.focusedElement, e,
207 description + ": when editor becomes read-write, focus moved unexpectedly");
208 is(utils.IMEStatus, utils.IME_STATUS_ENABLED,
209 description + ": when editor becomes read-write, IME is still disabled");
212 // hide all iframes
213 document.getElementById("iframe_not_editable").style.display = "none";
214 document.getElementById("iframe_html").style.display = "none";
215 document.getElementById("iframe_designMode").style.display = "none";
216 document.getElementById("iframe_body").style.display = "none";
217 document.getElementById("iframe_p").style.display = "none";
219 // non editable HTML element and input element can get focus.
220 iframe = document.getElementById("iframe_not_editable");
221 iframe.style.display = "inline";
222 editor = iframe.contentDocument.getElementById("editor");
223 root = iframe.contentDocument.documentElement;
224 resetFocusToInput("initializing for iframe_not_editable");
226 testTabKey(true, root, false, prev, true,
227 false, "input#prev[readonly] -> html");
228 testTabKey(true, editor, true, root, false,
229 true, "html -> input in the subdoc");
230 testTabKey(true, next, true, editor, true,
231 false, "input in the subdoc -> input#next[readonly]");
232 testTabKey(false, editor, true, next, true,
233 true, "input#next[readonly] -> input in the subdoc");
234 testTabKey(false, root, false, editor, true,
235 false, "input in the subdoc -> html");
236 testTabKey(false, prev, true, root, false,
237 false, "html -> input#next[readonly]");
239 iframe.style.display = "none";
241 // HTML element (of course, it's root) must enables IME.
242 iframe = document.getElementById("iframe_html");
243 iframe.style.display = "inline";
244 editor = iframe.contentDocument.getElementById("editor");
245 root = iframe.contentDocument.documentElement;
246 resetFocusToInput("initializing for iframe_html");
248 testTabKey(true, editor, true, prev, true,
249 true, "input#prev[readonly] -> html[contentediable=true]");
250 testTabKey(true, next, true, editor, true,
251 false, "html[contentediable=true] -> input#next[readonly]");
252 testTabKey(false, editor, true, next, true,
253 true, "input#next[readonly] -> html[contentediable=true]");
254 testTabKey(false, prev, true, editor, true,
255 false, "html[contenteditable=true] -> input[readonly]");
257 prev.style.display = "none";
258 resetFocusToParentHTML("testing iframe_html");
259 testTabKey(true, editor, true, html, false,
260 true, "html of parent -> html[contentediable=true]");
261 testTabKey(false, html, false, editor, true,
262 false, "html[contenteditable=true] -> html of parent");
263 prev.style.display = "inline";
264 resetFocusToInput("after parent html <-> html[contenteditable=true]");
266 testMouseClick(editor, true, false, prev, true, true, "iframe_html");
268 testOnEditorFlagChange("html[contentediable=true]", false);
270 iframe.style.display = "none";
272 // designMode should behave like <html contenteditable="true"></html>
273 // but focus/blur events shouldn't be fired on its root element because
274 // any elements shouldn't be focused state in designMode.
275 iframe = document.getElementById("iframe_designMode");
276 iframe.style.display = "inline";
277 iframe.contentDocument.designMode = "on";
278 editor = iframe.contentDocument.getElementById("editor");
279 root = iframe.contentDocument.documentElement;
280 resetFocusToInput("initializing for iframe_designMode");
282 testTabKey(true, root, false, prev, true,
283 true, "input#prev[readonly] -> html in designMode");
284 testTabKey(true, next, true, root, false,
285 false, "html in designMode -> input#next[readonly]");
286 testTabKey(false, root, false, next, true,
287 true, "input#next[readonly] -> html in designMode");
288 testTabKey(false, prev, true, root, false,
289 false, "html in designMode -> input#prev[readonly]");
291 prev.style.display = "none";
292 resetFocusToParentHTML("testing iframe_designMode");
293 testTabKey(true, root, false, html, false,
294 true, "html of parent -> html in designMode");
295 testTabKey(false, html, false, root, false,
296 false, "html in designMode -> html of parent");
297 prev.style.display = "inline";
298 resetFocusToInput("after parent html <-> html in designMode");
300 testMouseClick(editor, false, true, prev, true, true, "iframe_designMode");
302 testOnEditorFlagChange("html in designMode", true);
304 iframe.style.display = "none";
306 // When there is no HTML element but the BODY element is editable,
307 // the body element should get focus and enables IME.
308 iframe = document.getElementById("iframe_body");
309 iframe.style.display = "inline";
310 editor = iframe.contentDocument.getElementById("editor");
311 root = iframe.contentDocument.documentElement;
312 resetFocusToInput("initializing for iframe_body");
314 testTabKey(true, editor, true, prev, true,
315 true, "input#prev[readonly] -> body[contentediable=true]");
316 testTabKey(true, next, true, editor, true,
317 false, "body[contentediable=true] -> input#next[readonly]");
318 testTabKey(false, editor, true, next, true,
319 true, "input#next[readonly] -> body[contentediable=true]");
320 testTabKey(false, prev, true, editor, true,
321 false, "body[contenteditable=true] -> input#prev[readonly]");
323 prev.style.display = "none";
324 resetFocusToParentHTML("testing iframe_body");
325 testTabKey(true, editor, true, html, false,
326 true, "html of parent -> body[contentediable=true]");
327 testTabKey(false, html, false, editor, true,
328 false, "body[contenteditable=true] -> html of parent");
329 prev.style.display = "inline";
330 resetFocusToInput("after parent html <-> body[contenteditable=true]");
332 testMouseClick(editor, true, false, prev, true, true, "iframe_body");
334 testOnEditorFlagChange("body[contentediable=true]", false);
336 iframe.style.display = "none";
338 // When HTML/BODY elements are not editable, focus shouldn't be moved to
339 // the editable content directly.
340 iframe = document.getElementById("iframe_p");
341 iframe.style.display = "inline";
342 editor = iframe.contentDocument.getElementById("editor");
343 root = iframe.contentDocument.documentElement;
344 resetFocusToInput("initializing for iframe_p");
346 testTabKey(true, root, false, prev, true,
347 false, "input#prev[readonly] -> html (has p[contenteditable=true])");
348 testTabKey(true, editor, true, root, false,
349 true, "html (has p[contenteditable=true]) -> p[contentediable=true]");
350 testTabKey(true, next, true, editor, true,
351 false, "p[contentediable=true] -> input#next[readonly]");
352 testTabKey(false, editor, true, next, true,
353 true, "input#next[readonly] -> p[contentediable=true]");
354 testTabKey(false, root, false, editor, true,
355 false, "p[contenteditable=true] -> html (has p[contenteditable=true])");
356 testTabKey(false, prev, true, root, false,
357 false, "html (has p[contenteditable=true]) -> input#prev[readonly]");
358 prev.style.display = "none";
360 resetFocusToParentHTML("testing iframe_p");
361 testTabKey(true, root, false, html, false,
362 false, "html of parent -> html (has p[contentediable=true])");
363 testTabKey(false, html, false, root, false,
364 false, "html (has p[contentediable=true]) -> html of parent");
365 prev.style.display = "inline";
366 resetFocusToInput("after parent html <-> html (has p[contentediable=true])");
368 testMouseClick(root, false, true, prev, true, false, "iframe_p");
370 testOnEditorFlagChange("p[contenteditable=true]", false);
372 iframe.style.display = "none";
374 window.close();
377 </script>
378 </body>
380 </html>