Backed out changeset ce9c917d3e22 (bug 582361) for causing wpt failures on scroll...
[gecko.git] / widget / tests / window_imestate_iframes.html
blobc8b182977fe9f6a6a2604a3e38a66660c806fb14
1 <html>
2 <head>
3 <title>Test for IME state controling and focus moving for iframes</title>
4 <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
5 <link rel="stylesheet" type="text/css"
6 href="chrome://mochikit/content/tests/SimpleTest/test.css" />
7 <style type="text/css">
8 iframe {
9 border: none;
10 height: 100px;
12 </style>
13 </head>
14 <body onunload="onUnload();">
15 <p id="display">
16 <!-- Use input[readonly] because it isn't affected by the partial focus
17 movement on Mac -->
18 <input id="prev" readonly><br>
19 <iframe id="iframe_not_editable"
20 src="data:text/html,&lt;html&gt;&lt;body&gt;&lt;input id='editor'&gt;&lt;/body&gt;&lt;/html&gt;"></iframe><br>
22 <!-- Testing IME state and focus movement, the anchor elements cannot get focus -->
23 <iframe id="iframe_html"
24 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>
25 <iframe id="iframe_designMode"
26 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>
27 <iframe id="iframe_body"
28 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>
29 <iframe id="iframe_p"
30 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>
32 <input id="next" readonly><br>
33 </p>
34 <script class="testbody" type="application/javascript">
36 window.opener.SimpleTest.waitForFocus(runTests, window);
38 function ok(aCondition, aMessage) {
39 window.opener.SimpleTest.ok(aCondition, aMessage);
42 function is(aLeft, aRight, aMessage) {
43 window.opener.SimpleTest.is(aLeft, aRight, aMessage);
46 function onUnload() {
47 window.opener.onFinish();
50 var gFocusObservingElement = null;
51 var gBlurObservingElement = null;
53 function onFocus(aEvent) {
54 if (aEvent.target != gFocusObservingElement) {
55 return;
57 ok(gFocusObservingElement.willFocus,
58 "focus event is fired on unexpected element");
59 gFocusObservingElement.willFocus = false;
62 function onBlur(aEvent) {
63 if (aEvent.target != gBlurObservingElement) {
64 return;
66 ok(gBlurObservingElement.willBlur,
67 "blur event is fired on unexpected element");
68 gBlurObservingElement.willBlur = false;
71 function observeFocusBlur(aNextFocusedNode, aWillFireFocusEvent,
72 aNextBlurredNode, aWillFireBlurEvent) {
73 if (gFocusObservingElement) {
74 if (gFocusObservingElement.willFocus) {
75 ok(false, "focus event was never fired on " + gFocusObservingElement);
77 gFocusObservingElement.removeEventListener("focus", onFocus, true);
78 gFocusObservingElement.willFocus = NaN;
79 gFocusObservingElement = null;
81 if (gBlurObservingElement) {
82 if (gBlurObservingElement.willBlur) {
83 ok(false, "blur event was never fired on " + gBlurObservingElement);
85 gBlurObservingElement.removeEventListener("blur", onBlur, true);
86 gBlurObservingElement.willBlur = NaN;
87 gBlurObservingElement = null;
89 if (aNextFocusedNode) {
90 gFocusObservingElement = aNextFocusedNode;
91 gFocusObservingElement.willFocus = aWillFireFocusEvent;
92 gFocusObservingElement.addEventListener("focus", onFocus, true);
94 if (aNextBlurredNode) {
95 gBlurObservingElement = aNextBlurredNode;
96 gBlurObservingElement.willBlur = aWillFireBlurEvent;
97 gBlurObservingElement.addEventListener("blur", onBlur, true);
101 function runTests() {
102 var utils = window.windowUtils;
103 var fm = Services.focus;
105 var iframe, editor, root;
106 var prev = document.getElementById("prev");
107 var next = document.getElementById("next");
108 var html = document.documentElement;
110 function resetFocusToInput(aDescription) {
111 observeFocusBlur(null, false, null, false);
112 prev.focus();
113 is(fm.focusedElement, prev,
114 "input#prev[readonly] element didn't get focus: " + aDescription);
115 is(utils.IMEStatus, utils.IME_STATUS_DISABLED,
116 "IME enabled on input#prev[readonly]: " + aDescription);
119 function resetFocusToParentHTML(aDescription) {
120 observeFocusBlur(null, false, null, false);
121 html.focus();
122 is(fm.focusedElement, html,
123 "Parent html element didn't get focus: " + aDescription);
124 is(utils.IMEStatus, utils.IME_STATUS_DISABLED,
125 "IME enabled on parent html element: " + aDescription);
128 function testTabKey(aForward,
129 aNextFocusedNode, aWillFireFocusEvent,
130 aNextBlurredNode, aWillFireBlurEvent,
131 aIMEShouldBeEnabled, aTestingCaseDescription) {
132 observeFocusBlur(aNextFocusedNode, aWillFireFocusEvent,
133 aNextBlurredNode, aWillFireBlurEvent);
134 synthesizeKey("VK_TAB", { shiftKey: !aForward });
135 var description = "Tab key test: ";
136 if (!aForward) {
137 description = "Shift-" + description;
139 description += aTestingCaseDescription + ": ";
140 is(fm.focusedElement, aNextFocusedNode,
141 description + "didn't move focus as expected");
142 is(utils.IMEStatus,
143 aIMEShouldBeEnabled ?
144 utils.IME_STATUS_ENABLED : utils.IME_STATUS_DISABLED,
145 description + "didn't set IME state as expected");
148 function testMouseClick(aNextFocusedNode, aWillFireFocusEvent,
149 aWillAllNodeLostFocus,
150 aNextBlurredNode, aWillFireBlurEvent,
151 aIMEShouldBeEnabled, aTestingCaseDescription) {
152 observeFocusBlur(aNextFocusedNode, aWillFireFocusEvent,
153 aNextBlurredNode, aWillFireBlurEvent);
154 // We're relying on layout inside the iframe being up to date, so make it so
155 iframe.contentDocument.documentElement.getBoundingClientRect();
156 synthesizeMouse(iframe, 10, 80, { });
157 var description = "Click test: " + aTestingCaseDescription + ": ";
158 is(fm.focusedElement, !aWillAllNodeLostFocus ? aNextFocusedNode : null,
159 description + "didn't move focus as expected");
160 is(utils.IMEStatus,
161 aIMEShouldBeEnabled ?
162 utils.IME_STATUS_ENABLED : utils.IME_STATUS_DISABLED,
163 description + "didn't set IME state as expected");
166 function testOnEditorFlagChange(aDescription, aIsInDesignMode) {
167 const kReadonly = Ci.nsIEditor.eEditorReadonlyMask;
168 var description = "testOnEditorFlagChange: " + aDescription;
169 resetFocusToParentHTML(description);
170 var htmlEditor = iframe.contentWindow.docShell.editor;
171 var e = aIsInDesignMode ? root : editor;
172 e.focus();
173 is(fm.focusedElement, e,
174 description + ": focus() of editor didn't move focus as expected");
175 is(utils.IMEStatus, utils.IME_STATUS_ENABLED,
176 description + ": IME isn't enabled when the editor gets focus");
177 var flags = htmlEditor.flags;
178 htmlEditor.flags |= kReadonly;
179 is(fm.focusedElement, e,
180 description + ": when editor becomes readonly, focus moved unexpectedly");
181 is(utils.IMEStatus, utils.IME_STATUS_DISABLED,
182 description + ": when editor becomes readonly, IME is still enabled");
183 htmlEditor.flags = flags;
184 is(fm.focusedElement, e,
185 description + ": when editor becomes read-write, focus moved unexpectedly");
186 is(utils.IMEStatus, utils.IME_STATUS_ENABLED,
187 description + ": when editor becomes read-write, IME is still disabled");
190 // hide all iframes
191 document.getElementById("iframe_not_editable").style.display = "none";
192 document.getElementById("iframe_html").style.display = "none";
193 document.getElementById("iframe_designMode").style.display = "none";
194 document.getElementById("iframe_body").style.display = "none";
195 document.getElementById("iframe_p").style.display = "none";
197 // non editable HTML element and input element can get focus.
198 iframe = document.getElementById("iframe_not_editable");
199 iframe.style.display = "inline";
200 editor = iframe.contentDocument.getElementById("editor");
201 root = iframe.contentDocument.documentElement;
202 resetFocusToInput("initializing for iframe_not_editable");
204 testTabKey(true, root, false, prev, true,
205 false, "input#prev[readonly] -> html");
206 testTabKey(true, editor, true, root, false,
207 true, "html -> input in the subdoc");
208 testTabKey(true, next, true, editor, true,
209 false, "input in the subdoc -> input#next[readonly]");
210 testTabKey(false, editor, true, next, true,
211 true, "input#next[readonly] -> input in the subdoc");
212 testTabKey(false, root, false, editor, true,
213 false, "input in the subdoc -> html");
214 testTabKey(false, prev, true, root, false,
215 false, "html -> input#next[readonly]");
217 iframe.style.display = "none";
219 // HTML element (of course, it's root) must enables IME.
220 iframe = document.getElementById("iframe_html");
221 iframe.style.display = "inline";
222 editor = iframe.contentDocument.getElementById("editor");
223 root = iframe.contentDocument.documentElement;
224 resetFocusToInput("initializing for iframe_html");
226 testTabKey(true, editor, true, prev, true,
227 true, "input#prev[readonly] -> html[contentediable=true]");
228 testTabKey(true, next, true, editor, true,
229 false, "html[contentediable=true] -> input#next[readonly]");
230 testTabKey(false, editor, true, next, true,
231 true, "input#next[readonly] -> html[contentediable=true]");
232 testTabKey(false, prev, true, editor, true,
233 false, "html[contenteditable=true] -> input[readonly]");
235 prev.style.display = "none";
236 resetFocusToParentHTML("testing iframe_html");
237 testTabKey(true, editor, true, html, false,
238 true, "html of parent -> html[contentediable=true]");
239 testTabKey(false, html, false, editor, true,
240 false, "html[contenteditable=true] -> html of parent");
241 prev.style.display = "inline";
242 resetFocusToInput("after parent html <-> html[contenteditable=true]");
244 testMouseClick(editor, true, false, prev, true, true, "iframe_html");
246 testOnEditorFlagChange("html[contentediable=true]", false);
248 iframe.style.display = "none";
250 // designMode should behave like <html contenteditable="true"></html>
251 // but focus/blur events shouldn't be fired on its root element because
252 // any elements shouldn't be focused state in designMode.
253 iframe = document.getElementById("iframe_designMode");
254 iframe.style.display = "inline";
255 iframe.contentDocument.designMode = "on";
256 editor = iframe.contentDocument.getElementById("editor");
257 root = iframe.contentDocument.documentElement;
258 resetFocusToInput("initializing for iframe_designMode");
260 testTabKey(true, root, false, prev, true,
261 true, "input#prev[readonly] -> html in designMode");
262 testTabKey(true, next, true, root, false,
263 false, "html in designMode -> input#next[readonly]");
264 testTabKey(false, root, false, next, true,
265 true, "input#next[readonly] -> html in designMode");
266 testTabKey(false, prev, true, root, false,
267 false, "html in designMode -> input#prev[readonly]");
269 prev.style.display = "none";
270 resetFocusToParentHTML("testing iframe_designMode");
271 testTabKey(true, root, false, html, false,
272 true, "html of parent -> html in designMode");
273 testTabKey(false, html, false, root, false,
274 false, "html in designMode -> html of parent");
275 prev.style.display = "inline";
276 resetFocusToInput("after parent html <-> html in designMode");
278 testMouseClick(editor, false, true, prev, true, true, "iframe_designMode");
280 testOnEditorFlagChange("html in designMode", true);
282 iframe.style.display = "none";
284 // When there is no HTML element but the BODY element is editable,
285 // the body element should get focus and enables IME.
286 iframe = document.getElementById("iframe_body");
287 iframe.style.display = "inline";
288 editor = iframe.contentDocument.getElementById("editor");
289 root = iframe.contentDocument.documentElement;
290 resetFocusToInput("initializing for iframe_body");
292 testTabKey(true, editor, true, prev, true,
293 true, "input#prev[readonly] -> body[contentediable=true]");
294 testTabKey(true, next, true, editor, true,
295 false, "body[contentediable=true] -> input#next[readonly]");
296 testTabKey(false, editor, true, next, true,
297 true, "input#next[readonly] -> body[contentediable=true]");
298 testTabKey(false, prev, true, editor, true,
299 false, "body[contenteditable=true] -> input#prev[readonly]");
301 prev.style.display = "none";
302 resetFocusToParentHTML("testing iframe_body");
303 testTabKey(true, editor, true, html, false,
304 true, "html of parent -> body[contentediable=true]");
305 testTabKey(false, html, false, editor, true,
306 false, "body[contenteditable=true] -> html of parent");
307 prev.style.display = "inline";
308 resetFocusToInput("after parent html <-> body[contenteditable=true]");
310 testMouseClick(editor, true, false, prev, true, true, "iframe_body");
312 testOnEditorFlagChange("body[contentediable=true]", false);
314 iframe.style.display = "none";
316 // When HTML/BODY elements are not editable, focus shouldn't be moved to
317 // the editable content directly.
318 iframe = document.getElementById("iframe_p");
319 iframe.style.display = "inline";
320 editor = iframe.contentDocument.getElementById("editor");
321 root = iframe.contentDocument.documentElement;
322 resetFocusToInput("initializing for iframe_p");
324 testTabKey(true, root, false, prev, true,
325 false, "input#prev[readonly] -> html (has p[contenteditable=true])");
326 testTabKey(true, editor, true, root, false,
327 true, "html (has p[contenteditable=true]) -> p[contentediable=true]");
328 testTabKey(true, next, true, editor, true,
329 false, "p[contentediable=true] -> input#next[readonly]");
330 testTabKey(false, editor, true, next, true,
331 true, "input#next[readonly] -> p[contentediable=true]");
332 testTabKey(false, root, false, editor, true,
333 false, "p[contenteditable=true] -> html (has p[contenteditable=true])");
334 testTabKey(false, prev, true, root, false,
335 false, "html (has p[contenteditable=true]) -> input#prev[readonly]");
336 prev.style.display = "none";
338 resetFocusToParentHTML("testing iframe_p");
339 testTabKey(true, root, false, html, false,
340 false, "html of parent -> html (has p[contentediable=true])");
341 testTabKey(false, html, false, root, false,
342 false, "html (has p[contentediable=true]) -> html of parent");
343 prev.style.display = "inline";
344 resetFocusToInput("after parent html <-> html (has p[contentediable=true])");
346 testMouseClick(root, false, true, prev, true, false, "iframe_p");
348 testOnEditorFlagChange("p[contenteditable=true]", false);
350 iframe.style.display = "none";
352 window.close();
355 </script>
356 </body>
358 </html>