widget/tests/test_imestate.html

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 <html style="ime-mode: disabled;">
michael@0 2 <head>
michael@0 3 <title>Test for IME state controling</title>
michael@0 4 <script type="text/javascript"
michael@0 5 src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
michael@0 6 <script type="text/javascript"
michael@0 7 src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
michael@0 8 <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/ChromeUtils.js"></script>
michael@0 9 <link rel="stylesheet" type="text/css"
michael@0 10 href="chrome://mochikit/content/tests/SimpleTest/test.css" />
michael@0 11 </head>
michael@0 12 <body onload="setTimeout(runTests, 0);" style="ime-mode: disabled;">
michael@0 13 <div id="display" style="ime-mode: disabled;">
michael@0 14 <!-- input elements -->
michael@0 15 <input type="text" id="text"/><br/>
michael@0 16 <input type="text" id="text_readonly" readonly="readonly"/><br/>
michael@0 17 <input type="password" id="password"/><br/>
michael@0 18 <input type="password" id="password_readonly" readonly="readonly"/><br/>
michael@0 19 <input type="checkbox" id="checkbox"/><br/>
michael@0 20 <input type="radio" id="radio"/><br/>
michael@0 21 <input type="submit" id="submit"/><br/>
michael@0 22 <input type="reset" id="reset"/><br/>
michael@0 23 <input type="file" id="file"/><br/>
michael@0 24 <input type="button" id="ibutton"/><br/>
michael@0 25 <input type="image" id="image" alt="image"/><br/>
michael@0 26
michael@0 27 <!-- html5 input elements -->
michael@0 28 <input type="url" id="url"/><br/>
michael@0 29 <input type="email" id="email"/><br/>
michael@0 30 <input type="search" id="search"/><br/>
michael@0 31 <input type="tel" id="tel"/><br/>
michael@0 32 <input type="number" id="number"/><br/>
michael@0 33
michael@0 34 <!-- form controls -->
michael@0 35 <button id="button">button</button><br/>
michael@0 36 <textarea id="textarea">textarea</textarea><br/>
michael@0 37 <textarea id="textarea_readonly" readonly="readonly">textarea[readonly]</textarea><br/>
michael@0 38 <select id="select">
michael@0 39 <option value="option" selected="selected"/>
michael@0 40 </select><br/>
michael@0 41 <select id="select_multiple" multiple="multiple">
michael@0 42 <option value="option" selected="selected"/>
michael@0 43 </select><br/>
michael@0 44 <isindex id="isindex" prompt="isindex"/><br/>
michael@0 45
michael@0 46 <!-- a element -->
michael@0 47 <a id="a_href" href="about:blank">a[href]</a><br/>
michael@0 48
michael@0 49 <!-- ime-mode test -->
michael@0 50 <input type="text" id="ime_mode_auto" style="ime-mode: auto;"/><br/>
michael@0 51 <input type="text" id="ime_mode_normal" style="ime-mode: normal;"/><br/>
michael@0 52 <input type="text" id="ime_mode_active" style="ime-mode: active;"/><br/>
michael@0 53 <input type="text" id="ime_mode_inactive" style="ime-mode: inactive;"/><br/>
michael@0 54 <input type="text" id="ime_mode_disabled" style="ime-mode: disabled;"/><br/>
michael@0 55
michael@0 56 <input type="text" id="ime_mode_auto_url" style="ime-mode: auto;"/><br/>
michael@0 57 <input type="text" id="ime_mode_normal_url" style="ime-mode: normal;"/><br/>
michael@0 58 <input type="text" id="ime_mode_active_url" style="ime-mode: active;"/><br/>
michael@0 59 <input type="text" id="ime_mode_inactive_url" style="ime-mode: inactive;"/><br/>
michael@0 60 <input type="text" id="ime_mode_disabled_url" style="ime-mode: disabled;"/><br/>
michael@0 61
michael@0 62 <input type="text" id="ime_mode_auto_email" style="ime-mode: auto;"/><br/>
michael@0 63 <input type="text" id="ime_mode_normal_email" style="ime-mode: normal;"/><br/>
michael@0 64 <input type="text" id="ime_mode_active_email" style="ime-mode: active;"/><br/>
michael@0 65 <input type="text" id="ime_mode_inactive_email" style="ime-mode: inactive;"/><br/>
michael@0 66 <input type="text" id="ime_mode_disabled_email" style="ime-mode: disabled;"/><br/>
michael@0 67
michael@0 68 <input type="text" id="ime_mode_auto_search" style="ime-mode: auto;"/><br/>
michael@0 69 <input type="text" id="ime_mode_normal_search" style="ime-mode: normal;"/><br/>
michael@0 70 <input type="text" id="ime_mode_active_search" style="ime-mode: active;"/><br/>
michael@0 71 <input type="text" id="ime_mode_inactive_search" style="ime-mode: inactive;"/><br/>
michael@0 72 <input type="text" id="ime_mode_disabled_search" style="ime-mode: disabled;"/><br/>
michael@0 73
michael@0 74 <input type="text" id="ime_mode_auto_tel" style="ime-mode: auto;"/><br/>
michael@0 75 <input type="text" id="ime_mode_normal_tel" style="ime-mode: normal;"/><br/>
michael@0 76 <input type="text" id="ime_mode_active_tel" style="ime-mode: active;"/><br/>
michael@0 77 <input type="text" id="ime_mode_inactive_tel" style="ime-mode: inactive;"/><br/>
michael@0 78 <input type="text" id="ime_mode_disabled_tel" style="ime-mode: disabled;"/><br/>
michael@0 79
michael@0 80 <input type="text" id="ime_mode_auto_number" style="ime-mode: auto;"/><br/>
michael@0 81 <input type="text" id="ime_mode_normal_number" style="ime-mode: normal;"/><br/>
michael@0 82 <input type="text" id="ime_mode_active_number" style="ime-mode: active;"/><br/>
michael@0 83 <input type="text" id="ime_mode_inactive_number" style="ime-mode: inactive;"/><br/>
michael@0 84 <input type="text" id="ime_mode_disabled_number" style="ime-mode: disabled;"/><br/>
michael@0 85
michael@0 86 <input type="password" id="ime_mode_auto_p" style="ime-mode: auto;"/><br/>
michael@0 87 <input type="password" id="ime_mode_normal_p" style="ime-mode: normal;"/><br/>
michael@0 88 <input type="password" id="ime_mode_active_p" style="ime-mode: active;"/><br/>
michael@0 89 <input type="password" id="ime_mode_inactive_p" style="ime-mode: inactive;"/><br/>
michael@0 90 <input type="password" id="ime_mode_disabled_p" style="ime-mode: disabled;"/><br/>
michael@0 91 <textarea id="ime_mode_auto_t" style="ime-mode: auto;">textarea</textarea><br/>
michael@0 92 <textarea id="ime_mode_normal_t" style="ime-mode: normal;">textarea</textarea><br/>
michael@0 93 <textarea id="ime_mode_active_t" style="ime-mode: active;">textarea</textarea><br/>
michael@0 94 <textarea id="ime_mode_inactive_t" style="ime-mode: inactive;">textarea</textarea><br/>
michael@0 95 <textarea id="ime_mode_disabled_t" style="ime-mode: disabled;">textarea</textarea><br/>
michael@0 96
michael@0 97 <!-- plugin -->
michael@0 98 <object type="application/x-test" id="plugin"></object><br/>
michael@0 99
michael@0 100 <!-- contenteditable editor -->
michael@0 101 <div id="contenteditableEditor" contenteditable="true"></div>
michael@0 102
michael@0 103 <!-- designMode editor -->
michael@0 104 <iframe id="designModeEditor"
michael@0 105 onload="document.getElementById('designModeEditor').contentDocument.designMode = 'on';"
michael@0 106 src="data:text/html,<html><body></body></html>"></iframe><br/>
michael@0 107 </div>
michael@0 108 <div id="content" style="display: none">
michael@0 109
michael@0 110 </div>
michael@0 111 <pre id="test">
michael@0 112 </pre>
michael@0 113
michael@0 114 <script class="testbody" type="application/javascript">
michael@0 115
michael@0 116 SimpleTest.waitForExplicitFinish();
michael@0 117
michael@0 118 function hitEventLoop(aFunc, aTimes)
michael@0 119 {
michael@0 120 if (--aTimes) {
michael@0 121 setTimeout(hitEventLoop, 0, aFunc, aTimes);
michael@0 122 } else {
michael@0 123 setTimeout(aFunc, 20);
michael@0 124 }
michael@0 125 }
michael@0 126
michael@0 127 var gUtils = window.
michael@0 128 QueryInterface(Components.interfaces.nsIInterfaceRequestor).
michael@0 129 getInterface(Components.interfaces.nsIDOMWindowUtils);
michael@0 130 var gFM = Components.classes["@mozilla.org/focus-manager;1"].
michael@0 131 getService(Components.interfaces.nsIFocusManager);
michael@0 132 const kIMEEnabledSupported = navigator.platform.indexOf("Mac") == 0 ||
michael@0 133 navigator.platform.indexOf("Win") == 0 ||
michael@0 134 navigator.platform.indexOf("Linux") == 0;
michael@0 135
michael@0 136 // We support to control IME open state on Windows and Mac actually. However,
michael@0 137 // we cannot test it on Mac if the current keyboard layout is not CJK. And also
michael@0 138 // we cannot test it on Win32 if the system didn't be installed IME. So,
michael@0 139 // currently we should not run the open state testing.
michael@0 140 const kIMEOpenSupported = false;
michael@0 141
michael@0 142 function runBasicTest(aIsEditable, aInDesignMode, aDescription)
michael@0 143 {
michael@0 144 function test(aTest)
michael@0 145 {
michael@0 146 function moveFocus(aTest, aFocusEventHandler)
michael@0 147 {
michael@0 148 if (aInDesignMode) {
michael@0 149 if (document.activeElement) {
michael@0 150 document.activeElement.blur();
michael@0 151 }
michael@0 152 } else if (aIsEditable) {
michael@0 153 document.getElementById("display").focus();
michael@0 154 } else if (aTest.expectedEnabled == gUtils.IME_STATUS_ENABLED) {
michael@0 155 document.getElementById("password").focus();
michael@0 156 } else {
michael@0 157 document.getElementById("text").focus();
michael@0 158 }
michael@0 159 var previousFocusedElement = gFM.focusedElement;
michael@0 160 var element = document.getElementById(aTest.id);
michael@0 161 var focusEventTarget = element;
michael@0 162 var subDocument = null;
michael@0 163 if (element.contentDocument) {
michael@0 164 focusEventTarget = element.contentDocument;
michael@0 165 subDocument = element.contentDocument;
michael@0 166 element = element.contentDocument.documentElement;
michael@0 167 }
michael@0 168
michael@0 169 focusEventTarget.addEventListener("focus", aFocusEventHandler, true);
michael@0 170 document.addEventListener("MozIMEFocusIn", aFocusEventHandler, true);
michael@0 171 document.addEventListener("MozIMEFocusOut", aFocusEventHandler, true);
michael@0 172 if (subDocument) {
michael@0 173 subDocument.addEventListener("MozIMEFocusIn", aFocusEventHandler, true);
michael@0 174 subDocument.addEventListener("MozIMEFocusOut", aFocusEventHandler, true);
michael@0 175 }
michael@0 176
michael@0 177 element.focus();
michael@0 178
michael@0 179 focusEventTarget.removeEventListener("focus", aFocusEventHandler, true);
michael@0 180 document.removeEventListener("MozIMEFocusIn", aFocusEventHandler, true);
michael@0 181 document.removeEventListener("MozIMEFocusOut", aFocusEventHandler, true);
michael@0 182 if (element.contentDocument) {
michael@0 183 subDocument.removeEventListener("MozIMEFocusIn", aFocusEventHandler, true);
michael@0 184 subDocument.removeEventListener("MozIMEFocusOut", aFocusEventHandler, true);
michael@0 185 }
michael@0 186
michael@0 187 var focusedElement = gFM.focusedElement;
michael@0 188 if (focusedElement) {
michael@0 189 var bindingParent = document.getBindingParent(focusedElement);
michael@0 190 if (bindingParent) {
michael@0 191 focusedElement = bindingParent;
michael@0 192 }
michael@0 193 }
michael@0 194 if (aTest.focusable) {
michael@0 195 is(focusedElement, element,
michael@0 196 aDescription + ": " + aTest.description + ", focus didn't move");
michael@0 197 return (element == focusedElement);
michael@0 198 }
michael@0 199 is(focusedElement, previousFocusedElement,
michael@0 200 aDescription + ": " + aTest.description + ", focus moved as unexpected");
michael@0 201 return (previousFocusedElement == focusedElement);
michael@0 202 }
michael@0 203
michael@0 204 function testOpened(aTest, aOpened)
michael@0 205 {
michael@0 206 document.getElementById("text").focus();
michael@0 207 gUtils.IMEIsOpen = aOpened;
michael@0 208 if (!moveFocus(aTest)) {
michael@0 209 return;
michael@0 210 }
michael@0 211 var message = aDescription + ": " + aTest.description +
michael@0 212 ", wrong opened state";
michael@0 213 is(gUtils.IMEIsOpen,
michael@0 214 aTest.changeOpened ? aTest.expectedOpened : aOpened, message);
michael@0 215 }
michael@0 216
michael@0 217 // IME Enabled state testing
michael@0 218 var enabled = gUtils.IME_STATUS_ENABLED;
michael@0 219 if (kIMEEnabledSupported) {
michael@0 220 var focusEventCount = 0;
michael@0 221 var mozIMEFocusInCount = 0;
michael@0 222 var mozIMEFocusOutCount = 0;
michael@0 223 var IMEHasFocus = false;
michael@0 224
michael@0 225 function onFocus(aEvent)
michael@0 226 {
michael@0 227 switch (aEvent.type) {
michael@0 228 case "focus":
michael@0 229 focusEventCount++;
michael@0 230 is(gUtils.IMEStatus, aTest.expectedEnabled,
michael@0 231 aDescription + ": " + aTest.description + ", wrong enabled state at focus event");
michael@0 232 break;
michael@0 233 case "MozIMEFocusIn":
michael@0 234 mozIMEFocusInCount++;
michael@0 235 IMEHasFocus = true;
michael@0 236 is(gUtils.IMEStatus, aTest.expectedEnabled,
michael@0 237 aDescription + ": " + aTest.description +
michael@0 238 ", MozIMEFocusIn event must be fired after IME state is updated");
michael@0 239 break;
michael@0 240 case "MozIMEFocusOut":
michael@0 241 mozIMEFocusOutCount++;
michael@0 242 IMEHasFocus = false;
michael@0 243 var changingStatus = !(aIsEditable && aTest.expectedEnabled == gUtils.IME_STATUS_ENABLED);
michael@0 244 if (aTest.toDesignModeEditor) {
michael@0 245 is(gUtils.IME_STATUS_ENABLED, aTest.expectedEnabled,
michael@0 246 aDescription + ": " + aTest.description +
michael@0 247 ", MozIMEFocusOut event must be fired after IME state is updated");
michael@0 248 } else if (changingStatus) {
michael@0 249 isnot(gUtils.IMEStatus, aTest.expectedEnabled,
michael@0 250 aDescription + ": " + aTest.description +
michael@0 251 ", MozIMEFocusOut event must be fired before IME state is updated");
michael@0 252 } else {
michael@0 253 is(gUtils.IMEStatus, aTest.expectedEnabled,
michael@0 254 aDescription + ": " + aTest.description +
michael@0 255 ", MozIMEFocusOut event must be fired with expected IME state if the state isn't being changed");
michael@0 256 }
michael@0 257 break;
michael@0 258 }
michael@0 259 }
michael@0 260
michael@0 261 if (!moveFocus(aTest, onFocus)) {
michael@0 262 return;
michael@0 263 }
michael@0 264
michael@0 265 if (aTest.focusable) {
michael@0 266 if (!aTest.focusEventNotFired) {
michael@0 267 ok(focusEventCount > 0,
michael@0 268 aDescription + ": " + aTest.description + ", focus event is never fired");
michael@0 269 if (aTest.expectedEnabled == gUtils.IME_STATUS_ENABLED || aTest.expectedEnabled == gUtils.IME_STATUS_PASSWORD) {
michael@0 270 ok(mozIMEFocusInCount > 0,
michael@0 271 aDescription + ": " + aTest.description + ", MozIMEFocusIn event should be fired");
michael@0 272 if (aInDesignMode && !aTest.toDesignModeEditor) {
michael@0 273 is(mozIMEFocusOutCount, 0,
michael@0 274 aDescription + ": " + aTest.description +
michael@0 275 ", MozIMEFocusOut event shouldn't be fired in designMode since focus isn't moved from another editor");
michael@0 276 } else {
michael@0 277 ok(mozIMEFocusOutCount > 0,
michael@0 278 aDescription + ": " + aTest.description +
michael@0 279 ", MozIMEFocusOut event should be fired for the previous focused editor");
michael@0 280 }
michael@0 281 ok(IMEHasFocus,
michael@0 282 aDescription + ": " + aTest.description +
michael@0 283 ", The latest MozIMEFocus* event must be MozIMEFocusIn");
michael@0 284 } else {
michael@0 285 is(mozIMEFocusInCount, 0,
michael@0 286 aDescription + ": " + aTest.description +
michael@0 287 ", MozIMEFocusIn event shouldn't be fired");
michael@0 288 ok(mozIMEFocusOutCount > 0,
michael@0 289 aDescription + ": " + aTest.description +
michael@0 290 ", MozIMEFocusOut event should be fired");
michael@0 291 ok(!IMEHasFocus,
michael@0 292 aDescription + ": " + aTest.description +
michael@0 293 ", The latest MozIMEFocus* event must be MozIMEFocusOut");
michael@0 294 }
michael@0 295 } else {
michael@0 296 todo(focusEventCount > 0,
michael@0 297 aDescription + ": " + aTest.description + ", focus event should be fired");
michael@0 298 }
michael@0 299 } else {
michael@0 300 is(mozIMEFocusInCount, 0,
michael@0 301 aDescription + ": " + aTest.description +
michael@0 302 ", MozIMEFocusIn event shouldn't be fired at testing non-focusable element");
michael@0 303 is(mozIMEFocusOutCount, 0,
michael@0 304 aDescription + ": " + aTest.description +
michael@0 305 ", MozIMEFocusOut event shouldn't be fired at testing non-focusable element");
michael@0 306 }
michael@0 307
michael@0 308 enabled = gUtils.IMEStatus;
michael@0 309 inputtype = gUtils.focusedInputType;
michael@0 310 is(enabled, aTest.expectedEnabled,
michael@0 311 aDescription + ": " + aTest.description + ", wrong enabled state");
michael@0 312 if (aTest.expectedType && !aInDesignMode) {
michael@0 313 is(inputtype, aTest.expectedType,
michael@0 314 aDescription + ": " + aTest.description + ", wrong input type");
michael@0 315 } else if (aInDesignMode) {
michael@0 316 is(inputtype, "",
michael@0 317 aDescription + ": " + aTest.description + ", wrong input type")
michael@0 318 }
michael@0 319 }
michael@0 320
michael@0 321 if (!kIMEOpenSupported || enabled != gUtils.IME_STATUS_ENABLED ||
michael@0 322 aTest.expectedEnabled != gUtils.IME_STATUS_ENABLED) {
michael@0 323 return;
michael@0 324 }
michael@0 325
michael@0 326 // IME Open state testing
michael@0 327 testOpened(aTest, false);
michael@0 328 testOpened(aTest, true);
michael@0 329 }
michael@0 330
michael@0 331 if (kIMEEnabledSupported) {
michael@0 332 // make sure there is an active element
michael@0 333 document.getElementById("text").focus();
michael@0 334 document.activeElement.blur();
michael@0 335 is(gUtils.IMEStatus,
michael@0 336 aInDesignMode ? gUtils.IME_STATUS_ENABLED : gUtils.IME_STATUS_DISABLED,
michael@0 337 aDescription + ": unexpected enabled state when no element has focus");
michael@0 338 }
michael@0 339
michael@0 340 // Form controls except text editable elements are "disable" in normal
michael@0 341 // condition, however, if they are editable, they are "enabled".
michael@0 342 // XXX Probably there are some bugs: If the form controls editable, they
michael@0 343 // shouldn't be focusable.
michael@0 344 const kEnabledStateOnNonEditableElement =
michael@0 345 (aInDesignMode || aIsEditable) ? gUtils.IME_STATUS_ENABLED :
michael@0 346 gUtils.IME_STATUS_DISABLED;
michael@0 347 const kEnabledStateOnPasswordField =
michael@0 348 aInDesignMode ? gUtils.IME_STATUS_ENABLED : gUtils.IME_STATUS_PASSWORD;
michael@0 349 const kEnabledStateOnReadonlyField =
michael@0 350 aInDesignMode ? gUtils.IME_STATUS_ENABLED : gUtils.IME_STATUS_DISABLED;
michael@0 351 const kTests = [
michael@0 352 { id: "text",
michael@0 353 description: "input[type=text]",
michael@0 354 focusable: !aInDesignMode,
michael@0 355 expectedEnabled: gUtils.IME_STATUS_ENABLED,
michael@0 356 expectedType: "text" },
michael@0 357 { id: "text_readonly",
michael@0 358 description: "input[type=text][readonly]",
michael@0 359 focusable: !aInDesignMode,
michael@0 360 expectedEnabled: kEnabledStateOnReadonlyField },
michael@0 361 { id: "password",
michael@0 362 description: "input[type=password]",
michael@0 363 focusable: !aInDesignMode,
michael@0 364 expectedEnabled: kEnabledStateOnPasswordField,
michael@0 365 expectedType: "password" },
michael@0 366 { id: "password_readonly",
michael@0 367 description: "input[type=password][readonly]",
michael@0 368 focusable: !aInDesignMode,
michael@0 369 expectedEnabled: kEnabledStateOnReadonlyField },
michael@0 370 { id: "checkbox",
michael@0 371 description: "input[type=checkbox]",
michael@0 372 focusable: !aInDesignMode,
michael@0 373 focusEventNotFired: aIsEditable && !aInDesignMode,
michael@0 374 expectedEnabled: kEnabledStateOnNonEditableElement },
michael@0 375 { id: "radio",
michael@0 376 description: "input[type=radio]",
michael@0 377 focusable: !aInDesignMode,
michael@0 378 focusEventNotFired: aIsEditable && !aInDesignMode,
michael@0 379 expectedEnabled: kEnabledStateOnNonEditableElement },
michael@0 380 { id: "submit",
michael@0 381 description: "input[type=submit]",
michael@0 382 focusable: !aInDesignMode,
michael@0 383 expectedEnabled: kEnabledStateOnNonEditableElement },
michael@0 384 { id: "reset",
michael@0 385 description: "input[type=reset]",
michael@0 386 focusable: !aInDesignMode,
michael@0 387 expectedEnabled: kEnabledStateOnNonEditableElement },
michael@0 388 { id: "file",
michael@0 389 description: "input[type=file]",
michael@0 390 focusable: !aInDesignMode,
michael@0 391 focusEventNotFired: aIsEditable && !aInDesignMode,
michael@0 392 expectedEnabled: kEnabledStateOnNonEditableElement },
michael@0 393 { id: "button",
michael@0 394 description: "input[type=button]",
michael@0 395 focusable: !aInDesignMode,
michael@0 396 expectedEnabled: kEnabledStateOnNonEditableElement },
michael@0 397 { id: "image",
michael@0 398 description: "input[type=image]",
michael@0 399 focusable: !aInDesignMode,
michael@0 400 expectedEnabled: kEnabledStateOnNonEditableElement },
michael@0 401 { id: "url",
michael@0 402 description: "input[type=url]",
michael@0 403 focusable: !aInDesignMode,
michael@0 404 expectedEnabled: gUtils.IME_STATUS_ENABLED,
michael@0 405 expectedType: "url" },
michael@0 406 { id: "email",
michael@0 407 description: "input[type=email]",
michael@0 408 focusable: !aInDesignMode,
michael@0 409 expectedEnabled: gUtils.IME_STATUS_ENABLED,
michael@0 410 expectedType: "email" },
michael@0 411 { id: "search",
michael@0 412 description: "input[type=search]",
michael@0 413 focusable: !aInDesignMode,
michael@0 414 expectedEnabled: gUtils.IME_STATUS_ENABLED,
michael@0 415 expectedType: "search" },
michael@0 416 { id: "tel",
michael@0 417 description: "input[type=tel]",
michael@0 418 focusable: !aInDesignMode,
michael@0 419 expectedEnabled: gUtils.IME_STATUS_ENABLED,
michael@0 420 expectedType: "tel" },
michael@0 421 { id: "number",
michael@0 422 description: "input[type=number]",
michael@0 423 focusable: !aInDesignMode,
michael@0 424 expectedEnabled: gUtils.IME_STATUS_ENABLED,
michael@0 425 expectedType: "number" },
michael@0 426
michael@0 427 // form controls
michael@0 428 { id: "button",
michael@0 429 description: "button",
michael@0 430 focusable: !aInDesignMode,
michael@0 431 expectedEnabled: kEnabledStateOnNonEditableElement },
michael@0 432 { id: "textarea",
michael@0 433 description: "textarea",
michael@0 434 focusable: !aInDesignMode,
michael@0 435 expectedEnabled: gUtils.IME_STATUS_ENABLED },
michael@0 436 { id: "textarea_readonly",
michael@0 437 description: "textarea[readonly]",
michael@0 438 focusable: !aInDesignMode,
michael@0 439 expectedEnabled: kEnabledStateOnReadonlyField },
michael@0 440 { id: "select",
michael@0 441 description: "select (dropdown list)",
michael@0 442 focusable: !aInDesignMode,
michael@0 443 focusEventNotFired: aIsEditable && !aInDesignMode,
michael@0 444 expectedEnabled: kEnabledStateOnNonEditableElement },
michael@0 445 { id: "select_multiple",
michael@0 446 description: "select (list box)",
michael@0 447 focusable: !aInDesignMode,
michael@0 448 focusEventNotFired: aIsEditable && !aInDesignMode,
michael@0 449 expectedEnabled: kEnabledStateOnNonEditableElement },
michael@0 450
michael@0 451 // a element
michael@0 452 { id: "a_href",
michael@0 453 description: "a[href]",
michael@0 454 focusable: !aIsEditable && !aInDesignMode,
michael@0 455 expectedEnabled: kEnabledStateOnNonEditableElement },
michael@0 456
michael@0 457 // ime-mode
michael@0 458 { id: "ime_mode_auto",
michael@0 459 description: "input[type=text][style=\"ime-mode: auto;\"]",
michael@0 460 focusable: !aInDesignMode,
michael@0 461 expectedEnabled: gUtils.IME_STATUS_ENABLED },
michael@0 462 { id: "ime_mode_normal",
michael@0 463 description: "input[type=text][style=\"ime-mode: normal;\"]",
michael@0 464 focusable: !aInDesignMode,
michael@0 465 expectedEnabled: gUtils.IME_STATUS_ENABLED },
michael@0 466 { id: "ime_mode_active",
michael@0 467 description: "input[type=text][style=\"ime-mode: active;\"]",
michael@0 468 expectedEnabled: gUtils.IME_STATUS_ENABLED,
michael@0 469 focusable: !aInDesignMode,
michael@0 470 changeOpened: true, expectedOpened: true },
michael@0 471 { id: "ime_mode_inactive",
michael@0 472 description: "input[type=text][style=\"ime-mode: inactive;\"]",
michael@0 473 expectedEnabled: gUtils.IME_STATUS_ENABLED,
michael@0 474 focusable: !aInDesignMode,
michael@0 475 changeOpened: true, expectedOpened: false },
michael@0 476 { id: "ime_mode_disabled",
michael@0 477 description: "input[type=text][style=\"ime-mode: disabled;\"]",
michael@0 478 focusable: !aInDesignMode,
michael@0 479 expectedEnabled: kEnabledStateOnPasswordField },
michael@0 480
michael@0 481 { id: "ime_mode_auto_url",
michael@0 482 description: "input[type=url][style=\"ime-mode: auto;\"]",
michael@0 483 focusable: !aInDesignMode,
michael@0 484 expectedEnabled: gUtils.IME_STATUS_ENABLED },
michael@0 485 { id: "ime_mode_normal_url",
michael@0 486 description: "input[type=url][style=\"ime-mode: normal;\"]",
michael@0 487 focusable: !aInDesignMode,
michael@0 488 expectedEnabled: gUtils.IME_STATUS_ENABLED },
michael@0 489 { id: "ime_mode_active_url",
michael@0 490 description: "input[type=url][style=\"ime-mode: active;\"]",
michael@0 491 expectedEnabled: gUtils.IME_STATUS_ENABLED,
michael@0 492 focusable: !aInDesignMode,
michael@0 493 changeOpened: true, expectedOpened: true },
michael@0 494 { id: "ime_mode_inactive_url",
michael@0 495 description: "input[type=url][style=\"ime-mode: inactive;\"]",
michael@0 496 expectedEnabled: gUtils.IME_STATUS_ENABLED,
michael@0 497 focusable: !aInDesignMode,
michael@0 498 changeOpened: true, expectedOpened: false },
michael@0 499 { id: "ime_mode_disabled_url",
michael@0 500 description: "input[type=url][style=\"ime-mode: disabled;\"]",
michael@0 501 focusable: !aInDesignMode,
michael@0 502 expectedEnabled: kEnabledStateOnPasswordField },
michael@0 503
michael@0 504 { id: "ime_mode_auto_email",
michael@0 505 description: "input[type=email][style=\"ime-mode: auto;\"]",
michael@0 506 focusable: !aInDesignMode,
michael@0 507 expectedEnabled: gUtils.IME_STATUS_ENABLED },
michael@0 508 { id: "ime_mode_normal_email",
michael@0 509 description: "input[type=email][style=\"ime-mode: normal;\"]",
michael@0 510 focusable: !aInDesignMode,
michael@0 511 expectedEnabled: gUtils.IME_STATUS_ENABLED },
michael@0 512 { id: "ime_mode_active_email",
michael@0 513 description: "input[type=email][style=\"ime-mode: active;\"]",
michael@0 514 expectedEnabled: gUtils.IME_STATUS_ENABLED,
michael@0 515 focusable: !aInDesignMode,
michael@0 516 changeOpened: true, expectedOpened: true },
michael@0 517 { id: "ime_mode_inactive_email",
michael@0 518 description: "input[type=email][style=\"ime-mode: inactive;\"]",
michael@0 519 expectedEnabled: gUtils.IME_STATUS_ENABLED,
michael@0 520 focusable: !aInDesignMode,
michael@0 521 changeOpened: true, expectedOpened: false },
michael@0 522 { id: "ime_mode_disabled_email",
michael@0 523 description: "input[type=email][style=\"ime-mode: disabled;\"]",
michael@0 524 focusable: !aInDesignMode,
michael@0 525 expectedEnabled: kEnabledStateOnPasswordField },
michael@0 526
michael@0 527 { id: "ime_mode_auto_search",
michael@0 528 description: "input[type=search][style=\"ime-mode: auto;\"]",
michael@0 529 focusable: !aInDesignMode,
michael@0 530 expectedEnabled: gUtils.IME_STATUS_ENABLED },
michael@0 531 { id: "ime_mode_normal_search",
michael@0 532 description: "input[type=search][style=\"ime-mode: normal;\"]",
michael@0 533 focusable: !aInDesignMode,
michael@0 534 expectedEnabled: gUtils.IME_STATUS_ENABLED },
michael@0 535 { id: "ime_mode_active_search",
michael@0 536 description: "input[type=search][style=\"ime-mode: active;\"]",
michael@0 537 expectedEnabled: gUtils.IME_STATUS_ENABLED,
michael@0 538 focusable: !aInDesignMode,
michael@0 539 changeOpened: true, expectedOpened: true },
michael@0 540 { id: "ime_mode_inactive_search",
michael@0 541 description: "input[type=search][style=\"ime-mode: inactive;\"]",
michael@0 542 expectedEnabled: gUtils.IME_STATUS_ENABLED,
michael@0 543 focusable: !aInDesignMode,
michael@0 544 changeOpened: true, expectedOpened: false },
michael@0 545 { id: "ime_mode_disabled_search",
michael@0 546 description: "input[type=search][style=\"ime-mode: disabled;\"]",
michael@0 547 focusable: !aInDesignMode,
michael@0 548 expectedEnabled: kEnabledStateOnPasswordField },
michael@0 549
michael@0 550 { id: "ime_mode_auto_tel",
michael@0 551 description: "input[type=tel][style=\"ime-mode: auto;\"]",
michael@0 552 focusable: !aInDesignMode,
michael@0 553 expectedEnabled: gUtils.IME_STATUS_ENABLED },
michael@0 554 { id: "ime_mode_normal_tel",
michael@0 555 description: "input[type=tel][style=\"ime-mode: normal;\"]",
michael@0 556 focusable: !aInDesignMode,
michael@0 557 expectedEnabled: gUtils.IME_STATUS_ENABLED },
michael@0 558 { id: "ime_mode_active_tel",
michael@0 559 description: "input[type=tel][style=\"ime-mode: active;\"]",
michael@0 560 expectedEnabled: gUtils.IME_STATUS_ENABLED,
michael@0 561 focusable: !aInDesignMode,
michael@0 562 changeOpened: true, expectedOpened: true },
michael@0 563 { id: "ime_mode_inactive_tel",
michael@0 564 description: "input[type=tel][style=\"ime-mode: inactive;\"]",
michael@0 565 expectedEnabled: gUtils.IME_STATUS_ENABLED,
michael@0 566 focusable: !aInDesignMode,
michael@0 567 changeOpened: true, expectedOpened: false },
michael@0 568 { id: "ime_mode_disabled_tel",
michael@0 569 description: "input[type=tel][style=\"ime-mode: disabled;\"]",
michael@0 570 focusable: !aInDesignMode,
michael@0 571 expectedEnabled: kEnabledStateOnPasswordField },
michael@0 572
michael@0 573 { id: "ime_mode_auto_number",
michael@0 574 description: "input[type=number][style=\"ime-mode: auto;\"]",
michael@0 575 focusable: !aInDesignMode,
michael@0 576 expectedEnabled: gUtils.IME_STATUS_ENABLED },
michael@0 577 { id: "ime_mode_normal_number",
michael@0 578 description: "input[type=number][style=\"ime-mode: normal;\"]",
michael@0 579 focusable: !aInDesignMode,
michael@0 580 expectedEnabled: gUtils.IME_STATUS_ENABLED },
michael@0 581 { id: "ime_mode_active_number",
michael@0 582 description: "input[type=number][style=\"ime-mode: active;\"]",
michael@0 583 expectedEnabled: gUtils.IME_STATUS_ENABLED,
michael@0 584 focusable: !aInDesignMode,
michael@0 585 changeOpened: true, expectedOpened: true },
michael@0 586 { id: "ime_mode_inactive_number",
michael@0 587 description: "input[type=number][style=\"ime-mode: inactive;\"]",
michael@0 588 expectedEnabled: gUtils.IME_STATUS_ENABLED,
michael@0 589 focusable: !aInDesignMode,
michael@0 590 changeOpened: true, expectedOpened: false },
michael@0 591 { id: "ime_mode_disabled_number",
michael@0 592 description: "input[type=number][style=\"ime-mode: disabled;\"]",
michael@0 593 focusable: !aInDesignMode,
michael@0 594 expectedEnabled: kEnabledStateOnPasswordField },
michael@0 595
michael@0 596 { id: "ime_mode_auto_p",
michael@0 597 description: "input[type=password][style=\"ime-mode: auto;\"]",
michael@0 598 focusable: !aInDesignMode,
michael@0 599 expectedEnabled: kEnabledStateOnPasswordField },
michael@0 600 { id: "ime_mode_normal_p",
michael@0 601 description: "input[type=password][style=\"ime-mode: normal;\"]",
michael@0 602 focusable: !aInDesignMode,
michael@0 603 expectedEnabled: gUtils.IME_STATUS_ENABLED },
michael@0 604 { id: "ime_mode_active_p",
michael@0 605 description: "input[type=password][style=\"ime-mode: active;\"]",
michael@0 606 expectedEnabled: gUtils.IME_STATUS_ENABLED,
michael@0 607 focusable: !aInDesignMode,
michael@0 608 changeOpened: true, expectedOpened: true },
michael@0 609 { id: "ime_mode_inactive_p",
michael@0 610 description: "input[type=password][style=\"ime-mode: inactive;\"]",
michael@0 611 expectedEnabled: gUtils.IME_STATUS_ENABLED,
michael@0 612 focusable: !aInDesignMode,
michael@0 613 changeOpened: true, expectedOpened: false },
michael@0 614 { id: "ime_mode_disabled_p",
michael@0 615 description: "input[type=password][style=\"ime-mode: disabled;\"]",
michael@0 616 focusable: !aInDesignMode,
michael@0 617 expectedEnabled: kEnabledStateOnPasswordField },
michael@0 618 { id: "ime_mode_auto",
michael@0 619 description: "textarea[style=\"ime-mode: auto;\"]",
michael@0 620 focusable: !aInDesignMode,
michael@0 621 expectedEnabled: gUtils.IME_STATUS_ENABLED },
michael@0 622 { id: "ime_mode_normal",
michael@0 623 description: "textarea[style=\"ime-mode: normal;\"]",
michael@0 624 focusable: !aInDesignMode,
michael@0 625 expectedEnabled: gUtils.IME_STATUS_ENABLED },
michael@0 626 { id: "ime_mode_active",
michael@0 627 description: "textarea[style=\"ime-mode: active;\"]",
michael@0 628 focusable: !aInDesignMode,
michael@0 629 expectedEnabled: gUtils.IME_STATUS_ENABLED,
michael@0 630 changeOpened: true, expectedOpened: true },
michael@0 631 { id: "ime_mode_inactive",
michael@0 632 description: "textarea[style=\"ime-mode: inactive;\"]",
michael@0 633 focusable: !aInDesignMode,
michael@0 634 expectedEnabled: gUtils.IME_STATUS_ENABLED,
michael@0 635 changeOpened: true, expectedOpened: false },
michael@0 636 { id: "ime_mode_disabled",
michael@0 637 description: "textarea[style=\"ime-mode: disabled;\"]",
michael@0 638 focusable: !aInDesignMode,
michael@0 639 expectedEnabled: kEnabledStateOnPasswordField },
michael@0 640
michael@0 641 // HTML editors
michael@0 642 { id: "contenteditableEditor",
michael@0 643 description: "div[contenteditable=\"true\"]",
michael@0 644 focusable: !aIsEditable && !aInDesignMode,
michael@0 645 expectedEnabled: gUtils.IME_STATUS_ENABLED },
michael@0 646 { id: "designModeEditor",
michael@0 647 description: "designMode editor",
michael@0 648 focusable: true,
michael@0 649 toDesignModeEditor: true,
michael@0 650 expectedEnabled: gUtils.IME_STATUS_ENABLED },
michael@0 651 ];
michael@0 652
michael@0 653 for (var i = 0; i < kTests.length; i++) {
michael@0 654 test(kTests[i]);
michael@0 655 }
michael@0 656 }
michael@0 657
michael@0 658 function runPluginTest()
michael@0 659 {
michael@0 660 if (!kIMEEnabledSupported) {
michael@0 661 return;
michael@0 662 }
michael@0 663
michael@0 664 if (navigator.platform.indexOf("Mac") == 0) {
michael@0 665 // XXX on mac, currently, this test isn't passed because it doesn't return
michael@0 666 // IME_STATUS_PLUGIN by its bug.
michael@0 667 return;
michael@0 668 }
michael@0 669
michael@0 670 var plugin = document.getElementById("plugin");
michael@0 671
michael@0 672 document.activeElement.blur();
michael@0 673 is(gUtils.IMEStatus, gUtils.IME_STATUS_DISABLED,
michael@0 674 "runPluginTest: unexpected enabled state when no element has focus");
michael@0 675
michael@0 676 plugin.focus();
michael@0 677 is(gUtils.IMEStatus, gUtils.IME_STATUS_PLUGIN,
michael@0 678 "runPluginTest: unexpected enabled state when plugin has focus");
michael@0 679
michael@0 680 plugin.blur();
michael@0 681 is(gUtils.IMEStatus, gUtils.IME_STATUS_DISABLED,
michael@0 682 "runPluginTest: unexpected enabled state when plugin has focus");
michael@0 683
michael@0 684 plugin.focus();
michael@0 685 is(gUtils.IMEStatus, gUtils.IME_STATUS_PLUGIN,
michael@0 686 "runPluginTest: unexpected enabled state when plugin has focus #2");
michael@0 687
michael@0 688 var parent = plugin.parentNode;
michael@0 689 parent.removeChild(plugin);
michael@0 690 is(gUtils.IMEStatus, gUtils.IME_STATUS_DISABLED,
michael@0 691 "runPluginTest: unexpected enabled state when plugin is removed from tree");
michael@0 692
michael@0 693 document.getElementById("text").focus();
michael@0 694 is(gUtils.IMEStatus, gUtils.IME_STATUS_ENABLED,
michael@0 695 "runPluginTest: unexpected enabled state when input[type=text] has focus");
michael@0 696 }
michael@0 697
michael@0 698 function runTypeChangingTest()
michael@0 699 {
michael@0 700 if (!kIMEEnabledSupported)
michael@0 701 return;
michael@0 702
michael@0 703 const kInputControls = [
michael@0 704 { id: "text",
michael@0 705 type: "text", expected: gUtils.IME_STATUS_ENABLED,
michael@0 706 description: "[type=\"text\"]" },
michael@0 707 { id: "text_readonly",
michael@0 708 type: "text", expected: gUtils.IME_STATUS_DISABLED, isReadonly: true,
michael@0 709 description: "[type=\"text\"][readonly]" },
michael@0 710 { id: "password",
michael@0 711 type: "password", expected: gUtils.IME_STATUS_PASSWORD,
michael@0 712 description: "[type=\"password\"]" },
michael@0 713 { id: "password_readonly",
michael@0 714 type: "password", expected: gUtils.IME_STATUS_DISABLED, isReadonly: true,
michael@0 715 description: "[type=\"password\"][readonly]" },
michael@0 716 { id: "checkbox",
michael@0 717 type: "checkbox", expected: gUtils.IME_STATUS_DISABLED,
michael@0 718 description: "[type=\"checkbox\"]" },
michael@0 719 { id: "radio",
michael@0 720 type: "radio", expected: gUtils.IME_STATUS_DISABLED,
michael@0 721 description: "[type=\"radio\"]" },
michael@0 722 { id: "submit",
michael@0 723 type: "submit", expected: gUtils.IME_STATUS_DISABLED,
michael@0 724 description: "[type=\"submit\"]" },
michael@0 725 { id: "reset",
michael@0 726 type: "reset", expected: gUtils.IME_STATUS_DISABLED,
michael@0 727 description: "[type=\"reset\"]" },
michael@0 728 { id: "file",
michael@0 729 type: "file", expected: gUtils.IME_STATUS_DISABLED,
michael@0 730 description: "[type=\"file\"]" },
michael@0 731 { id: "ibutton",
michael@0 732 type: "button", expected: gUtils.IME_STATUS_DISABLED,
michael@0 733 description: "[type=\"button\"]" },
michael@0 734 { id: "image",
michael@0 735 type: "image", expected: gUtils.IME_STATUS_DISABLED,
michael@0 736 description: "[type=\"image\"]" },
michael@0 737 { id: "url",
michael@0 738 type: "url", expected: gUtils.IME_STATUS_ENABLED,
michael@0 739 description: "[type=\"url\"]" },
michael@0 740 { id: "email",
michael@0 741 type: "email", expected: gUtils.IME_STATUS_ENABLED,
michael@0 742 description: "[type=\"email\"]" },
michael@0 743 { id: "search",
michael@0 744 type: "search", expected: gUtils.IME_STATUS_ENABLED,
michael@0 745 description: "[type=\"search\"]" },
michael@0 746 { id: "tel",
michael@0 747 type: "tel", expected: gUtils.IME_STATUS_ENABLED,
michael@0 748 description: "[type=\"tel\"]" },
michael@0 749 { id: "number",
michael@0 750 type: "number", expected: gUtils.IME_STATUS_ENABLED,
michael@0 751 description: "[type=\"number\"]" },
michael@0 752 { id: "ime_mode_auto",
michael@0 753 type: "text", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 754 description: "[type=\"text\"][ime-mode: auto;]" },
michael@0 755 { id: "ime_mode_normal",
michael@0 756 type: "text", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 757 description: "[type=\"text\"][ime-mode: normal;]" },
michael@0 758 { id: "ime_mode_active",
michael@0 759 type: "text", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 760 description: "[type=\"text\"][ime-mode: active;]" },
michael@0 761 { id: "ime_mode_inactive",
michael@0 762 type: "text", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 763 description: "[type=\"text\"][ime-mode: inactive;]" },
michael@0 764 { id: "ime_mode_disabled",
michael@0 765 type: "text", expected: gUtils.IME_STATUS_PASSWORD, imeMode: true,
michael@0 766 description: "[type=\"text\"][ime-mode: disabled;]" },
michael@0 767
michael@0 768 { id: "ime_mode_auto_url",
michael@0 769 type: "url", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 770 description: "[type=\"url\"][ime-mode: auto;]" },
michael@0 771 { id: "ime_mode_normal_url",
michael@0 772 type: "url", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 773 description: "[type=\"url\"][ime-mode: normal;]" },
michael@0 774 { id: "ime_mode_active_url",
michael@0 775 type: "url", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 776 description: "[type=\"url\"][ime-mode: active;]" },
michael@0 777 { id: "ime_mode_inactive_url",
michael@0 778 type: "url", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 779 description: "[type=\"url\"][ime-mode: inactive;]" },
michael@0 780 { id: "ime_mode_disabled_url",
michael@0 781 type: "url", expected: gUtils.IME_STATUS_PASSWORD, imeMode: true,
michael@0 782 description: "[type=\"url\"][ime-mode: disabled;]" },
michael@0 783
michael@0 784 { id: "ime_mode_auto_email",
michael@0 785 type: "email", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 786 description: "[type=\"email\"][ime-mode: auto;]" },
michael@0 787 { id: "ime_mode_normal_email",
michael@0 788 type: "email", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 789 description: "[type=\"email\"][ime-mode: normal;]" },
michael@0 790 { id: "ime_mode_active_email",
michael@0 791 type: "email", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 792 description: "[type=\"email\"][ime-mode: active;]" },
michael@0 793 { id: "ime_mode_inactive_email",
michael@0 794 type: "email", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 795 description: "[type=\"email\"][ime-mode: inactive;]" },
michael@0 796 { id: "ime_mode_disabled_email",
michael@0 797 type: "email", expected: gUtils.IME_STATUS_PASSWORD, imeMode: true,
michael@0 798 description: "[type=\"email\"][ime-mode: disabled;]" },
michael@0 799
michael@0 800 { id: "ime_mode_auto_search",
michael@0 801 type: "search", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 802 description: "[type=\"search\"][ime-mode: auto;]" },
michael@0 803 { id: "ime_mode_normal_search",
michael@0 804 type: "search", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 805 description: "[type=\"search\"][ime-mode: normal;]" },
michael@0 806 { id: "ime_mode_active_search",
michael@0 807 type: "search", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 808 description: "[type=\"search\"][ime-mode: active;]" },
michael@0 809 { id: "ime_mode_inactive_search",
michael@0 810 type: "search", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 811 description: "[type=\"search\"][ime-mode: inactive;]" },
michael@0 812 { id: "ime_mode_disabled_search",
michael@0 813 type: "search", expected: gUtils.IME_STATUS_PASSWORD, imeMode: true,
michael@0 814 description: "[type=\"search\"][ime-mode: disabled;]" },
michael@0 815
michael@0 816 { id: "ime_mode_auto_tel",
michael@0 817 type: "tel", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 818 description: "[type=\"tel\"][ime-mode: auto;]" },
michael@0 819 { id: "ime_mode_normal_tel",
michael@0 820 type: "tel", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 821 description: "[type=\"tel\"][ime-mode: normal;]" },
michael@0 822 { id: "ime_mode_active_tel",
michael@0 823 type: "tel", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 824 description: "[type=\"tel\"][ime-mode: active;]" },
michael@0 825 { id: "ime_mode_inactive_tel",
michael@0 826 type: "tel", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 827 description: "[type=\"tel\"][ime-mode: inactive;]" },
michael@0 828 { id: "ime_mode_disabled_tel",
michael@0 829 type: "tel", expected: gUtils.IME_STATUS_PASSWORD, imeMode: true,
michael@0 830 description: "[type=\"tel\"][ime-mode: disabled;]" },
michael@0 831
michael@0 832 { id: "ime_mode_auto_number",
michael@0 833 type: "number", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 834 description: "[type=\"number\"][ime-mode: auto;]" },
michael@0 835 { id: "ime_mode_normal_number",
michael@0 836 type: "number", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 837 description: "[type=\"number\"][ime-mode: normal;]" },
michael@0 838 { id: "ime_mode_active_number",
michael@0 839 type: "number", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 840 description: "[type=\"number\"][ime-mode: active;]" },
michael@0 841 { id: "ime_mode_inactive_number",
michael@0 842 type: "number", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 843 description: "[type=\"number\"][ime-mode: inactive;]" },
michael@0 844 { id: "ime_mode_disabled_number",
michael@0 845 type: "number", expected: gUtils.IME_STATUS_PASSWORD, imeMode: true,
michael@0 846 description: "[type=\"number\"][ime-mode: disabled;]" },
michael@0 847
michael@0 848 { id: "ime_mode_auto_p",
michael@0 849 type: "password", expected: gUtils.IME_STATUS_PASSWORD, imeMode: true,
michael@0 850 description: "[type=\"password\"][ime-mode: auto;]" },
michael@0 851 { id: "ime_mode_normal_p",
michael@0 852 type: "password", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 853 description: "[type=\"password\"][ime-mode: normal;]" },
michael@0 854 { id: "ime_mode_active_p",
michael@0 855 type: "password", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 856 description: "[type=\"password\"][ime-mode: active;]" },
michael@0 857 { id: "ime_mode_inactive_p",
michael@0 858 type: "password", expected: gUtils.IME_STATUS_ENABLED, imeMode: true,
michael@0 859 description: "[type=\"password\"][ime-mode: inactive;]" },
michael@0 860 { id: "ime_mode_disabled_p",
michael@0 861 type: "password", expected: gUtils.IME_STATUS_PASSWORD, imeMode: true,
michael@0 862 description: "[type=\"password\"][ime-mode: disabled;]" }
michael@0 863 ];
michael@0 864
michael@0 865 const kInputTypes = [
michael@0 866 { type: "", expected: gUtils.IME_STATUS_ENABLED },
michael@0 867 { type: "text", expected: gUtils.IME_STATUS_ENABLED },
michael@0 868 { type: "password", expected: gUtils.IME_STATUS_PASSWORD },
michael@0 869 { type: "checkbox", expected: gUtils.IME_STATUS_DISABLED },
michael@0 870 { type: "radio", expected: gUtils.IME_STATUS_DISABLED },
michael@0 871 { type: "submit", expected: gUtils.IME_STATUS_DISABLED },
michael@0 872 { type: "reset", expected: gUtils.IME_STATUS_DISABLED },
michael@0 873 { type: "file", expected: gUtils.IME_STATUS_DISABLED },
michael@0 874 { type: "button", expected: gUtils.IME_STATUS_DISABLED },
michael@0 875 { type: "image", expected: gUtils.IME_STATUS_DISABLED },
michael@0 876 { type: "url", expected: gUtils.IME_STATUS_ENABLED },
michael@0 877 { type: "email", expected: gUtils.IME_STATUS_ENABLED },
michael@0 878 { type: "search", expected: gUtils.IME_STATUS_ENABLED },
michael@0 879 { type: "tel", expected: gUtils.IME_STATUS_ENABLED },
michael@0 880 { type: "number", expected: gUtils.IME_STATUS_ENABLED }
michael@0 881 ];
michael@0 882
michael@0 883 function getExpectedIMEEnabled(aNewType, aInputControl)
michael@0 884 {
michael@0 885 if (aNewType.expected == gUtils.IME_STATUS_DISABLED ||
michael@0 886 aInputControl.isReadonly)
michael@0 887 return gUtils.IME_STATUS_DISABLED;
michael@0 888 return aInputControl.imeMode ? aInputControl.expected : aNewType.expected;
michael@0 889 }
michael@0 890
michael@0 891 const kOpenedState = [ true, false ];
michael@0 892
michael@0 893 for (var i = 0; i < kOpenedState.length; i++) {
michael@0 894 const kOpened = kOpenedState[i];
michael@0 895 for (var j = 0; j < kInputControls.length; j++) {
michael@0 896 const kInput = kInputControls[j];
michael@0 897 var e = document.getElementById(kInput.id);
michael@0 898 e.focus();
michael@0 899 for (var k = 0; k < kInputTypes.length; k++) {
michael@0 900 const kType = kInputTypes[k];
michael@0 901 var typeChangingDescription =
michael@0 902 "\"" + e.getAttribute("type") + "\" to \"" + kInput.type + "\"";
michael@0 903 e.setAttribute("type", kInput.type);
michael@0 904 is(gUtils.IMEStatus, kInput.expected,
michael@0 905 "type attr changing test (IMEStatus): " + typeChangingDescription +
michael@0 906 " (" + kInput.description + ")");
michael@0 907 is(gUtils.focusedInputType, kInput.type,
michael@0 908 "type attr changing test (type): " + typeChangingDescription +
michael@0 909 " (" + kInput.description + ")");
michael@0 910
michael@0 911 const kTestOpenState = kIMEOpenSupported &&
michael@0 912 gUtils.IMEStatus == gUtils.IME_STATUS_ENABLED &&
michael@0 913 getExpectedIMEEnabled(kType, kInput) == gUtils.IME_STATUS_ENABLED;
michael@0 914 if (kTestOpenState) {
michael@0 915 gUtils.IMEIsOpen = kOpened;
michael@0 916 }
michael@0 917
michael@0 918 typeChangingDescription =
michael@0 919 "\"" + e.getAttribute("type") + "\" to \"" + kType.type + "\"";
michael@0 920 if (kType.type != "")
michael@0 921 e.setAttribute("type", kType.type);
michael@0 922 else
michael@0 923 e.removeAttribute("type");
michael@0 924
michael@0 925 is(gUtils.IMEStatus, getExpectedIMEEnabled(kType, kInput),
michael@0 926 "type attr changing test (IMEStatus): " + typeChangingDescription +
michael@0 927 " (" + kInput.description + ")");
michael@0 928 is(gUtils.focusedInputType, kType.type,
michael@0 929 "type attr changing test (type): " + typeChangingDescription +
michael@0 930 " (" + kInput.description + ")");
michael@0 931 if (kTestOpenState && gUtils.IMEStatus == gUtils.IME_STATUS_ENABLED) {
michael@0 932 is(gUtils.IMEIsOpen, kOpened,
michael@0 933 "type attr changing test (open state is changed): " +
michael@0 934 typeChangingDescription + " (" + kInput.description + ")");
michael@0 935 }
michael@0 936 }
michael@0 937 // reset the type to default
michael@0 938 e.setAttribute("type", kInput.type);
michael@0 939 }
michael@0 940 if (!kIMEOpenSupported)
michael@0 941 break;
michael@0 942 }
michael@0 943 }
michael@0 944
michael@0 945 function runReadonlyChangingTest()
michael@0 946 {
michael@0 947 if (!kIMEEnabledSupported)
michael@0 948 return;
michael@0 949
michael@0 950 const kInputControls = [
michael@0 951 { id: "text",
michael@0 952 type: "text", expected: gUtils.IME_STATUS_ENABLED },
michael@0 953 { id: "password",
michael@0 954 type: "password", expected: gUtils.IME_STATUS_PASSWORD },
michael@0 955 { id: "url",
michael@0 956 type: "url", expected: gUtils.IME_STATUS_ENABLED },
michael@0 957 { id: "email",
michael@0 958 type: "email", expected: gUtils.IME_STATUS_ENABLED },
michael@0 959 { id: "search",
michael@0 960 type: "search", expected: gUtils.IME_STATUS_ENABLED },
michael@0 961 { id: "tel",
michael@0 962 type: "tel", expected: gUtils.IME_STATUS_ENABLED },
michael@0 963 { id: "number",
michael@0 964 type: "number", expected: gUtils.IME_STATUS_ENABLED },
michael@0 965 { id: "textarea",
michael@0 966 type: "textarea", expected: gUtils.IME_STATUS_ENABLED }
michael@0 967 ];
michael@0 968 const kOpenedState = [ true, false ];
michael@0 969
michael@0 970 for (var i = 0; i < kOpenedState.length; i++) {
michael@0 971 const kOpened = kOpenedState[i];
michael@0 972 for (var j = 0; j < kInputControls.length; j++) {
michael@0 973 const kInput = kInputControls[j];
michael@0 974 var e = document.getElementById(kInput.id);
michael@0 975 e.focus();
michael@0 976 if (kIMEOpenSupported && gUtils.IMEStatus == gUtils.IME_STATUS_ENABLED) {
michael@0 977 gUtils.IMEIsOpen = kOpened;
michael@0 978 }
michael@0 979 e.setAttribute("readonly", "readonly");
michael@0 980 is(gUtils.IMEStatus, gUtils.IME_STATUS_DISABLED,
michael@0 981 "readonly attr setting test: type=" + kInput.type);
michael@0 982 e.removeAttribute("readonly");
michael@0 983 is(gUtils.IMEStatus, kInput.expected,
michael@0 984 "readonly attr removing test: type=" + kInput.type);
michael@0 985 if (kIMEOpenSupported && gUtils.IMEStatus == gUtils.IME_STATUS_ENABLED) {
michael@0 986 is(gUtils.IMEIsOpen, kOpened,
michael@0 987 "readonly attr removing test (open state is changed): type=" +
michael@0 988 kInput.type);
michael@0 989 }
michael@0 990 }
michael@0 991 if (!kIMEOpenSupported)
michael@0 992 break;
michael@0 993 }
michael@0 994 }
michael@0 995
michael@0 996 function runComplexContenteditableTests()
michael@0 997 {
michael@0 998 if (!kIMEEnabledSupported) {
michael@0 999 return;
michael@0 1000 }
michael@0 1001
michael@0 1002 var description = "runReadonlyChangingOnContenteditable: ";
michael@0 1003
michael@0 1004 var container = document.getElementById("display");
michael@0 1005 var button = document.getElementById("button");
michael@0 1006
michael@0 1007 // the editor has focus directly.
michael@0 1008 container.setAttribute("contenteditable", "true");
michael@0 1009 container.focus();
michael@0 1010
michael@0 1011 is(gFM.focusedElement, container,
michael@0 1012 description + "The editor doesn't get focus");
michael@0 1013 is(gUtils.IMEStatus, gUtils.IME_STATUS_ENABLED,
michael@0 1014 description + "IME isn't enabled on HTML editor");
michael@0 1015 const kReadonly =
michael@0 1016 Components.interfaces.nsIPlaintextEditor.eEditorReadonlyMask;
michael@0 1017 var editor =
michael@0 1018 window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
michael@0 1019 getInterface(Components.interfaces.nsIWebNavigation).
michael@0 1020 QueryInterface(Components.interfaces.nsIDocShell).editor;
michael@0 1021 var flags = editor.flags;
michael@0 1022 editor.flags = flags | kReadonly;
michael@0 1023 is(gFM.focusedElement, container,
michael@0 1024 description + "The editor loses focus by flag change");
michael@0 1025 is(gUtils.IMEStatus, gUtils.IME_STATUS_DISABLED,
michael@0 1026 description + "IME is still enabled on readonly HTML editor");
michael@0 1027 editor.flags = flags;
michael@0 1028 is(gFM.focusedElement, container,
michael@0 1029 description + "The editor loses focus by flag change #2");
michael@0 1030 is(gUtils.IMEStatus, gUtils.IME_STATUS_ENABLED,
michael@0 1031 description + "IME is still disabled, the editor isn't readonly now");
michael@0 1032 container.removeAttribute("contenteditable");
michael@0 1033 todo_is(gFM.focusedElement, null,
michael@0 1034 description + "The container still has focus, the editor has been no editable");
michael@0 1035 todo_is(gUtils.IMEStatus, gUtils.IME_STATUS_DISABLED,
michael@0 1036 description + "IME is still enabled on the editor, the editor has been no editable");
michael@0 1037
michael@0 1038 // a button which is in the editor has focus
michael@0 1039 button.focus();
michael@0 1040 is(gFM.focusedElement, button,
michael@0 1041 description + "The button doesn't get focus");
michael@0 1042 is(gUtils.IMEStatus, gUtils.IME_STATUS_DISABLED,
michael@0 1043 description + "IME is enabled on the button");
michael@0 1044 container.setAttribute("contenteditable", "true");
michael@0 1045 is(gFM.focusedElement, button,
michael@0 1046 description + "The button loses focus, the container is editable now");
michael@0 1047 todo_is(gUtils.IMEStatus, gUtils.IME_STATUS_ENABLED,
michael@0 1048 description + "IME is still disabled on the button, the container is editable now");
michael@0 1049 editor =
michael@0 1050 window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
michael@0 1051 getInterface(Components.interfaces.nsIWebNavigation).
michael@0 1052 QueryInterface(Components.interfaces.nsIDocShell).editor;
michael@0 1053 flags = editor.flags;
michael@0 1054 editor.flags = flags | kReadonly;
michael@0 1055 is(gFM.focusedElement, button,
michael@0 1056 description + "The button loses focus by changing editor flags");
michael@0 1057 is(gUtils.IMEStatus, gUtils.IME_STATUS_DISABLED,
michael@0 1058 description + "IME is still enabled on the button, the container is readonly now");
michael@0 1059 editor.flags = flags;
michael@0 1060 is(gFM.focusedElement, button,
michael@0 1061 description + "The button loses focus by changing editor flags #2");
michael@0 1062 is(gUtils.IMEStatus, gUtils.IME_STATUS_ENABLED,
michael@0 1063 description + "IME is still disabled on the button, the container isn't readonly now");
michael@0 1064 container.removeAttribute("contenteditable");
michael@0 1065 is(gFM.focusedElement, button,
michael@0 1066 description + "The button loses focus, the container has been no editable");
michael@0 1067 todo_is(gUtils.IMEStatus, gUtils.IME_STATUS_DISABLED,
michael@0 1068 description + "IME is still enabled on the button, the container has been no editable");
michael@0 1069
michael@0 1070 description = "testOnIndependentEditor: ";
michael@0 1071 function testOnIndependentEditor(aEditor, aEditorDescription)
michael@0 1072 {
michael@0 1073 var isReadonly = aEditor.readOnly;
michael@0 1074 var expectedState =
michael@0 1075 aEditor.readOnly ? gUtils.IME_STATUS_DISABLED : gUtils.IME_STATUS_ENABLED;
michael@0 1076 var unexpectedStateDescription =
michael@0 1077 expectedState != gUtils.IME_STATUS_ENABLED ? "enabled" : "disabled";
michael@0 1078 aEditor.focus();
michael@0 1079 is(gFM.focusedElement, aEditor,
michael@0 1080 description + "The " + aEditorDescription + " doesn't get focus");
michael@0 1081 is(gUtils.IMEStatus, expectedState,
michael@0 1082 description + "IME is " + unexpectedStateDescription +
michael@0 1083 " on the " + aEditorDescription);
michael@0 1084 container.setAttribute("contenteditable", "true");
michael@0 1085 is(gFM.focusedElement, aEditor,
michael@0 1086 description + "The " + aEditorDescription +
michael@0 1087 " loses focus, the container is editable now");
michael@0 1088 is(gUtils.IMEStatus, expectedState,
michael@0 1089 description + "IME becomes " + unexpectedStateDescription +
michael@0 1090 " on the " + aEditorDescription + ", the container is editable now");
michael@0 1091 editor =
michael@0 1092 window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
michael@0 1093 getInterface(Components.interfaces.nsIWebNavigation).
michael@0 1094 QueryInterface(Components.interfaces.nsIDocShell).editor;
michael@0 1095 flags = editor.flags;
michael@0 1096 editor.flags = flags | kReadonly;
michael@0 1097 is(gFM.focusedElement, aEditor,
michael@0 1098 description + "The " + aEditorDescription +
michael@0 1099 " loses focus by changing editor flags");
michael@0 1100 is(gUtils.IMEStatus, expectedState,
michael@0 1101 description + "IME becomes " + unexpectedStateDescription + " on the " +
michael@0 1102 aEditorDescription + ", the container is readonly now");
michael@0 1103 editor.flags = flags;
michael@0 1104 is(gFM.focusedElement, aEditor,
michael@0 1105 description + "The " + aEditorDescription +
michael@0 1106 " loses focus by changing editor flags #2");
michael@0 1107 is(gUtils.IMEStatus, expectedState,
michael@0 1108 description + "IME becomes " + unexpectedStateDescription + " on the " +
michael@0 1109 aEditorDescription + ", the container isn't readonly now");
michael@0 1110 container.removeAttribute("contenteditable");
michael@0 1111 is(gFM.focusedElement, aEditor,
michael@0 1112 description + "The " + aEditorDescription +
michael@0 1113 " loses focus, the container has been no editable");
michael@0 1114 is(gUtils.IMEStatus, expectedState,
michael@0 1115 description + "IME becomes " + unexpectedStateDescription + " on the " +
michael@0 1116 aEditorDescription + ", the container has been no editable");
michael@0 1117 }
michael@0 1118
michael@0 1119 // a textarea which is in the editor has focus
michael@0 1120 testOnIndependentEditor(document.getElementById("textarea"),
michael@0 1121 "textarea");
michael@0 1122 // a readonly textarea which is in the editor has focus
michael@0 1123 testOnIndependentEditor(document.getElementById("textarea_readonly"),
michael@0 1124 "textarea[readonly]");
michael@0 1125 // an input field which is in the editor has focus
michael@0 1126 testOnIndependentEditor(document.getElementById("text"),
michael@0 1127 "input[type=\"text\"]");
michael@0 1128 // a readonly input field which is in the editor has focus
michael@0 1129 testOnIndependentEditor(document.getElementById("text_readonly"),
michael@0 1130 "input[type=\"text\"][readonly]");
michael@0 1131
michael@0 1132 description = "testOnOutsideOfEditor: ";
michael@0 1133 function testOnOutsideOfEditor(aFocusNode, aFocusNodeDescription, aEditor)
michael@0 1134 {
michael@0 1135 if (aFocusNode) {
michael@0 1136 aFocusNode.focus();
michael@0 1137 is(gFM.focusedElement, aFocusNode,
michael@0 1138 description + "The " + aFocusNodeDescription + " doesn't get focus");
michael@0 1139 } else {
michael@0 1140 if (document.activeElement) {
michael@0 1141 document.activeElement.blur();
michael@0 1142 }
michael@0 1143 is(gFM.focusedElement, null,
michael@0 1144 description + "Unexpected element has focus");
michael@0 1145 }
michael@0 1146 var expectedState =
michael@0 1147 aFocusNode ? gUtils.IMEStatus : gUtils.IME_STATUS_DISABLED;
michael@0 1148 var unexpectedStateDescription =
michael@0 1149 expectedState != gUtils.IME_STATUS_ENABLED ? "enabled" : "disabled";
michael@0 1150
michael@0 1151 aEditor.setAttribute("contenteditable", "true");
michael@0 1152 is(gFM.focusedElement, aFocusNode,
michael@0 1153 description + "The " + aFocusNodeDescription +
michael@0 1154 " loses focus, a HTML editor is editable now");
michael@0 1155 is(gUtils.IMEStatus, expectedState,
michael@0 1156 description + "IME becomes " + unexpectedStateDescription +
michael@0 1157 " on the " + aFocusNodeDescription +
michael@0 1158 ", the HTML editor is editable now");
michael@0 1159 editor =
michael@0 1160 window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
michael@0 1161 getInterface(Components.interfaces.nsIWebNavigation).
michael@0 1162 QueryInterface(Components.interfaces.nsIDocShell).editor;
michael@0 1163 flags = editor.flags;
michael@0 1164 editor.flags = flags | kReadonly;
michael@0 1165 is(gFM.focusedElement, aFocusNode,
michael@0 1166 description + aFocusNodeDescription +
michael@0 1167 " loses focus by changing HTML editor flags");
michael@0 1168 is(gUtils.IMEStatus, expectedState,
michael@0 1169 description + "IME becomes " + unexpectedStateDescription + " on " +
michael@0 1170 aFocusNodeDescription + ", the HTML editor is readonly now");
michael@0 1171 editor.flags = flags;
michael@0 1172 is(gFM.focusedElement, aFocusNode,
michael@0 1173 description + aFocusNodeDescription +
michael@0 1174 " loses focus by changing HTML editor flags #2");
michael@0 1175 is(gUtils.IMEStatus, expectedState,
michael@0 1176 description + "IME becomes " + unexpectedStateDescription + " on " +
michael@0 1177 aFocusNodeDescription + ", the HTML editor isn't readonly now");
michael@0 1178 container.removeAttribute("contenteditable");
michael@0 1179 is(gFM.focusedElement, aFocusNode,
michael@0 1180 description + aFocusNodeDescription +
michael@0 1181 " loses focus, the HTML editor has been no editable");
michael@0 1182 is(gUtils.IMEStatus, expectedState,
michael@0 1183 description + "IME becomes " + unexpectedStateDescription + " on " +
michael@0 1184 aFocusNodeDescription + ", the HTML editor has been no editable");
michael@0 1185 }
michael@0 1186
michael@0 1187 var div = document.getElementById("contenteditableEditor");
michael@0 1188 // a textarea which is outside of the editor has focus
michael@0 1189 testOnOutsideOfEditor(document.getElementById("textarea"), "textarea", div);
michael@0 1190 // a readonly textarea which is outside of the editor has focus
michael@0 1191 testOnOutsideOfEditor(document.getElementById("textarea_readonly"),
michael@0 1192 "textarea[readonly]", div);
michael@0 1193 // an input field which is outside of the editor has focus
michael@0 1194 testOnOutsideOfEditor(document.getElementById("text"),
michael@0 1195 "input[type=\"text\"]", div);
michael@0 1196 // a readonly input field which outside of the editor has focus
michael@0 1197 testOnOutsideOfEditor(document.getElementById("text_readonly"),
michael@0 1198 "input[type=\"text\"][readonly]", div);
michael@0 1199 // a readonly input field which outside of the editor has focus
michael@0 1200 testOnOutsideOfEditor(document.getElementById("button"), "button", div);
michael@0 1201 // nobody has focus.
michael@0 1202 testOnOutsideOfEditor(null, "nobody", div);
michael@0 1203 }
michael@0 1204
michael@0 1205 function runEditorFlagChangeTests()
michael@0 1206 {
michael@0 1207 if (!kIMEEnabledSupported) {
michael@0 1208 return;
michael@0 1209 }
michael@0 1210
michael@0 1211 var description = "runEditorFlagChangeTests: ";
michael@0 1212
michael@0 1213 var container = document.getElementById("display");
michael@0 1214
michael@0 1215 // the editor has focus directly.
michael@0 1216 container.setAttribute("contenteditable", "true");
michael@0 1217 container.focus();
michael@0 1218
michael@0 1219 is(gFM.focusedElement, container,
michael@0 1220 description + "The editor doesn't get focus");
michael@0 1221 is(gUtils.IMEStatus, gUtils.IME_STATUS_ENABLED,
michael@0 1222 description + "IME isn't enabled on HTML editor");
michael@0 1223 const kIMEStateChangeFlags =
michael@0 1224 Components.interfaces.nsIPlaintextEditor.eEditorPasswordMask |
michael@0 1225 Components.interfaces.nsIPlaintextEditor.eEditorReadonlyMask |
michael@0 1226 Components.interfaces.nsIPlaintextEditor.eEditorDisabledMask;
michael@0 1227 var editor =
michael@0 1228 window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
michael@0 1229 getInterface(Components.interfaces.nsIWebNavigation).
michael@0 1230 QueryInterface(Components.interfaces.nsIDocShell).editor;
michael@0 1231 var editorIMESupport =
michael@0 1232 editor.QueryInterface(Components.interfaces.nsIEditorIMESupport);
michael@0 1233 var flags = editor.flags;
michael@0 1234
michael@0 1235 // start composition
michael@0 1236 synthesizeComposition({ type: "compositionstart" });
michael@0 1237
michael@0 1238 // input characters
michael@0 1239 synthesizeComposition({ type: "compositionupdate",
michael@0 1240 data: "\u3078\u3093\u3057\u3093" });
michael@0 1241 synthesizeText(
michael@0 1242 { "composition":
michael@0 1243 { "string": "\u3078\u3093\u3057\u3093",
michael@0 1244 "clauses":
michael@0 1245 [
michael@0 1246 { "length": 4, "attr": COMPOSITION_ATTR_RAWINPUT }
michael@0 1247 ]
michael@0 1248 },
michael@0 1249 "caret": { "start": 4, "length": 0 }
michael@0 1250 });
michael@0 1251
michael@0 1252 editor.flags &= ~kIMEStateChangeFlags;
michael@0 1253 ok(editorIMESupport.composing,
michael@0 1254 description + "#1 IME composition was committed unexpectedly");
michael@0 1255 is(gUtils.IMEStatus, gUtils.IME_STATUS_ENABLED,
michael@0 1256 description + "#1 IME isn't enabled on HTML editor");
michael@0 1257
michael@0 1258 editor.flags |= ~kIMEStateChangeFlags;
michael@0 1259 ok(editorIMESupport.composing,
michael@0 1260 description + "#2 IME composition was committed unexpectedly");
michael@0 1261 is(gUtils.IMEStatus, gUtils.IME_STATUS_ENABLED,
michael@0 1262 description + "#2 IME isn't enabled on HTML editor");
michael@0 1263
michael@0 1264 editor.flags = flags;
michael@0 1265 ok(editorIMESupport.composing,
michael@0 1266 description + "#3 IME composition was committed unexpectedly");
michael@0 1267 is(gUtils.IMEStatus, gUtils.IME_STATUS_ENABLED,
michael@0 1268 description + "#3 IME isn't enabled on HTML editor");
michael@0 1269
michael@0 1270 // cancel the composition
michael@0 1271 synthesizeComposition({ type: "compositionupdate", data: "" });
michael@0 1272 synthesizeText(
michael@0 1273 { "composition":
michael@0 1274 { "string": "",
michael@0 1275 "clauses":
michael@0 1276 [
michael@0 1277 { "length": 0, "attr": 0 }
michael@0 1278 ]
michael@0 1279 },
michael@0 1280 "caret": { "start": 0, "length": 0 }
michael@0 1281 });
michael@0 1282
michael@0 1283 synthesizeComposition({ type: "compositionend", data: "" });
michael@0 1284
michael@0 1285 container.removeAttribute("contenteditable");
michael@0 1286 }
michael@0 1287
michael@0 1288 function runEditableSubframeTests()
michael@0 1289 {
michael@0 1290 window.open("window_imestate_iframes.html", "_blank",
michael@0 1291 "width=600,height=600");
michael@0 1292 }
michael@0 1293
michael@0 1294 function runTestPasswordFieldOnDialog()
michael@0 1295 {
michael@0 1296 if (!kIMEEnabledSupported) {
michael@0 1297 return;
michael@0 1298 }
michael@0 1299
michael@0 1300 if (document.activeElement) {
michael@0 1301 document.activeElement.blur();
michael@0 1302 }
michael@0 1303
michael@0 1304 var dialog;
michael@0 1305
michael@0 1306 function WindowObserver()
michael@0 1307 {
michael@0 1308 Components.classes["@mozilla.org/observer-service;1"].
michael@0 1309 getService(Components.interfaces.nsIObserverService).
michael@0 1310 addObserver(this, "domwindowopened", false);
michael@0 1311 }
michael@0 1312
michael@0 1313 WindowObserver.prototype = {
michael@0 1314 QueryInterface: function (iid)
michael@0 1315 {
michael@0 1316 if (iid.equals(Components.interfaces.nsIObserver) ||
michael@0 1317 iid.equals(Components.interfaces.nsISupports)) {
michael@0 1318 return this;
michael@0 1319 }
michael@0 1320 },
michael@0 1321
michael@0 1322 observe: function (subject, topic, data)
michael@0 1323 {
michael@0 1324 if (topic === "domwindowopened") {
michael@0 1325 ok(true, "dialog window is created");
michael@0 1326 dialog = subject.QueryInterface(Components.interfaces.nsIDOMWindow);
michael@0 1327 dialog.addEventListener("load", onPasswordDialogLoad, false);
michael@0 1328 }
michael@0 1329 }
michael@0 1330 };
michael@0 1331
michael@0 1332 var observer = new WindowObserver();
michael@0 1333 var arg1 = new Object(), arg2 = new Object();
michael@0 1334 Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
michael@0 1335 getService(Components.interfaces.nsIPromptService).
michael@0 1336 promptPassword(window, "title", "text", arg1, "msg", arg2);
michael@0 1337
michael@0 1338 ok(true, "password dialog was closed");
michael@0 1339
michael@0 1340 Components.classes["@mozilla.org/observer-service;1"].
michael@0 1341 getService(Components.interfaces.nsIObserverService).
michael@0 1342 removeObserver(observer, "domwindowopened");
michael@0 1343
michael@0 1344 var passwordField;
michael@0 1345
michael@0 1346 function onPasswordDialogLoad()
michael@0 1347 {
michael@0 1348 ok(true, "onPasswordDialogLoad is called");
michael@0 1349 dialog.removeEventListener("load", onPasswordDialogLoad, false);
michael@0 1350 passwordField = dialog.document.getElementById("password1Textbox");
michael@0 1351 passwordField.addEventListener("focus", onPasswordFieldFocus, false);
michael@0 1352 }
michael@0 1353
michael@0 1354 function onPasswordFieldFocus()
michael@0 1355 {
michael@0 1356 ok(true, "onPasswordFieldFocus is called");
michael@0 1357 passwordField.removeEventListener("focus", onPasswordFieldFocus, false);
michael@0 1358 var utils = dialog.
michael@0 1359 QueryInterface(Components.interfaces.nsIInterfaceRequestor).
michael@0 1360 getInterface(Components.interfaces.nsIDOMWindowUtils);
michael@0 1361 is(utils.IMEStatus, utils.IME_STATUS_PASSWORD,
michael@0 1362 "IME isn't disabled on a password field of password dialog");
michael@0 1363 synthesizeKey("VK_ESCAPE", { }, dialog);
michael@0 1364 }
michael@0 1365 }
michael@0 1366
michael@0 1367 // Bug 580388 and bug 808287
michael@0 1368 function runEditorReframeTests(aCallback)
michael@0 1369 {
michael@0 1370 if (document.activeElement) {
michael@0 1371 document.activeElement.blur();
michael@0 1372 }
michael@0 1373
michael@0 1374 var input = document.getElementById("text");
michael@0 1375 input.focus();
michael@0 1376 input.style.overflow = "visible";
michael@0 1377
michael@0 1378 var mozIMEFocusIn = 0;
michael@0 1379 var mozIMEFocusOut = 0;
michael@0 1380 var IMEHasFocus = false;
michael@0 1381
michael@0 1382 var handler = function (aEvent) {
michael@0 1383 switch (aEvent.type) {
michael@0 1384 case "MozIMEFocusIn":
michael@0 1385 mozIMEFocusIn++;
michael@0 1386 IMEHasFocus = true;
michael@0 1387 break;
michael@0 1388 case "MozIMEFocusOut":
michael@0 1389 mozIMEFocusOut++;
michael@0 1390 IMEHasFocus = false;
michael@0 1391 break;
michael@0 1392 }
michael@0 1393 };
michael@0 1394
michael@0 1395 var onInput = function (aEvent) {
michael@0 1396 aEvent.target.style.overflow = "hidden";
michael@0 1397 }
michael@0 1398
michael@0 1399 document.addEventListener("MozIMEFocusIn", handler, true);
michael@0 1400 document.addEventListener("MozIMEFocusOut", handler, true);
michael@0 1401 input.addEventListener("input", onInput, true);
michael@0 1402
michael@0 1403 sendChar("a");
michael@0 1404
michael@0 1405 hitEventLoop(function () {
michael@0 1406 ok(mozIMEFocusOut > 0, "runEditorReframeTests(): IME focus must be lost at reframing");
michael@0 1407 ok(mozIMEFocusIn > 0, "runEditorReframeTests(): IME focus must be restored after reframing");
michael@0 1408 ok(IMEHasFocus, "runEditorReframeTests(): IME must have focus after reframing");
michael@0 1409
michael@0 1410 var focusQueryHandler = function(aEvent) {
michael@0 1411 // Perform a style change and query during focus to trigger reframing
michael@0 1412 input.style.overflow = "visible";
michael@0 1413 synthesizeQuerySelectedText();
michael@0 1414 }
michael@0 1415 document.addEventListener("MozIMEFocusIn", focusQueryHandler, true);
michael@0 1416 mozIMEFocusIn = mozIMEFocusOut = 0;
michael@0 1417
michael@0 1418 input.blur();
michael@0 1419 input.focus();
michael@0 1420 sendChar("a");
michael@0 1421
michael@0 1422 hitEventLoop(function() {
michael@0 1423 ok(IMEHasFocus, "runEditorReframeTests(): IME must have focus after reframing during focus");
michael@0 1424 ok(mozIMEFocusOut == mozIMEFocusIn, "runEditorReframeTests(): IME focus/blur (" + mozIMEFocusIn + "/" + mozIMEFocusOut + ") must match after reframing during focus");
michael@0 1425
michael@0 1426 document.removeEventListener("MozIMEFocusIn", focusQueryHandler, true);
michael@0 1427 document.removeEventListener("MozIMEFocusIn", handler, true);
michael@0 1428 document.removeEventListener("MozIMEFocusOut", handler, true);
michael@0 1429 input.removeEventListener("input", onInput, true);
michael@0 1430
michael@0 1431 input.style.overflow = "visible";
michael@0 1432 input.value = "";
michael@0 1433
michael@0 1434 hitEventLoop(aCallback, 20);
michael@0 1435 }, 20);
michael@0 1436 }, 20);
michael@0 1437 }
michael@0 1438
michael@0 1439 function runTests()
michael@0 1440 {
michael@0 1441 if (!kIMEEnabledSupported && !kIMEOpenSupported)
michael@0 1442 return;
michael@0 1443
michael@0 1444 SpecialPowers.setBoolPref("test.IME", true);
michael@0 1445
michael@0 1446 // test for normal contents.
michael@0 1447 runBasicTest(false, false, "Testing of normal contents");
michael@0 1448
michael@0 1449 // test for plugin contents
michael@0 1450 runPluginTest();
michael@0 1451
michael@0 1452 var container = document.getElementById("display");
michael@0 1453 // test for contentEditable="true"
michael@0 1454 container.setAttribute("contenteditable", "true");
michael@0 1455 runBasicTest(true, false, "Testing [contentEditable=\"true\"]");
michael@0 1456
michael@0 1457 // test for contentEditable="false"
michael@0 1458 container.setAttribute("contenteditable", "false");
michael@0 1459 runBasicTest(false, false, "Testing [contentEditable=\"false\"]");
michael@0 1460
michael@0 1461 // test for removing contentEditable
michael@0 1462 container.setAttribute("contenteditable", "true");
michael@0 1463 container.removeAttribute("contenteditable");
michael@0 1464 runBasicTest(false, false, "Testing after contentEditable to be removed");
michael@0 1465
michael@0 1466 // test designMode
michael@0 1467 document.designMode = "on";
michael@0 1468 runBasicTest(true, true, "Testing designMode=\"on\"");
michael@0 1469 document.designMode = "off";
michael@0 1470 document.getElementById("text").focus();
michael@0 1471 runBasicTest(false, false, "Testing designMode=\"off\"");
michael@0 1472
michael@0 1473 // changing input[type] values
michael@0 1474 // XXX currently, type attribute changing doesn't work fine. bug 559728.
michael@0 1475 // runTypeChangingTest();
michael@0 1476
michael@0 1477 // changing readonly attribute
michael@0 1478 runReadonlyChangingTest();
michael@0 1479
michael@0 1480 // complex contenteditable editor's tests
michael@0 1481 runComplexContenteditableTests();
michael@0 1482
michael@0 1483 // test whether the IME state and composition are not changed unexpectedly
michael@0 1484 runEditorFlagChangeTests();
michael@0 1485
michael@0 1486 // test password field on dialog
michael@0 1487 // XXX temporary disable against failure
michael@0 1488 //runTestPasswordFieldOnDialog();
michael@0 1489
michael@0 1490 // Asynchronous tests
michael@0 1491 runEditorReframeTests(function () {
michael@0 1492 // This will call onFinish(), so, this test must be the last.
michael@0 1493 runEditableSubframeTests();
michael@0 1494 });
michael@0 1495 }
michael@0 1496
michael@0 1497 function onFinish()
michael@0 1498 {
michael@0 1499 SpecialPowers.clearUserPref("test.IME");
michael@0 1500 SimpleTest.finish();
michael@0 1501 }
michael@0 1502
michael@0 1503 </script>
michael@0 1504 </body>
michael@0 1505
michael@0 1506 </html>

mercurial