widget/tests/window_imestate_iframes.html

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial