CLOSED TREE: TraceMonkey merge head. (a=blockers)
[mozilla-central.git] / widget / tests / test_imestate.html
blob01859d352b3875f1a3f47b2e31cefc2765837cf8
1 <html style="ime-mode: disabled;">
2 <head>
3 <title>Test for IME state controling</title>
4 <script type="text/javascript"
5 src="chrome://mochikit/content/MochiKit/packed.js"></script>
6 <script type="text/javascript"
7 src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
8 <script type="text/javascript"
9 src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
10 <link rel="stylesheet" type="text/css"
11 href="chrome://mochikit/content/tests/SimpleTest/test.css" />
12 </head>
13 <body onload="setTimeout(runTests, 0);" style="ime-mode: disabled;">
14 <div id="display" style="ime-mode: disabled;">
15 <!-- input elements -->
16 <input type="text" id="text"/><br/>
17 <input type="text" id="text_readonly" readonly="readonly"/><br/>
18 <input type="password" id="password"/><br/>
19 <input type="password" id="password_readonly" readonly="readonly"/><br/>
20 <input type="checkbox" id="checkbox"/><br/>
21 <input type="radio" id="radio"/><br/>
22 <input type="submit" id="submit"/><br/>
23 <input type="reset" id="reset"/><br/>
24 <input type="file" id="file"/><br/>
25 <input type="button" id="ibutton"/><br/>
26 <input type="image" id="image" alt="image"/><br/>
28 <!-- html5 input elements -->
29 <input type="url" id="url"/><br/>
30 <input type="email" id="email"/><br/>
31 <input type="search" id="search"/><br/>
32 <input type="tel" id="tel"/><br/>
33 <input type="number" id="number"/><br/>
35 <!-- form controls -->
36 <button id="button">button</button><br/>
37 <textarea id="textarea">textarea</textarea><br/>
38 <textarea id="textarea_readonly" readonly="readonly">textarea[readonly]</textarea><br/>
39 <select id="select">
40 <option value="option" selected="selected"/>
41 </select><br/>
42 <select id="select_multiple" multiple="multiple">
43 <option value="option" selected="selected"/>
44 </select><br/>
45 <isindex id="isindex" prompt="isindex"/><br/>
47 <!-- a element -->
48 <a id="a_href" href="about:blank">a[href]</a><br/>
50 <!-- ime-mode test -->
51 <input type="text" id="ime_mode_auto" style="ime-mode: auto;"/><br/>
52 <input type="text" id="ime_mode_normal" style="ime-mode: normal;"/><br/>
53 <input type="text" id="ime_mode_active" style="ime-mode: active;"/><br/>
54 <input type="text" id="ime_mode_inactive" style="ime-mode: inactive;"/><br/>
55 <input type="text" id="ime_mode_disabled" style="ime-mode: disabled;"/><br/>
57 <input type="text" id="ime_mode_auto_url" style="ime-mode: auto;"/><br/>
58 <input type="text" id="ime_mode_normal_url" style="ime-mode: normal;"/><br/>
59 <input type="text" id="ime_mode_active_url" style="ime-mode: active;"/><br/>
60 <input type="text" id="ime_mode_inactive_url" style="ime-mode: inactive;"/><br/>
61 <input type="text" id="ime_mode_disabled_url" style="ime-mode: disabled;"/><br/>
63 <input type="text" id="ime_mode_auto_email" style="ime-mode: auto;"/><br/>
64 <input type="text" id="ime_mode_normal_email" style="ime-mode: normal;"/><br/>
65 <input type="text" id="ime_mode_active_email" style="ime-mode: active;"/><br/>
66 <input type="text" id="ime_mode_inactive_email" style="ime-mode: inactive;"/><br/>
67 <input type="text" id="ime_mode_disabled_email" style="ime-mode: disabled;"/><br/>
69 <input type="text" id="ime_mode_auto_search" style="ime-mode: auto;"/><br/>
70 <input type="text" id="ime_mode_normal_search" style="ime-mode: normal;"/><br/>
71 <input type="text" id="ime_mode_active_search" style="ime-mode: active;"/><br/>
72 <input type="text" id="ime_mode_inactive_search" style="ime-mode: inactive;"/><br/>
73 <input type="text" id="ime_mode_disabled_search" style="ime-mode: disabled;"/><br/>
75 <input type="text" id="ime_mode_auto_tel" style="ime-mode: auto;"/><br/>
76 <input type="text" id="ime_mode_normal_tel" style="ime-mode: normal;"/><br/>
77 <input type="text" id="ime_mode_active_tel" style="ime-mode: active;"/><br/>
78 <input type="text" id="ime_mode_inactive_tel" style="ime-mode: inactive;"/><br/>
79 <input type="text" id="ime_mode_disabled_tel" style="ime-mode: disabled;"/><br/>
81 <input type="text" id="ime_mode_auto_number" style="ime-mode: auto;"/><br/>
82 <input type="text" id="ime_mode_normal_number" style="ime-mode: normal;"/><br/>
83 <input type="text" id="ime_mode_active_number" style="ime-mode: active;"/><br/>
84 <input type="text" id="ime_mode_inactive_number" style="ime-mode: inactive;"/><br/>
85 <input type="text" id="ime_mode_disabled_number" style="ime-mode: disabled;"/><br/>
87 <input type="password" id="ime_mode_auto_p" style="ime-mode: auto;"/><br/>
88 <input type="password" id="ime_mode_normal_p" style="ime-mode: normal;"/><br/>
89 <input type="password" id="ime_mode_active_p" style="ime-mode: active;"/><br/>
90 <input type="password" id="ime_mode_inactive_p" style="ime-mode: inactive;"/><br/>
91 <input type="password" id="ime_mode_disabled_p" style="ime-mode: disabled;"/><br/>
92 <textarea id="ime_mode_auto_t" style="ime-mode: auto;">textarea</textarea><br/>
93 <textarea id="ime_mode_normal_t" style="ime-mode: normal;">textarea</textarea><br/>
94 <textarea id="ime_mode_active_t" style="ime-mode: active;">textarea</textarea><br/>
95 <textarea id="ime_mode_inactive_t" style="ime-mode: inactive;">textarea</textarea><br/>
96 <textarea id="ime_mode_disabled_t" style="ime-mode: disabled;">textarea</textarea><br/>
98 <!-- plugin -->
99 <object type="application/x-test" id="plugin"></object><br/>
101 <!-- contenteditable editor -->
102 <div id="contenteditableEditor" contenteditable="true"></div>
104 <!-- designMode editor -->
105 <iframe id="designModeEditor"
106 onload="document.getElementById('designModeEditor').contentDocument.designMode = 'on';"
107 src="data:text/html,<html><body></body></html>"></iframe><br/>
108 </div>
109 <div id="content" style="display: none">
111 </div>
112 <pre id="test">
113 </pre>
115 <script class="testbody" type="application/javascript">
117 SimpleTest.waitForExplicitFinish();
119 var gUtils = window.
120 QueryInterface(Components.interfaces.nsIInterfaceRequestor).
121 getInterface(Components.interfaces.nsIDOMWindowUtils);
122 var gUtils2 = gUtils.QueryInterface(Components.interfaces.nsIDOMWindowUtils_MOZILLA_2_0_BRANCH);
124 var gUtils2 = window.
125 QueryInterface(Components.interfaces.nsIInterfaceRequestor).
126 getInterface(Components.interfaces.nsIDOMWindowUtils_MOZILLA_2_0_BRANCH);
128 var gFM = Components.classes["@mozilla.org/focus-manager;1"].
129 getService(Components.interfaces.nsIFocusManager);
130 const kIMEEnabledSupported = navigator.platform.indexOf("Mac") == 0 ||
131 navigator.platform.indexOf("Win") == 0 ||
132 navigator.platform.indexOf("Linux") == 0;
134 // We support to control IME open state on Windows and Mac actually. However,
135 // we cannot test it on Mac if the current keyboard layout is not CJK. And also
136 // we cannot test it on Win32 if the system didn't be installed IME. So,
137 // currently we should not run the open state testing.
138 const kIMEOpenSupported = false;
140 function runBasicTest(aIsEditable, aInDesignMode, aDescription)
142 function test(aTest)
144 function moveFocus(aTest)
146 if (aInDesignMode) {
147 if (document.activeElement) {
148 document.activeElement.blur();
150 } else if (aIsEditable) {
151 document.getElementById("display").focus();
152 } else if (aTest.expectedEnabled == gUtils.IME_STATUS_ENABLED) {
153 document.getElementById("password").focus();
154 } else {
155 document.getElementById("text").focus();
157 var previousFocusedElement = gFM.focusedElement;
158 var element = document.getElementById(aTest.id);
159 if (element.contentDocument) {
160 element = element.contentDocument.documentElement;
162 element.focus();
163 var focusedElement = gFM.focusedElement;
164 if (focusedElement) {
165 var bindingParent = document.getBindingParent(focusedElement);
166 if (bindingParent) {
167 focusedElement = bindingParent;
170 if (aTest.focusable) {
171 is(focusedElement, element,
172 aDescription + ": " + aTest.description + ", focus didn't move");
173 return (element == focusedElement);
175 is(focusedElement, previousFocusedElement,
176 aDescription + ": " + aTest.description + ", focus moved as unexpected");
177 return (previousFocusedElement == focusedElement);
180 function testOpened(aTest, aOpened)
182 document.getElementById("text").focus();
183 gUtils.IMEIsOpen = aOpened;
184 if (!moveFocus(aTest)) {
185 return;
187 var message = aDescription + ": " + aTest.description +
188 ", wrong opened state";
189 is(gUtils.IMEIsOpen,
190 aTest.changeOpened ? aTest.expectedOpened : aOpened, message);
193 // IME Enabled state testing
194 var enabled = gUtils.IME_STATUS_ENABLED;
195 if (kIMEEnabledSupported) {
196 if (!moveFocus(aTest)) {
197 return;
199 enabled = gUtils.IMEStatus;
200 inputtype = gUtils2.focusedInputType;
201 is(enabled, aTest.expectedEnabled,
202 aDescription + ": " + aTest.description + ", wrong enabled state");
203 if (aTest.expectedType && !aInDesignMode) {
204 is(inputtype, aTest.expectedType,
205 aDescription + ": " + aTest.description + ", wrong input type");
206 } else if (aInDesignMode) {
207 is(inputtype, "",
208 aDescription + ": " + aTest.description + ", wrong input type")
212 if (!kIMEOpenSupported || enabled != gUtils.IME_STATUS_ENABLED ||
213 aTest.expectedEnabled != gUtils.IME_STATUS_ENABLED) {
214 return;
217 // IME Open state testing
218 testOpened(aTest, false);
219 testOpened(aTest, true);
222 if (kIMEEnabledSupported) {
223 // make sure there is an active element
224 document.getElementById("text").focus();
225 document.activeElement.blur();
226 is(gUtils.IMEStatus,
227 aInDesignMode ? gUtils.IME_STATUS_ENABLED : gUtils.IME_STATUS_DISABLED,
228 aDescription + ": unexpected enabled state when no element has focus");
231 // Form controls except text editable elements are "disable" in normal
232 // condition, however, if they are editable, they are "enabled".
233 // XXX Probably there are some bugs: If the form controls editable, they
234 // shouldn't be focusable.
235 const kEnabledStateOnNonEditableElement =
236 (aInDesignMode || aIsEditable) ? gUtils.IME_STATUS_ENABLED :
237 gUtils.IME_STATUS_DISABLED;
238 const kEnabledStateOnPasswordField =
239 aInDesignMode ? gUtils.IME_STATUS_ENABLED : gUtils.IME_STATUS_PASSWORD;
240 const kEnabledStateOnReadonlyField =
241 aInDesignMode ? gUtils.IME_STATUS_ENABLED : gUtils.IME_STATUS_DISABLED;
242 const kTests = [
243 { id: "text",
244 description: "input[type=text]",
245 focusable: !aInDesignMode,
246 expectedEnabled: gUtils.IME_STATUS_ENABLED,
247 expectedType: "text" },
248 { id: "text_readonly",
249 description: "input[type=text][readonly]",
250 focusable: !aInDesignMode,
251 expectedEnabled: kEnabledStateOnReadonlyField },
252 { id: "password",
253 description: "input[type=password]",
254 focusable: !aInDesignMode,
255 expectedEnabled: kEnabledStateOnPasswordField,
256 expectedType: "password" },
257 { id: "password_readonly",
258 description: "input[type=password][readonly]",
259 focusable: !aInDesignMode,
260 expectedEnabled: kEnabledStateOnReadonlyField },
261 { id: "checkbox",
262 description: "input[type=checkbox]",
263 focusable: !aInDesignMode,
264 expectedEnabled: kEnabledStateOnNonEditableElement },
265 { id: "radio",
266 description: "input[type=radio]",
267 focusable: !aInDesignMode,
268 expectedEnabled: kEnabledStateOnNonEditableElement },
269 { id: "submit",
270 description: "input[type=submit]",
271 focusable: !aInDesignMode,
272 expectedEnabled: kEnabledStateOnNonEditableElement },
273 { id: "reset",
274 description: "input[type=reset]",
275 focusable: !aInDesignMode,
276 expectedEnabled: kEnabledStateOnNonEditableElement },
277 { id: "file",
278 description: "input[type=file]",
279 focusable: !aInDesignMode,
280 expectedEnabled: kEnabledStateOnNonEditableElement },
281 { id: "button",
282 description: "input[type=button]",
283 focusable: !aInDesignMode,
284 expectedEnabled: kEnabledStateOnNonEditableElement },
285 { id: "image",
286 description: "input[type=image]",
287 focusable: !aInDesignMode,
288 expectedEnabled: kEnabledStateOnNonEditableElement },
289 { id: "url",
290 description: "input[type=url]",
291 focusable: !aInDesignMode,
292 expectedEnabled: gUtils.IME_STATUS_ENABLED,
293 expectedType: "url" },
294 { id: "email",
295 description: "input[type=email]",
296 focusable: !aInDesignMode,
297 expectedEnabled: gUtils.IME_STATUS_ENABLED,
298 expectedType: "email" },
299 { id: "search",
300 description: "input[type=search]",
301 focusable: !aInDesignMode,
302 expectedEnabled: gUtils.IME_STATUS_ENABLED,
303 expectedType: "search" },
304 { id: "tel",
305 description: "input[type=tel]",
306 focusable: !aInDesignMode,
307 expectedEnabled: gUtils.IME_STATUS_ENABLED,
308 expectedType: "tel" },
309 { id: "number",
310 description: "input[type=number]",
311 focusable: !aInDesignMode,
312 expectedEnabled: gUtils.IME_STATUS_ENABLED,
313 expectedType: "number" },
315 // form controls
316 { id: "button",
317 description: "button",
318 focusable: !aInDesignMode,
319 expectedEnabled: kEnabledStateOnNonEditableElement },
320 { id: "textarea",
321 description: "textarea",
322 focusable: !aInDesignMode,
323 expectedEnabled: gUtils.IME_STATUS_ENABLED },
324 { id: "textarea_readonly",
325 description: "textarea[readonly]",
326 focusable: !aInDesignMode,
327 expectedEnabled: kEnabledStateOnReadonlyField },
328 { id: "select",
329 description: "select (dropdown list)",
330 focusable: !aInDesignMode,
331 expectedEnabled: kEnabledStateOnNonEditableElement },
332 { id: "select_multiple",
333 description: "select (list box)",
334 focusable: !aInDesignMode,
335 expectedEnabled: kEnabledStateOnNonEditableElement },
337 // a element
338 { id: "a_href",
339 description: "a[href]",
340 focusable: !aIsEditable && !aInDesignMode,
341 expectedEnabled: kEnabledStateOnNonEditableElement },
343 // ime-mode
344 { id: "ime_mode_auto",
345 description: "input[type=text][style=\"ime-mode: auto;\"]",
346 focusable: !aInDesignMode,
347 expectedEnabled: gUtils.IME_STATUS_ENABLED },
348 { id: "ime_mode_normal",
349 description: "input[type=text][style=\"ime-mode: normal;\"]",
350 focusable: !aInDesignMode,
351 expectedEnabled: gUtils.IME_STATUS_ENABLED },
352 { id: "ime_mode_active",
353 description: "input[type=text][style=\"ime-mode: active;\"]",
354 expectedEnabled: gUtils.IME_STATUS_ENABLED,
355 focusable: !aInDesignMode,
356 changeOpened: true, expectedOpened: true },
357 { id: "ime_mode_inactive",
358 description: "input[type=text][style=\"ime-mode: inactive;\"]",
359 expectedEnabled: gUtils.IME_STATUS_ENABLED,
360 focusable: !aInDesignMode,
361 changeOpened: true, expectedOpened: false },
362 { id: "ime_mode_disabled",
363 description: "input[type=text][style=\"ime-mode: disabled;\"]",
364 focusable: !aInDesignMode,
365 expectedEnabled: kEnabledStateOnPasswordField },
367 { id: "ime_mode_auto_url",
368 description: "input[type=url][style=\"ime-mode: auto;\"]",
369 focusable: !aInDesignMode,
370 expectedEnabled: gUtils.IME_STATUS_ENABLED },
371 { id: "ime_mode_normal_url",
372 description: "input[type=url][style=\"ime-mode: normal;\"]",
373 focusable: !aInDesignMode,
374 expectedEnabled: gUtils.IME_STATUS_ENABLED },
375 { id: "ime_mode_active_url",
376 description: "input[type=url][style=\"ime-mode: active;\"]",
377 expectedEnabled: gUtils.IME_STATUS_ENABLED,
378 focusable: !aInDesignMode,
379 changeOpened: true, expectedOpened: true },
380 { id: "ime_mode_inactive_url",
381 description: "input[type=url][style=\"ime-mode: inactive;\"]",
382 expectedEnabled: gUtils.IME_STATUS_ENABLED,
383 focusable: !aInDesignMode,
384 changeOpened: true, expectedOpened: false },
385 { id: "ime_mode_disabled_url",
386 description: "input[type=url][style=\"ime-mode: disabled;\"]",
387 focusable: !aInDesignMode,
388 expectedEnabled: kEnabledStateOnPasswordField },
390 { id: "ime_mode_auto_email",
391 description: "input[type=email][style=\"ime-mode: auto;\"]",
392 focusable: !aInDesignMode,
393 expectedEnabled: gUtils.IME_STATUS_ENABLED },
394 { id: "ime_mode_normal_email",
395 description: "input[type=email][style=\"ime-mode: normal;\"]",
396 focusable: !aInDesignMode,
397 expectedEnabled: gUtils.IME_STATUS_ENABLED },
398 { id: "ime_mode_active_email",
399 description: "input[type=email][style=\"ime-mode: active;\"]",
400 expectedEnabled: gUtils.IME_STATUS_ENABLED,
401 focusable: !aInDesignMode,
402 changeOpened: true, expectedOpened: true },
403 { id: "ime_mode_inactive_email",
404 description: "input[type=email][style=\"ime-mode: inactive;\"]",
405 expectedEnabled: gUtils.IME_STATUS_ENABLED,
406 focusable: !aInDesignMode,
407 changeOpened: true, expectedOpened: false },
408 { id: "ime_mode_disabled_email",
409 description: "input[type=email][style=\"ime-mode: disabled;\"]",
410 focusable: !aInDesignMode,
411 expectedEnabled: kEnabledStateOnPasswordField },
413 { id: "ime_mode_auto_search",
414 description: "input[type=search][style=\"ime-mode: auto;\"]",
415 focusable: !aInDesignMode,
416 expectedEnabled: gUtils.IME_STATUS_ENABLED },
417 { id: "ime_mode_normal_search",
418 description: "input[type=search][style=\"ime-mode: normal;\"]",
419 focusable: !aInDesignMode,
420 expectedEnabled: gUtils.IME_STATUS_ENABLED },
421 { id: "ime_mode_active_search",
422 description: "input[type=search][style=\"ime-mode: active;\"]",
423 expectedEnabled: gUtils.IME_STATUS_ENABLED,
424 focusable: !aInDesignMode,
425 changeOpened: true, expectedOpened: true },
426 { id: "ime_mode_inactive_search",
427 description: "input[type=search][style=\"ime-mode: inactive;\"]",
428 expectedEnabled: gUtils.IME_STATUS_ENABLED,
429 focusable: !aInDesignMode,
430 changeOpened: true, expectedOpened: false },
431 { id: "ime_mode_disabled_search",
432 description: "input[type=search][style=\"ime-mode: disabled;\"]",
433 focusable: !aInDesignMode,
434 expectedEnabled: kEnabledStateOnPasswordField },
436 { id: "ime_mode_auto_tel",
437 description: "input[type=tel][style=\"ime-mode: auto;\"]",
438 focusable: !aInDesignMode,
439 expectedEnabled: gUtils.IME_STATUS_ENABLED },
440 { id: "ime_mode_normal_tel",
441 description: "input[type=tel][style=\"ime-mode: normal;\"]",
442 focusable: !aInDesignMode,
443 expectedEnabled: gUtils.IME_STATUS_ENABLED },
444 { id: "ime_mode_active_tel",
445 description: "input[type=tel][style=\"ime-mode: active;\"]",
446 expectedEnabled: gUtils.IME_STATUS_ENABLED,
447 focusable: !aInDesignMode,
448 changeOpened: true, expectedOpened: true },
449 { id: "ime_mode_inactive_tel",
450 description: "input[type=tel][style=\"ime-mode: inactive;\"]",
451 expectedEnabled: gUtils.IME_STATUS_ENABLED,
452 focusable: !aInDesignMode,
453 changeOpened: true, expectedOpened: false },
454 { id: "ime_mode_disabled_tel",
455 description: "input[type=tel][style=\"ime-mode: disabled;\"]",
456 focusable: !aInDesignMode,
457 expectedEnabled: kEnabledStateOnPasswordField },
459 { id: "ime_mode_auto_number",
460 description: "input[type=number][style=\"ime-mode: auto;\"]",
461 focusable: !aInDesignMode,
462 expectedEnabled: gUtils.IME_STATUS_ENABLED },
463 { id: "ime_mode_normal_number",
464 description: "input[type=number][style=\"ime-mode: normal;\"]",
465 focusable: !aInDesignMode,
466 expectedEnabled: gUtils.IME_STATUS_ENABLED },
467 { id: "ime_mode_active_number",
468 description: "input[type=number][style=\"ime-mode: active;\"]",
469 expectedEnabled: gUtils.IME_STATUS_ENABLED,
470 focusable: !aInDesignMode,
471 changeOpened: true, expectedOpened: true },
472 { id: "ime_mode_inactive_number",
473 description: "input[type=number][style=\"ime-mode: inactive;\"]",
474 expectedEnabled: gUtils.IME_STATUS_ENABLED,
475 focusable: !aInDesignMode,
476 changeOpened: true, expectedOpened: false },
477 { id: "ime_mode_disabled_number",
478 description: "input[type=number][style=\"ime-mode: disabled;\"]",
479 focusable: !aInDesignMode,
480 expectedEnabled: kEnabledStateOnPasswordField },
482 { id: "ime_mode_auto_p",
483 description: "input[type=password][style=\"ime-mode: auto;\"]",
484 focusable: !aInDesignMode,
485 expectedEnabled: kEnabledStateOnPasswordField },
486 { id: "ime_mode_normal_p",
487 description: "input[type=password][style=\"ime-mode: normal;\"]",
488 focusable: !aInDesignMode,
489 expectedEnabled: gUtils.IME_STATUS_ENABLED },
490 { id: "ime_mode_active_p",
491 description: "input[type=password][style=\"ime-mode: active;\"]",
492 expectedEnabled: gUtils.IME_STATUS_ENABLED,
493 focusable: !aInDesignMode,
494 changeOpened: true, expectedOpened: true },
495 { id: "ime_mode_inactive_p",
496 description: "input[type=password][style=\"ime-mode: inactive;\"]",
497 expectedEnabled: gUtils.IME_STATUS_ENABLED,
498 focusable: !aInDesignMode,
499 changeOpened: true, expectedOpened: false },
500 { id: "ime_mode_disabled_p",
501 description: "input[type=password][style=\"ime-mode: disabled;\"]",
502 focusable: !aInDesignMode,
503 expectedEnabled: kEnabledStateOnPasswordField },
504 { id: "ime_mode_auto",
505 description: "textarea[style=\"ime-mode: auto;\"]",
506 focusable: !aInDesignMode,
507 expectedEnabled: gUtils.IME_STATUS_ENABLED },
508 { id: "ime_mode_normal",
509 description: "textarea[style=\"ime-mode: normal;\"]",
510 focusable: !aInDesignMode,
511 expectedEnabled: gUtils.IME_STATUS_ENABLED },
512 { id: "ime_mode_active",
513 description: "textarea[style=\"ime-mode: active;\"]",
514 focusable: !aInDesignMode,
515 expectedEnabled: gUtils.IME_STATUS_ENABLED,
516 changeOpened: true, expectedOpened: true },
517 { id: "ime_mode_inactive",
518 description: "textarea[style=\"ime-mode: inactive;\"]",
519 focusable: !aInDesignMode,
520 expectedEnabled: gUtils.IME_STATUS_ENABLED,
521 changeOpened: true, expectedOpened: false },
522 { id: "ime_mode_disabled",
523 description: "textarea[style=\"ime-mode: disabled;\"]",
524 focusable: !aInDesignMode,
525 expectedEnabled: kEnabledStateOnPasswordField },
527 // HTML editors
528 { id: "contenteditableEditor",
529 description: "div[contenteditable=\"true\"]",
530 focusable: !aIsEditable && !aInDesignMode,
531 expectedEnabled: gUtils.IME_STATUS_ENABLED },
532 { id: "designModeEditor",
533 description: "designMode editor",
534 focusable: true,
535 expectedEnabled: gUtils.IME_STATUS_ENABLED },
538 for (var i = 0; i < kTests.length; i++) {
539 test(kTests[i]);
543 function runPluginTest()
545 if (!kIMEEnabledSupported) {
546 return;
549 if (navigator.platform.indexOf("Mac") == 0) {
550 // XXX on mac, currently, this test isn't passed because it doesn't return
551 // IME_STATUS_PLUGIN by its bug.
552 return;
555 var plugin = document.getElementById("plugin");
557 document.activeElement.blur();
558 is(gUtils.IMEStatus, gUtils.IME_STATUS_DISABLED,
559 "runPluginTest: unexpected enabled state when no element has focus");
561 plugin.focus();
562 is(gUtils.IMEStatus, gUtils.IME_STATUS_PLUGIN,
563 "runPluginTest: unexpected enabled state when plugin has focus");
565 plugin.blur();
566 is(gUtils.IMEStatus, gUtils.IME_STATUS_DISABLED,
567 "runPluginTest: unexpected enabled state when plugin has focus");
569 plugin.focus();
570 is(gUtils.IMEStatus, gUtils.IME_STATUS_PLUGIN,
571 "runPluginTest: unexpected enabled state when plugin has focus #2");
573 var parent = plugin.parentNode;
574 parent.removeChild(plugin);
575 is(gUtils.IMEStatus, gUtils.IME_STATUS_DISABLED,
576 "runPluginTest: unexpected enabled state when plugin is removed from tree");
578 document.getElementById("text").focus();
579 is(gUtils.IMEStatus, gUtils.IME_STATUS_ENABLED,
580 "runPluginTest: unexpected enabled state when input[type=text] has focus");
583 function runTypeChangingTest()
585 if (!kIMEEnabledSupported)
586 return;
588 const kInputControls = [
589 { id: "text",
590 type: "text", expected: gUtils.IME_STATUS_ENABLED,
591 description: "[type=\"text\"]" },
592 { id: "text_readonly",
593 type: "text", expected: gUtils.IME_STATUS_DISABLED, isReadonly: true,
594 description: "[type=\"text\"][readonly]" },
595 { id: "password",
596 type: "password", expected: gUtils.IME_STATUS_PASSWORD,
597 description: "[type=\"password\"]" },
598 { id: "password_readonly",
599 type: "password", expected: gUtils.IME_STATUS_DISABLED, isReadonly: true,
600 description: "[type=\"password\"][readonly]" },
601 { id: "checkbox",
602 type: "checkbox", expected: gUtils.IME_STATUS_DISABLED,
603 description: "[type=\"checkbox\"]" },
604 { id: "radio",
605 type: "radio", expected: gUtils.IME_STATUS_DISABLED,
606 description: "[type=\"radio\"]" },
607 { id: "submit",
608 type: "submit", expected: gUtils.IME_STATUS_DISABLED,
609 description: "[type=\"submit\"]" },
610 { id: "reset",
611 type: "reset", expected: gUtils.IME_STATUS_DISABLED,
612 description: "[type=\"reset\"]" },
613 { id: "file",
614 type: "file", expected: gUtils.IME_STATUS_DISABLED,
615 description: "[type=\"file\"]" },
616 { id: "ibutton",
617 type: "button", expected: gUtils.IME_STATUS_DISABLED,
618 description: "[type=\"button\"]" },
619 { id: "image",
620 type: "image", expected: gUtils.IME_STATUS_DISABLED,
621 description: "[type=\"image\"]" },
622 { id: "url",
623 type: "url", expected: gUtils.IME_STATUS_ENABLED,
624 description: "[type=\"url\"]" },
625 { id: "email",
626 type: "email", expected: gUtils.IME_STATUS_ENABLED,
627 description: "[type=\"email\"]" },
628 { id: "search",
629 type: "search", expected: gUtils.IME_STATUS_ENABLED,
630 description: "[type=\"search\"]" },
631 { id: "tel",
632 type: "tel", expected: gUtils.IME_STATUS_ENABLED,
633 description: "[type=\"tel\"]" },
634 { id: "number",
635 type: "number", expected: gUtils.IME_STATUS_ENABLED,
636 description: "[type=\"number\"]" },
637 { id: "ime_mode_auto",
638 type: "text", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
639 description: "[type=\"text\"][ime-mode: auto;]" },
640 { id: "ime_mode_normal",
641 type: "text", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
642 description: "[type=\"text\"][ime-mode: normal;]" },
643 { id: "ime_mode_active",
644 type: "text", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
645 description: "[type=\"text\"][ime-mode: active;]" },
646 { id: "ime_mode_inactive",
647 type: "text", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
648 description: "[type=\"text\"][ime-mode: inactive;]" },
649 { id: "ime_mode_disabled",
650 type: "text", expected: gUtils.IME_STATUS_PASSWORD, imeMode: true,
651 description: "[type=\"text\"][ime-mode: disabled;]" },
653 { id: "ime_mode_auto_url",
654 type: "url", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
655 description: "[type=\"url\"][ime-mode: auto;]" },
656 { id: "ime_mode_normal_url",
657 type: "url", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
658 description: "[type=\"url\"][ime-mode: normal;]" },
659 { id: "ime_mode_active_url",
660 type: "url", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
661 description: "[type=\"url\"][ime-mode: active;]" },
662 { id: "ime_mode_inactive_url",
663 type: "url", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
664 description: "[type=\"url\"][ime-mode: inactive;]" },
665 { id: "ime_mode_disabled_url",
666 type: "url", expected: gUtils.IME_STATUS_PASSWORD, imeMode: true,
667 description: "[type=\"url\"][ime-mode: disabled;]" },
669 { id: "ime_mode_auto_email",
670 type: "email", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
671 description: "[type=\"email\"][ime-mode: auto;]" },
672 { id: "ime_mode_normal_email",
673 type: "email", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
674 description: "[type=\"email\"][ime-mode: normal;]" },
675 { id: "ime_mode_active_email",
676 type: "email", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
677 description: "[type=\"email\"][ime-mode: active;]" },
678 { id: "ime_mode_inactive_email",
679 type: "email", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
680 description: "[type=\"email\"][ime-mode: inactive;]" },
681 { id: "ime_mode_disabled_email",
682 type: "email", expected: gUtils.IME_STATUS_PASSWORD, imeMode: true,
683 description: "[type=\"email\"][ime-mode: disabled;]" },
685 { id: "ime_mode_auto_search",
686 type: "search", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
687 description: "[type=\"search\"][ime-mode: auto;]" },
688 { id: "ime_mode_normal_search",
689 type: "search", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
690 description: "[type=\"search\"][ime-mode: normal;]" },
691 { id: "ime_mode_active_search",
692 type: "search", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
693 description: "[type=\"search\"][ime-mode: active;]" },
694 { id: "ime_mode_inactive_search",
695 type: "search", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
696 description: "[type=\"search\"][ime-mode: inactive;]" },
697 { id: "ime_mode_disabled_search",
698 type: "search", expected: gUtils.IME_STATUS_PASSWORD, imeMode: true,
699 description: "[type=\"search\"][ime-mode: disabled;]" },
701 { id: "ime_mode_auto_tel",
702 type: "tel", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
703 description: "[type=\"tel\"][ime-mode: auto;]" },
704 { id: "ime_mode_normal_tel",
705 type: "tel", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
706 description: "[type=\"tel\"][ime-mode: normal;]" },
707 { id: "ime_mode_active_tel",
708 type: "tel", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
709 description: "[type=\"tel\"][ime-mode: active;]" },
710 { id: "ime_mode_inactive_tel",
711 type: "tel", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
712 description: "[type=\"tel\"][ime-mode: inactive;]" },
713 { id: "ime_mode_disabled_tel",
714 type: "tel", expected: gUtils.IME_STATUS_PASSWORD, imeMode: true,
715 description: "[type=\"tel\"][ime-mode: disabled;]" },
717 { id: "ime_mode_auto_number",
718 type: "number", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
719 description: "[type=\"number\"][ime-mode: auto;]" },
720 { id: "ime_mode_normal_number",
721 type: "number", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
722 description: "[type=\"number\"][ime-mode: normal;]" },
723 { id: "ime_mode_active_number",
724 type: "number", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
725 description: "[type=\"number\"][ime-mode: active;]" },
726 { id: "ime_mode_inactive_number",
727 type: "number", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
728 description: "[type=\"number\"][ime-mode: inactive;]" },
729 { id: "ime_mode_disabled_number",
730 type: "number", expected: gUtils.IME_STATUS_PASSWORD, imeMode: true,
731 description: "[type=\"number\"][ime-mode: disabled;]" },
733 { id: "ime_mode_auto_p",
734 type: "password", expected: gUtils.IME_STATUS_PASSWORD, imeMode: true,
735 description: "[type=\"password\"][ime-mode: auto;]" },
736 { id: "ime_mode_normal_p",
737 type: "password", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
738 description: "[type=\"password\"][ime-mode: normal;]" },
739 { id: "ime_mode_active_p",
740 type: "password", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
741 description: "[type=\"password\"][ime-mode: active;]" },
742 { id: "ime_mode_inactive_p",
743 type: "password", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
744 description: "[type=\"password\"][ime-mode: inactive;]" },
745 { id: "ime_mode_disabled_p",
746 type: "password", expected: gUtils.IME_STATUS_PASSWORD, imeMode: true,
747 description: "[type=\"password\"][ime-mode: disabled;]" }
750 const kInputTypes = [
751 { type: "", expected: gUtils.IME_STATUS_ENABLED },
752 { type: "text", expected: gUtils.IME_STATUS_ENABLED },
753 { type: "password", expected: gUtils.IME_STATUS_PASSWORD },
754 { type: "checkbox", expected: gUtils.IME_STATUS_DISABLED },
755 { type: "radio", expected: gUtils.IME_STATUS_DISABLED },
756 { type: "submit", expected: gUtils.IME_STATUS_DISABLED },
757 { type: "reset", expected: gUtils.IME_STATUS_DISABLED },
758 { type: "file", expected: gUtils.IME_STATUS_DISABLED },
759 { type: "button", expected: gUtils.IME_STATUS_DISABLED },
760 { type: "image", expected: gUtils.IME_STATUS_DISABLED },
761 { type: "url", expected: gUtils.IME_STATUS_ENABLED },
762 { type: "email", expected: gUtils.IME_STATUS_ENABLED },
763 { type: "search", expected: gUtils.IME_STATUS_ENABLED },
764 { type: "tel", expected: gUtils.IME_STATUS_ENABLED },
765 { type: "number", expected: gUtils.IME_STATUS_ENABLED }
768 function getExpectedIMEEnabled(aNewType, aInputControl)
770 if (aNewType.expected == gUtils.IME_STATUS_DISABLED ||
771 aInputControl.isReadonly)
772 return gUtils.IME_STATUS_DISABLED;
773 return aInputControl.imeMode ? aInputControl.expected : aNewType.expected;
776 const kOpenedState = [ true, false ];
778 for (var i = 0; i < kOpenedState.length; i++) {
779 const kOpened = kOpenedState[i];
780 for (var j = 0; j < kInputControls.length; j++) {
781 const kInput = kInputControls[j];
782 var e = document.getElementById(kInput.id);
783 e.focus();
784 for (var k = 0; k < kInputTypes.length; k++) {
785 const kType = kInputTypes[k];
786 var typeChangingDescription =
787 "\"" + e.getAttribute("type") + "\" to \"" + kInput.type + "\"";
788 e.setAttribute("type", kInput.type);
789 is(gUtils.IMEStatus, kInput.expected,
790 "type attr changing test (IMEStatus): " + typeChangingDescription +
791 " (" + kInput.description + ")");
792 is(gUtils2.focusedInputType, kInput.type,
793 "type attr changing test (type): " + typeChangingDescription +
794 " (" + kInput.description + ")");
796 const kTestOpenState = kIMEOpenSupported &&
797 gUtils.IMEStatus == gUtils.IME_STATUS_ENABLED &&
798 getExpectedIMEEnabled(kType, kInput) == gUtils.IME_STATUS_ENABLED;
799 if (kTestOpenState) {
800 gUtils.IMEIsOpen = kOpened;
803 typeChangingDescription =
804 "\"" + e.getAttribute("type") + "\" to \"" + kType.type + "\"";
805 if (kType.type != "")
806 e.setAttribute("type", kType.type);
807 else
808 e.removeAttribute("type");
810 is(gUtils.IMEStatus, getExpectedIMEEnabled(kType, kInput),
811 "type attr changing test (IMEStatus): " + typeChangingDescription +
812 " (" + kInput.description + ")");
813 is(gUtils2.focusedInputType, kType.type,
814 "type attr changing test (type): " + typeChangingDescription +
815 " (" + kInput.description + ")");
816 if (kTestOpenState && gUtils.IMEStatus == gUtils.IME_STATUS_ENABLED) {
817 is(gUtils.IMEIsOpen, kOpened,
818 "type attr changing test (open state is changed): " +
819 typeChangingDescription + " (" + kInput.description + ")");
822 // reset the type to default
823 e.setAttribute("type", kInput.type);
825 if (!kIMEOpenSupported)
826 break;
830 function runReadonlyChangingTest()
832 if (!kIMEEnabledSupported)
833 return;
835 const kInputControls = [
836 { id: "text",
837 type: "text", expected: gUtils.IME_STATUS_ENABLED },
838 { id: "password",
839 type: "password", expected: gUtils.IME_STATUS_PASSWORD },
840 { id: "url",
841 type: "url", expected: gUtils.IME_STATUS_ENABLED },
842 { id: "email",
843 type: "email", expected: gUtils.IME_STATUS_ENABLED },
844 { id: "search",
845 type: "search", expected: gUtils.IME_STATUS_ENABLED },
846 { id: "tel",
847 type: "tel", expected: gUtils.IME_STATUS_ENABLED },
848 { id: "number",
849 type: "number", expected: gUtils.IME_STATUS_ENABLED },
850 { id: "textarea",
851 type: "textarea", expected: gUtils.IME_STATUS_ENABLED }
853 const kOpenedState = [ true, false ];
855 for (var i = 0; i < kOpenedState.length; i++) {
856 const kOpened = kOpenedState[i];
857 for (var j = 0; j < kInputControls.length; j++) {
858 const kInput = kInputControls[j];
859 var e = document.getElementById(kInput.id);
860 e.focus();
861 if (kIMEOpenSupported && gUtils.IMEStatus == gUtils.IME_STATUS_ENABLED) {
862 gUtils.IMEIsOpen = kOpened;
864 e.setAttribute("readonly", "readonly");
865 is(gUtils.IMEStatus, gUtils.IME_STATUS_DISABLED,
866 "readonly attr setting test: type=" + kInput.type);
867 e.removeAttribute("readonly");
868 is(gUtils.IMEStatus, kInput.expected,
869 "readonly attr removing test: type=" + kInput.type);
870 if (kIMEOpenSupported && gUtils.IMEStatus == gUtils.IME_STATUS_ENABLED) {
871 is(gUtils.IMEIsOpen, kOpened,
872 "readonly attr removing test (open state is changed): type=" +
873 kInput.type);
876 if (!kIMEOpenSupported)
877 break;
881 function runComplexContenteditableTests()
883 if (!kIMEEnabledSupported) {
884 return;
887 var description = "runReadonlyChangingOnContenteditable: ";
889 var container = document.getElementById("display");
890 var button = document.getElementById("button");
892 // the editor has focus directly.
893 container.setAttribute("contenteditable", "true");
894 container.focus();
896 is(gFM.focusedElement, container,
897 description + "The editor doesn't get focus");
898 is(gUtils.IMEStatus, gUtils.IME_STATUS_ENABLED,
899 description + "IME isn't enabled on HTML editor");
900 const kReadonly =
901 Components.interfaces.nsIPlaintextEditor.eEditorReadonlyMask;
902 var editor =
903 window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
904 getInterface(Components.interfaces.nsIWebNavigation).
905 QueryInterface(Components.interfaces.nsIEditorDocShell).editor;
906 var flags = editor.flags;
907 editor.flags = flags | kReadonly;
908 is(gFM.focusedElement, container,
909 description + "The editor loses focus by flag change");
910 is(gUtils.IMEStatus, gUtils.IME_STATUS_DISABLED,
911 description + "IME is still enabled on readonly HTML editor");
912 editor.flags = flags;
913 is(gFM.focusedElement, container,
914 description + "The editor loses focus by flag change #2");
915 is(gUtils.IMEStatus, gUtils.IME_STATUS_ENABLED,
916 description + "IME is still disabled, the editor isn't readonly now");
917 container.removeAttribute("contenteditable");
918 todo_is(gFM.focusedElement, null,
919 description + "The container still has focus, the editor has been no editable");
920 todo_is(gUtils.IMEStatus, gUtils.IME_STATUS_DISABLED,
921 description + "IME is still enabled on the editor, the editor has been no editable");
923 // a button which is in the editor has focus
924 button.focus();
925 is(gFM.focusedElement, button,
926 description + "The button doesn't get focus");
927 is(gUtils.IMEStatus, gUtils.IME_STATUS_DISABLED,
928 description + "IME is enabled on the button");
929 container.setAttribute("contenteditable", "true");
930 is(gFM.focusedElement, button,
931 description + "The button loses focus, the container is editable now");
932 todo_is(gUtils.IMEStatus, gUtils.IME_STATUS_ENABLED,
933 description + "IME is still disabled on the button, the container is editable now");
934 editor =
935 window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
936 getInterface(Components.interfaces.nsIWebNavigation).
937 QueryInterface(Components.interfaces.nsIEditorDocShell).editor;
938 flags = editor.flags;
939 editor.flags = flags | kReadonly;
940 is(gFM.focusedElement, button,
941 description + "The button loses focus by changing editor flags");
942 is(gUtils.IMEStatus, gUtils.IME_STATUS_DISABLED,
943 description + "IME is still enabled on the button, the container is readonly now");
944 editor.flags = flags;
945 is(gFM.focusedElement, button,
946 description + "The button loses focus by changing editor flags #2");
947 is(gUtils.IMEStatus, gUtils.IME_STATUS_ENABLED,
948 description + "IME is still disabled on the button, the container isn't readonly now");
949 container.removeAttribute("contenteditable");
950 is(gFM.focusedElement, button,
951 description + "The button loses focus, the container has been no editable");
952 todo_is(gUtils.IMEStatus, gUtils.IME_STATUS_DISABLED,
953 description + "IME is still enabled on the button, the container has been no editable");
955 description = "testOnIndependentEditor: ";
956 function testOnIndependentEditor(aEditor, aEditorDescription)
958 var isReadonly = aEditor.readOnly;
959 var expectedState =
960 aEditor.readOnly ? gUtils.IME_STATUS_DISABLED : gUtils.IME_STATUS_ENABLED;
961 var unexpectedStateDescription =
962 expectedState != gUtils.IME_STATUS_ENABLED ? "enabled" : "disabled";
963 aEditor.focus();
964 is(gFM.focusedElement, aEditor,
965 description + "The " + aEditorDescription + " doesn't get focus");
966 is(gUtils.IMEStatus, expectedState,
967 description + "IME is " + unexpectedStateDescription +
968 " on the " + aEditorDescription);
969 container.setAttribute("contenteditable", "true");
970 is(gFM.focusedElement, aEditor,
971 description + "The " + aEditorDescription +
972 " loses focus, the container is editable now");
973 is(gUtils.IMEStatus, expectedState,
974 description + "IME becomes " + unexpectedStateDescription +
975 " on the " + aEditorDescription + ", the container is editable now");
976 editor =
977 window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
978 getInterface(Components.interfaces.nsIWebNavigation).
979 QueryInterface(Components.interfaces.nsIEditorDocShell).editor;
980 flags = editor.flags;
981 editor.flags = flags | kReadonly;
982 is(gFM.focusedElement, aEditor,
983 description + "The " + aEditorDescription +
984 " loses focus by changing editor flags");
985 is(gUtils.IMEStatus, expectedState,
986 description + "IME becomes " + unexpectedStateDescription + " on the " +
987 aEditorDescription + ", the container is readonly now");
988 editor.flags = flags;
989 is(gFM.focusedElement, aEditor,
990 description + "The " + aEditorDescription +
991 " loses focus by changing editor flags #2");
992 is(gUtils.IMEStatus, expectedState,
993 description + "IME becomes " + unexpectedStateDescription + " on the " +
994 aEditorDescription + ", the container isn't readonly now");
995 container.removeAttribute("contenteditable");
996 is(gFM.focusedElement, aEditor,
997 description + "The " + aEditorDescription +
998 " loses focus, the container has been no editable");
999 is(gUtils.IMEStatus, expectedState,
1000 description + "IME becomes " + unexpectedStateDescription + " on the " +
1001 aEditorDescription + ", the container has been no editable");
1004 // a textarea which is in the editor has focus
1005 testOnIndependentEditor(document.getElementById("textarea"),
1006 "textarea");
1007 // a readonly textarea which is in the editor has focus
1008 testOnIndependentEditor(document.getElementById("textarea_readonly"),
1009 "textarea[readonly]");
1010 // an input field which is in the editor has focus
1011 testOnIndependentEditor(document.getElementById("text"),
1012 "input[type=\"text\"]");
1013 // a readonly input field which is in the editor has focus
1014 testOnIndependentEditor(document.getElementById("text_readonly"),
1015 "input[type=\"text\"][readonly]");
1017 description = "testOnOutsideOfEditor: ";
1018 function testOnOutsideOfEditor(aFocusNode, aFocusNodeDescription, aEditor)
1020 if (aFocusNode) {
1021 aFocusNode.focus();
1022 is(gFM.focusedElement, aFocusNode,
1023 description + "The " + aFocusNodeDescription + " doesn't get focus");
1024 } else {
1025 if (document.activeElement) {
1026 document.activeElement.blur();
1028 is(gFM.focusedElement, null,
1029 description + "Unexpected element has focus");
1031 var expectedState =
1032 aFocusNode ? gUtils.IMEStatus : gUtils.IME_STATUS_DISABLED;
1033 var unexpectedStateDescription =
1034 expectedState != gUtils.IME_STATUS_ENABLED ? "enabled" : "disabled";
1036 aEditor.setAttribute("contenteditable", "true");
1037 is(gFM.focusedElement, aFocusNode,
1038 description + "The " + aFocusNodeDescription +
1039 " loses focus, a HTML editor is editable now");
1040 is(gUtils.IMEStatus, expectedState,
1041 description + "IME becomes " + unexpectedStateDescription +
1042 " on the " + aFocusNodeDescription +
1043 ", the HTML editor is editable now");
1044 editor =
1045 window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
1046 getInterface(Components.interfaces.nsIWebNavigation).
1047 QueryInterface(Components.interfaces.nsIEditorDocShell).editor;
1048 flags = editor.flags;
1049 editor.flags = flags | kReadonly;
1050 is(gFM.focusedElement, aFocusNode,
1051 description + aFocusNodeDescription +
1052 " loses focus by changing HTML editor flags");
1053 is(gUtils.IMEStatus, expectedState,
1054 description + "IME becomes " + unexpectedStateDescription + " on " +
1055 aFocusNodeDescription + ", the HTML editor is readonly now");
1056 editor.flags = flags;
1057 is(gFM.focusedElement, aFocusNode,
1058 description + aFocusNodeDescription +
1059 " loses focus by changing HTML editor flags #2");
1060 is(gUtils.IMEStatus, expectedState,
1061 description + "IME becomes " + unexpectedStateDescription + " on " +
1062 aFocusNodeDescription + ", the HTML editor isn't readonly now");
1063 container.removeAttribute("contenteditable");
1064 is(gFM.focusedElement, aFocusNode,
1065 description + aFocusNodeDescription +
1066 " loses focus, the HTML editor has been no editable");
1067 is(gUtils.IMEStatus, expectedState,
1068 description + "IME becomes " + unexpectedStateDescription + " on " +
1069 aFocusNodeDescription + ", the HTML editor has been no editable");
1072 var div = document.getElementById("contenteditableEditor");
1073 // a textarea which is outside of the editor has focus
1074 testOnOutsideOfEditor(document.getElementById("textarea"), "textarea", div);
1075 // a readonly textarea which is outside of the editor has focus
1076 testOnOutsideOfEditor(document.getElementById("textarea_readonly"),
1077 "textarea[readonly]", div);
1078 // an input field which is outside of the editor has focus
1079 testOnOutsideOfEditor(document.getElementById("text"),
1080 "input[type=\"text\"]", div);
1081 // a readonly input field which outside of the editor has focus
1082 testOnOutsideOfEditor(document.getElementById("text_readonly"),
1083 "input[type=\"text\"][readonly]", div);
1084 // a readonly input field which outside of the editor has focus
1085 testOnOutsideOfEditor(document.getElementById("button"), "button", div);
1086 // nobody has focus.
1087 testOnOutsideOfEditor(null, "nobody", div);
1090 function runEditorFlagChangeTests()
1092 if (!kIMEEnabledSupported) {
1093 return;
1096 var description = "runEditorFlagChangeTests: ";
1098 var container = document.getElementById("display");
1100 // the editor has focus directly.
1101 container.setAttribute("contenteditable", "true");
1102 container.focus();
1104 is(gFM.focusedElement, container,
1105 description + "The editor doesn't get focus");
1106 is(gUtils.IMEStatus, gUtils.IME_STATUS_ENABLED,
1107 description + "IME isn't enabled on HTML editor");
1108 const kIMEStateChangeFlags =
1109 Components.interfaces.nsIPlaintextEditor.eEditorPasswordMask |
1110 Components.interfaces.nsIPlaintextEditor.eEditorReadonlyMask |
1111 Components.interfaces.nsIPlaintextEditor.eEditorDisabledMask;
1112 var editor =
1113 window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
1114 getInterface(Components.interfaces.nsIWebNavigation).
1115 QueryInterface(Components.interfaces.nsIEditorDocShell).editor;
1116 var editorIMESupport =
1117 editor.QueryInterface(Components.interfaces.nsIEditorIMESupport);
1118 var flags = editor.flags;
1120 // start composition
1121 synthesizeComposition(true);
1123 // input characters
1124 synthesizeText(
1125 { "composition":
1126 { "string": "\u3078\u3093\u3057\u3093",
1127 "clauses":
1129 { "length": 4, "attr": gUtils.COMPOSITION_ATTR_RAWINPUT }
1132 "caret": { "start": 4, "length": 0 }
1135 editor.flags &= ~kIMEStateChangeFlags;
1136 ok(editorIMESupport.composing,
1137 description + "#1 IME composition was committed unexpectedly");
1138 is(gUtils.IMEStatus, gUtils.IME_STATUS_ENABLED,
1139 description + "#1 IME isn't enabled on HTML editor");
1141 editor.flags |= ~kIMEStateChangeFlags;
1142 ok(editorIMESupport.composing,
1143 description + "#2 IME composition was committed unexpectedly");
1144 is(gUtils.IMEStatus, gUtils.IME_STATUS_ENABLED,
1145 description + "#2 IME isn't enabled on HTML editor");
1147 editor.flags = flags;
1148 ok(editorIMESupport.composing,
1149 description + "#3 IME composition was committed unexpectedly");
1150 is(gUtils.IMEStatus, gUtils.IME_STATUS_ENABLED,
1151 description + "#3 IME isn't enabled on HTML editor");
1153 // cancel the composition
1154 synthesizeText(
1155 { "composition":
1156 { "string": "",
1157 "clauses":
1159 { "length": 0, "attr": 0 }
1162 "caret": { "start": 0, "length": 0 }
1165 synthesizeComposition(false);
1167 container.removeAttribute("contenteditable");
1170 function runEditableSubframeTests()
1172 window.open("window_imestate_iframes.html", "_blank",
1173 "width=600,height=600");
1176 function runTestPasswordFieldOnDialog()
1178 if (!kIMEEnabledSupported) {
1179 return;
1182 if (document.activeElement) {
1183 document.activeElement.blur();
1186 var dialog;
1188 function WindowObserver()
1190 Components.classes["@mozilla.org/observer-service;1"].
1191 getService(Components.interfaces.nsIObserverService).
1192 addObserver(this, "domwindowopened", false);
1195 WindowObserver.prototype = {
1196 QueryInterface: function (iid)
1198 if (iid.equals(Components.interfaces.nsIObserver) ||
1199 iid.equals(Components.interfaces.nsISupports)) {
1200 return this;
1204 observe: function (subject, topic, data)
1206 if (topic === "domwindowopened") {
1207 ok(true, "dialog window is created");
1208 dialog = subject.QueryInterface(Components.interfaces.nsIDOMWindow);
1209 dialog.addEventListener("load", onPasswordDialogLoad, false);
1214 var observer = new WindowObserver();
1215 var arg1 = new Object(), arg2 = new Object();
1216 Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
1217 getService(Components.interfaces.nsIPromptService).
1218 promptPassword(window, "title", "text", arg1, "msg", arg2);
1220 ok(true, "password dialog was closed");
1222 Components.classes["@mozilla.org/observer-service;1"].
1223 getService(Components.interfaces.nsIObserverService).
1224 removeObserver(observer, "domwindowopened");
1226 var passwordField;
1228 function onPasswordDialogLoad()
1230 ok(true, "onPasswordDialogLoad is called");
1231 dialog.removeEventListener("load", onPasswordDialogLoad, false);
1232 passwordField = dialog.document.getElementById("password1Textbox");
1233 passwordField.addEventListener("focus", onPasswordFieldFocus, false);
1236 function onPasswordFieldFocus()
1238 ok(true, "onPasswordFieldFocus is called");
1239 passwordField.removeEventListener("focus", onPasswordFieldFocus, false);
1240 var utils = dialog.
1241 QueryInterface(Components.interfaces.nsIInterfaceRequestor).
1242 getInterface(Components.interfaces.nsIDOMWindowUtils);
1243 is(utils.IMEStatus, utils.IME_STATUS_PASSWORD,
1244 "IME isn't disabled on a password field of password dialog");
1245 synthesizeKey("VK_ESCAPE", { }, dialog);
1249 function runTests()
1251 if (!kIMEEnabledSupported && !kIMEOpenSupported)
1252 return;
1254 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
1256 // test for normal contents.
1257 runBasicTest(false, false, "Testing of normal contents");
1259 // test for plugin contents
1260 runPluginTest();
1262 var container = document.getElementById("display");
1263 // test for contentEditable="true"
1264 container.setAttribute("contenteditable", "true");
1265 runBasicTest(true, false, "Testing [contentEditable=\"true\"]");
1267 // test for contentEditable="false"
1268 container.setAttribute("contenteditable", "false");
1269 runBasicTest(false, false, "Testing [contentEditable=\"false\"]");
1271 // test for removing contentEditable
1272 container.setAttribute("contenteditable", "true");
1273 container.removeAttribute("contenteditable");
1274 runBasicTest(false, false, "Testing after contentEditable to be removed");
1276 // test designMode
1277 document.designMode = "on";
1278 runBasicTest(true, true, "Testing designMode=\"on\"");
1279 document.designMode = "off";
1280 document.getElementById("text").focus();
1281 runBasicTest(false, false, "Testing designMode=\"off\"");
1283 // changing input[type] values
1284 // XXX currently, type attribute changing doesn't work fine. bug 559728.
1285 // runTypeChangingTest();
1287 // changing readonly attribute
1288 runReadonlyChangingTest();
1290 // complex contenteditable editor's tests
1291 runComplexContenteditableTests();
1293 // test whether the IME state and composition are not changed unexpectedly
1294 runEditorFlagChangeTests();
1296 // test password field on dialog
1297 // XXX temporary disable against failure
1298 //runTestPasswordFieldOnDialog();
1300 runASyncTests();
1303 function runASyncTests()
1305 // The tests must call onFinish() method.
1306 runEditableSubframeTests();
1309 function onFinish()
1311 SimpleTest.finish();
1314 </script>
1315 </body>
1317 </html>