widget/tests/window_imestate_iframes.html

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/widget/tests/window_imestate_iframes.html	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,380 @@
     1.4 +<html>
     1.5 +<head>
     1.6 +  <title>Test for IME state controling and focus moving for iframes</title>
     1.7 +  <script type="text/javascript"
     1.8 +          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
     1.9 +  <link rel="stylesheet" type="text/css"
    1.10 +          href="chrome://mochikit/content/tests/SimpleTest/test.css" />
    1.11 +  <style type="text/css">
    1.12 +    iframe {
    1.13 +      border: none;
    1.14 +      height: 100px;
    1.15 +    }
    1.16 +  </style>
    1.17 +</head>
    1.18 +<body onunload="onUnload();">
    1.19 +<p id="display">
    1.20 +  <!-- Use input[readonly] because it isn't affected by the partial focus
    1.21 +       movement on Mac -->
    1.22 +  <input id="prev" readonly><br>
    1.23 +  <iframe id="iframe_not_editable"
    1.24 +          src="data:text/html,&lt;html&gt;&lt;body&gt;&lt;input id='editor'&gt;&lt;/body&gt;&lt;/html&gt;"></iframe><br>
    1.25 +
    1.26 +  <!-- Testing IME state and focus movement, the anchor elements cannot get focus -->
    1.27 +  <iframe id="iframe_html"
    1.28 +          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>
    1.29 +  <iframe id="iframe_designMode"
    1.30 +          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>
    1.31 +  <iframe id="iframe_body"
    1.32 +          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>
    1.33 +  <iframe id="iframe_p"
    1.34 +          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>
    1.35 +
    1.36 +  <input id="next" readonly><br>
    1.37 +</p>
    1.38 +<script class="testbody" type="application/javascript">
    1.39 +
    1.40 +window.opener.wrappedJSObject.SimpleTest.waitForFocus(runTests, window);
    1.41 +
    1.42 +function ok(aCondition, aMessage)
    1.43 +{
    1.44 +  window.opener.wrappedJSObject.SimpleTest.ok(aCondition, aMessage);
    1.45 +}
    1.46 +
    1.47 +function is(aLeft, aRight, aMessage)
    1.48 +{
    1.49 +  window.opener.wrappedJSObject.SimpleTest.is(aLeft, aRight, aMessage);
    1.50 +}
    1.51 +
    1.52 +function onUnload()
    1.53 +{
    1.54 +  window.opener.wrappedJSObject.onFinish();
    1.55 +}
    1.56 +
    1.57 +var gFocusObservingElement = null;
    1.58 +var gBlurObservingElement = null;
    1.59 +
    1.60 +function onFocus(aEvent)
    1.61 +{
    1.62 +  if (aEvent.target != gFocusObservingElement) {
    1.63 +    return;
    1.64 +  }
    1.65 +  ok(gFocusObservingElement.willFocus,
    1.66 +     "focus event is fired on unexpected element");
    1.67 +  gFocusObservingElement.willFocus = false;
    1.68 +}
    1.69 +
    1.70 +function onBlur(aEvent)
    1.71 +{
    1.72 +  if (aEvent.target != gBlurObservingElement) {
    1.73 +    return;
    1.74 +  }
    1.75 +  ok(gBlurObservingElement.willBlur,
    1.76 +     "blur event is fired on unexpected element");
    1.77 +  gBlurObservingElement.willBlur = false;
    1.78 +}
    1.79 +
    1.80 +function observeFocusBlur(aNextFocusedNode, aWillFireFocusEvent,
    1.81 +                          aNextBlurredNode, aWillFireBlurEvent)
    1.82 +{
    1.83 +  if (gFocusObservingElement) {
    1.84 +    if (gFocusObservingElement.willFocus) {
    1.85 +      ok(false, "focus event was never fired on " + gFocusObservingElement);
    1.86 +    }
    1.87 +    gFocusObservingElement.removeEventListener("focus", onFocus, true);
    1.88 +    gFocusObservingElement.willFocus = NaN;
    1.89 +    gFocusObservingElement = null;
    1.90 +  }
    1.91 +  if (gBlurObservingElement) {
    1.92 +    if (gBlurObservingElement.willBlur) {
    1.93 +      ok(false, "blur event was never fired on " + gBlurObservingElement);
    1.94 +    }
    1.95 +    gBlurObservingElement.removeEventListener("blur", onBlur, true);
    1.96 +    gBlurObservingElement.willBlur = NaN;
    1.97 +    gBlurObservingElement = null;
    1.98 +  }
    1.99 +  if (aNextFocusedNode) {
   1.100 +    gFocusObservingElement = aNextFocusedNode;
   1.101 +    gFocusObservingElement.willFocus = aWillFireFocusEvent;
   1.102 +    gFocusObservingElement.addEventListener("focus", onFocus, true);
   1.103 +  }
   1.104 +  if (aNextBlurredNode) {
   1.105 +    gBlurObservingElement = aNextBlurredNode;
   1.106 +    gBlurObservingElement.willBlur = aWillFireBlurEvent;
   1.107 +    gBlurObservingElement.addEventListener("blur", onBlur, true);
   1.108 +  }
   1.109 +}
   1.110 +
   1.111 +function runTests()
   1.112 +{
   1.113 +  var utils =
   1.114 +    window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
   1.115 +          .getInterface(Components.interfaces.nsIDOMWindowUtils);
   1.116 +  var fm =
   1.117 +    Components.classes["@mozilla.org/focus-manager;1"]
   1.118 +              .getService(Components.interfaces.nsIFocusManager);
   1.119 +
   1.120 +  var iframe, editor, root, input;
   1.121 +  var prev = document.getElementById("prev");
   1.122 +  var next = document.getElementById("next");
   1.123 +  var html = document.documentElement;
   1.124 +
   1.125 +  function resetFocusToInput(aDescription)
   1.126 +  {
   1.127 +    observeFocusBlur(null, false, null, false);
   1.128 +    prev.focus();
   1.129 +    is(fm.focusedElement, prev,
   1.130 +       "input#prev[readonly] element didn't get focus: " + aDescription);
   1.131 +    is(utils.IMEStatus, utils.IME_STATUS_DISABLED,
   1.132 +       "IME enabled on input#prev[readonly]: " + aDescription);
   1.133 +  }
   1.134 +
   1.135 +  function resetFocusToParentHTML(aDescription)
   1.136 +  {
   1.137 +    observeFocusBlur(null, false, null, false);
   1.138 +    html.focus();
   1.139 +    is(fm.focusedElement, html,
   1.140 +       "Parent html element didn't get focus: " + aDescription);
   1.141 +    is(utils.IMEStatus, utils.IME_STATUS_DISABLED,
   1.142 +       "IME enabled on parent html element: " + aDescription);
   1.143 +  }
   1.144 +
   1.145 +  function testTabKey(aForward,
   1.146 +                      aNextFocusedNode, aWillFireFocusEvent,
   1.147 +                      aNextBlurredNode, aWillFireBlurEvent,
   1.148 +                      aIMEShouldBeEnabled, aTestingCaseDescription)
   1.149 +  {
   1.150 +    observeFocusBlur(aNextFocusedNode, aWillFireFocusEvent,
   1.151 +                     aNextBlurredNode, aWillFireBlurEvent);
   1.152 +    synthesizeKey("VK_TAB", { shiftKey: !aForward });
   1.153 +    var description = "Tab key test: ";
   1.154 +    if (!aForward) {
   1.155 +      description = "Shift-" + description;
   1.156 +    }
   1.157 +    description += aTestingCaseDescription + ": ";
   1.158 +    is(fm.focusedElement, aNextFocusedNode,
   1.159 +       description + "didn't move focus as expected");
   1.160 +    is(utils.IMEStatus,
   1.161 +       aIMEShouldBeEnabled ?
   1.162 +         utils.IME_STATUS_ENABLED : utils.IME_STATUS_DISABLED,
   1.163 +       description + "didn't set IME state as expected");
   1.164 +  }
   1.165 +
   1.166 +  function testMouseClick(aNextFocusedNode, aWillFireFocusEvent,
   1.167 +                          aWillAllNodeLostFocus,
   1.168 +                          aNextBlurredNode, aWillFireBlurEvent,
   1.169 +                          aIMEShouldBeEnabled, aTestingCaseDescription)
   1.170 +  {
   1.171 +    observeFocusBlur(aNextFocusedNode, aWillFireFocusEvent,
   1.172 +                     aNextBlurredNode, aWillFireBlurEvent);
   1.173 +    // We're relying on layout inside the iframe being up to date, so make it so
   1.174 +    iframe.contentDocument.documentElement.getBoundingClientRect();
   1.175 +    synthesizeMouse(iframe, 10, 80, { });
   1.176 +    var description = "Click test: " + aTestingCaseDescription + ": ";
   1.177 +    is(fm.focusedElement, !aWillAllNodeLostFocus ? aNextFocusedNode : null,
   1.178 +       description + "didn't move focus as expected");
   1.179 +    is(utils.IMEStatus,
   1.180 +       aIMEShouldBeEnabled ?
   1.181 +         utils.IME_STATUS_ENABLED : utils.IME_STATUS_DISABLED,
   1.182 +       description + "didn't set IME state as expected");
   1.183 +  }
   1.184 +
   1.185 +  function testOnEditorFlagChange(aDescription, aIsInDesignMode)
   1.186 +  {
   1.187 +    const kReadonly =
   1.188 +      Components.interfaces.nsIPlaintextEditor.eEditorReadonlyMask;
   1.189 +    var description = "testOnEditorFlagChange: " + aDescription;
   1.190 +    resetFocusToParentHTML(description);
   1.191 +    var htmlEditor =
   1.192 +      iframe.contentWindow.
   1.193 +        QueryInterface(Components.interfaces.nsIInterfaceRequestor).
   1.194 +        getInterface(Components.interfaces.nsIWebNavigation).
   1.195 +        QueryInterface(Components.interfaces.nsIDocShell).editor;
   1.196 +    var e = aIsInDesignMode ? root : editor;
   1.197 +    e.focus();
   1.198 +    is(fm.focusedElement, e,
   1.199 +       description + ": focus() of editor didn't move focus as expected");
   1.200 +    is(utils.IMEStatus, utils.IME_STATUS_ENABLED,
   1.201 +       description + ": IME isn't enabled when the editor gets focus");
   1.202 +    var flags = htmlEditor.flags;
   1.203 +    htmlEditor.flags |= kReadonly;
   1.204 +    is(fm.focusedElement, e,
   1.205 +       description + ": when editor becomes readonly, focus moved unexpectedly");
   1.206 +    is(utils.IMEStatus, utils.IME_STATUS_DISABLED,
   1.207 +       description + ": when editor becomes readonly, IME is still enabled");
   1.208 +    htmlEditor.flags = flags;
   1.209 +    is(fm.focusedElement, e,
   1.210 +       description + ": when editor becomes read-write, focus moved unexpectedly");
   1.211 +    is(utils.IMEStatus, utils.IME_STATUS_ENABLED,
   1.212 +       description + ": when editor becomes read-write, IME is still disabled");
   1.213 +  }
   1.214 +
   1.215 +  // hide all iframes
   1.216 +  document.getElementById("iframe_not_editable").style.display = "none";
   1.217 +  document.getElementById("iframe_html").style.display = "none";
   1.218 +  document.getElementById("iframe_designMode").style.display = "none";
   1.219 +  document.getElementById("iframe_body").style.display = "none";
   1.220 +  document.getElementById("iframe_p").style.display = "none";
   1.221 +
   1.222 +  // non editable HTML element and input element can get focus.
   1.223 +  iframe = document.getElementById("iframe_not_editable");
   1.224 +  iframe.style.display = "inline";
   1.225 +  editor = iframe.contentDocument.getElementById("editor");
   1.226 +  root = iframe.contentDocument.documentElement;
   1.227 +  resetFocusToInput("initializing for iframe_not_editable");
   1.228 +
   1.229 +  testTabKey(true, root, false, prev, true,
   1.230 +             false, "input#prev[readonly] -> html");
   1.231 +  testTabKey(true, editor, true, root, false,
   1.232 +             true, "html -> input in the subdoc");
   1.233 +  testTabKey(true, next, true, editor, true,
   1.234 +             false, "input in the subdoc -> input#next[readonly]");
   1.235 +  testTabKey(false, editor, true, next, true,
   1.236 +             true, "input#next[readonly] -> input in the subdoc");
   1.237 +  testTabKey(false, root, false, editor, true,
   1.238 +             false, "input in the subdoc -> html");
   1.239 +  testTabKey(false, prev, true, root, false,
   1.240 +             false, "html -> input#next[readonly]");
   1.241 +
   1.242 +  iframe.style.display = "none";
   1.243 +
   1.244 +  // HTML element (of course, it's root) must enables IME.
   1.245 +  iframe = document.getElementById("iframe_html");
   1.246 +  iframe.style.display = "inline";
   1.247 +  editor = iframe.contentDocument.getElementById("editor");
   1.248 +  root = iframe.contentDocument.documentElement;
   1.249 +  resetFocusToInput("initializing for iframe_html");
   1.250 +
   1.251 +  testTabKey(true, editor, true, prev, true,
   1.252 +             true, "input#prev[readonly] -> html[contentediable=true]");
   1.253 +  testTabKey(true, next, true, editor, true,
   1.254 +             false, "html[contentediable=true] -> input#next[readonly]");
   1.255 +  testTabKey(false, editor, true, next, true,
   1.256 +             true, "input#next[readonly] -> html[contentediable=true]");
   1.257 +  testTabKey(false, prev, true, editor, true,
   1.258 +             false, "html[contenteditable=true] -> input[readonly]");
   1.259 +
   1.260 +  prev.style.display = "none";
   1.261 +  resetFocusToParentHTML("testing iframe_html");
   1.262 +  testTabKey(true, editor, true, html, false,
   1.263 +             true, "html of parent -> html[contentediable=true]");
   1.264 +  testTabKey(false, html, false, editor, true,
   1.265 +             false, "html[contenteditable=true] -> html of parent");
   1.266 +  prev.style.display = "inline";
   1.267 +  resetFocusToInput("after parent html <-> html[contenteditable=true]");
   1.268 +
   1.269 +  testMouseClick(editor, true, false, prev, true, true, "iframe_html");
   1.270 +
   1.271 +  testOnEditorFlagChange("html[contentediable=true]", false);
   1.272 +
   1.273 +  iframe.style.display = "none";
   1.274 +
   1.275 +  // designMode should behave like <html contenteditable="true"></html>
   1.276 +  // but focus/blur events shouldn't be fired on its root element because
   1.277 +  // any elements shouldn't be focused state in designMode.
   1.278 +  iframe = document.getElementById("iframe_designMode");
   1.279 +  iframe.style.display = "inline";
   1.280 +  iframe.contentDocument.designMode = "on";
   1.281 +  editor = iframe.contentDocument.getElementById("editor");
   1.282 +  root = iframe.contentDocument.documentElement;
   1.283 +  resetFocusToInput("initializing for iframe_designMode");
   1.284 +
   1.285 +  testTabKey(true, root, false, prev, true,
   1.286 +             true, "input#prev[readonly] -> html in designMode");
   1.287 +  testTabKey(true, next, true, root, false,
   1.288 +             false, "html in designMode -> input#next[readonly]");
   1.289 +  testTabKey(false, root, false, next, true,
   1.290 +             true, "input#next[readonly] -> html in designMode");
   1.291 +  testTabKey(false, prev, true, root, false,
   1.292 +             false, "html in designMode -> input#prev[readonly]");
   1.293 +
   1.294 +  prev.style.display = "none";
   1.295 +  resetFocusToParentHTML("testing iframe_designMode");
   1.296 +  testTabKey(true, root, false, html, false,
   1.297 +             true, "html of parent -> html in designMode");
   1.298 +  testTabKey(false, html, false, root, false,
   1.299 +             false, "html in designMode -> html of parent");
   1.300 +  prev.style.display = "inline";
   1.301 +  resetFocusToInput("after parent html <-> html in designMode");
   1.302 +
   1.303 +  testMouseClick(editor, false, true, prev, true, true, "iframe_designMode");
   1.304 +
   1.305 +  testOnEditorFlagChange("html in designMode", true);
   1.306 +
   1.307 +  iframe.style.display = "none";
   1.308 +
   1.309 +  // When there is no HTML element but the BODY element is editable,
   1.310 +  // the body element should get focus and enables IME.
   1.311 +  iframe = document.getElementById("iframe_body");
   1.312 +  iframe.style.display = "inline";
   1.313 +  editor = iframe.contentDocument.getElementById("editor");
   1.314 +  root = iframe.contentDocument.documentElement;
   1.315 +  resetFocusToInput("initializing for iframe_body");
   1.316 +
   1.317 +  testTabKey(true, editor, true, prev, true,
   1.318 +             true, "input#prev[readonly] -> body[contentediable=true]");
   1.319 +  testTabKey(true, next, true, editor, true,
   1.320 +             false, "body[contentediable=true] -> input#next[readonly]");
   1.321 +  testTabKey(false, editor, true, next, true,
   1.322 +             true, "input#next[readonly] -> body[contentediable=true]");
   1.323 +  testTabKey(false, prev, true, editor, true,
   1.324 +             false, "body[contenteditable=true] -> input#prev[readonly]");
   1.325 +
   1.326 +  prev.style.display = "none";
   1.327 +  resetFocusToParentHTML("testing iframe_body");
   1.328 +  testTabKey(true, editor, true, html, false,
   1.329 +             true, "html of parent -> body[contentediable=true]");
   1.330 +  testTabKey(false, html, false, editor, true,
   1.331 +             false, "body[contenteditable=true] -> html of parent");
   1.332 +  prev.style.display = "inline";
   1.333 +  resetFocusToInput("after parent html <-> body[contenteditable=true]");
   1.334 +
   1.335 +  testMouseClick(editor, true, false, prev, true, true, "iframe_body");
   1.336 +
   1.337 +  testOnEditorFlagChange("body[contentediable=true]", false);
   1.338 +
   1.339 +  iframe.style.display = "none";
   1.340 +
   1.341 +  // When HTML/BODY elements are not editable, focus shouldn't be moved to
   1.342 +  // the editable content directly.
   1.343 +  iframe = document.getElementById("iframe_p");
   1.344 +  iframe.style.display = "inline";
   1.345 +  editor = iframe.contentDocument.getElementById("editor");
   1.346 +  root = iframe.contentDocument.documentElement;
   1.347 +  resetFocusToInput("initializing for iframe_p");
   1.348 +
   1.349 +  testTabKey(true, root, false, prev, true,
   1.350 +             false, "input#prev[readonly] -> html (has p[contenteditable=true])");
   1.351 +  testTabKey(true, editor, true, root, false,
   1.352 +             true, "html (has p[contenteditable=true]) -> p[contentediable=true]");
   1.353 +  testTabKey(true, next, true, editor, true,
   1.354 +             false, "p[contentediable=true] -> input#next[readonly]");
   1.355 +  testTabKey(false, editor, true, next, true,
   1.356 +             true, "input#next[readonly] -> p[contentediable=true]");
   1.357 +  testTabKey(false, root, false, editor, true,
   1.358 +             false, "p[contenteditable=true] -> html (has p[contenteditable=true])");
   1.359 +  testTabKey(false, prev, true, root, false,
   1.360 +             false, "html (has p[contenteditable=true]) -> input#prev[readonly]");
   1.361 +  prev.style.display = "none";
   1.362 +
   1.363 +  resetFocusToParentHTML("testing iframe_p");
   1.364 +  testTabKey(true, root, false, html, false,
   1.365 +             false, "html of parent -> html (has p[contentediable=true])");
   1.366 +  testTabKey(false, html, false, root, false,
   1.367 +             false, "html (has p[contentediable=true]) -> html of parent");
   1.368 +  prev.style.display = "inline";
   1.369 +  resetFocusToInput("after parent html <-> html (has p[contentediable=true])");
   1.370 +
   1.371 +  testMouseClick(root, false, true, prev, true, false, "iframe_p");
   1.372 +
   1.373 +  testOnEditorFlagChange("p[contenteditable=true]", false);
   1.374 +
   1.375 +  iframe.style.display = "none";
   1.376 +
   1.377 +  window.close();
   1.378 +}
   1.379 +
   1.380 +</script>
   1.381 +</body>
   1.382 +
   1.383 +</html>

mercurial