Tue, 06 Jan 2015 21:39:09 +0100
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.
1 <?xml version="1.0"?>
2 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
3 <?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
4 type="text/css"?>
5 <!--
6 This test checks focus in various ways
7 -->
8 <window id="outer-document" title="Focus Test" width="600" height="550"
9 xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
10 <script type="application/javascript"
11 src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
12 <script type="application/javascript"
13 src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
15 <body xmlns="http://www.w3.org/1999/xhtml"/>
17 <script type="application/javascript"><![CDATA[
19 var fm = Components.classes["@mozilla.org/focus-manager;1"].
20 getService(Components.interfaces.nsIFocusManager);
22 const kChildDocumentRootIndex = 13;
23 const kBeforeTabboxIndex = 34;
24 const kTabbableSteps = 38;
25 const kFocusSteps = 26;
26 const kNoFocusSteps = 7;
27 const kOverflowElementIndex = 27;
29 var gTestStarted = false;
30 var gPartialTabbing = false;
31 var gMoveToFocusFrame = false;
32 var gLastFocus = null;
33 var gLastFocusWindow = window;
34 var gLastFocusMethod = -1;
35 var gEvents = "";
36 var gExpectedEvents = "";
37 var gEventMatched = true;
38 var gShowOutput = false;
39 var gChildWindow = null;
41 var gOldExpectedWindow = null;
42 var gNewExpectedWindow = null;
44 function is(l, r, n) { window.opener.wrappedJSObject.SimpleTest.is(l,r,n); }
45 function ok(v, n) { window.opener.wrappedJSObject.SimpleTest.ok(v,n); }
47 function initEvents(target)
48 {
49 target.addEventListener("focus", eventOccured, true);
50 target.addEventListener("blur", eventOccured, true);
51 getTopWindow(target).addEventListener("activate", eventOccured, true);
52 getTopWindow(target).addEventListener("deactivate", eventOccured, true);
53 }
55 function eventOccured(event)
56 {
57 // iframes should never receive focus or blur events directly
58 if (event.target instanceof Element && event.target.localName == "iframe")
59 ok(false, "iframe " + event.type + "occured");
61 var id;
62 if (gOldExpectedWindow && event.type == "blur") {
63 if (event.target instanceof Window)
64 id = "frame-" + gOldExpectedWindow.document.documentElement.id + "-window";
65 else if (event.target instanceof Document)
66 id = "frame-" + gOldExpectedWindow.document.documentElement.id + "-document";
67 else
68 id = event.originalTarget.id;
69 }
70 else if (gNewExpectedWindow && event.type == "focus") {
71 if (event.target instanceof Window)
72 id = "frame-" + gNewExpectedWindow.document.documentElement.id + "-window";
73 else if (event.target instanceof Document)
74 id = "frame-" + gNewExpectedWindow.document.documentElement.id + "-document";
75 else
76 id = event.originalTarget.id;
77 }
78 else if (event.type == "activate" || event.type == "deactivate")
79 id = event.target.document.documentElement.id + "-window";
80 else if (event.target instanceof Window)
81 id = (event.target == window) ? "outer-window" : "child-window";
82 else if (event.target instanceof Document)
83 id = (event.target == document) ? "outer-document" : "child-document";
84 else
85 id = event.originalTarget.id;
87 if (gEvents)
88 gEvents += " ";
89 gEvents += event.type + ": " + id;
90 }
92 function expectFocusShift(callback, expectedWindow, expectedElement, focusChanged, testid)
93 {
94 if (expectedWindow == null)
95 expectedWindow = expectedElement ?
96 expectedElement.ownerDocument.defaultView :
97 gLastFocusWindow;
99 var expectedEvents = "";
100 if (focusChanged) {
101 var id;
102 if (getTopWindow(gLastFocusWindow) != getTopWindow(expectedWindow)) {
103 id = getTopWindow(gLastFocusWindow).document.documentElement.id;
104 expectedEvents += "deactivate: " + id + "-window";
105 }
107 if (gLastFocus && gLastFocus.id != "t" + kChildDocumentRootIndex &&
108 (!gOldExpectedWindow || gOldExpectedWindow.document.documentElement != gLastFocus)) {
109 if (expectedEvents)
110 expectedEvents += " ";
111 if (!gOldExpectedWindow)
112 expectedEvents += "commandupdate: cu ";
113 expectedEvents += "blur: " + gLastFocus.id;
114 }
116 if (gLastFocusWindow && gLastFocusWindow != expectedWindow) {
117 if (!gMoveToFocusFrame) {
118 if (gOldExpectedWindow)
119 id = "frame-" + gOldExpectedWindow.document.documentElement.id;
120 else
121 id = (gLastFocusWindow == window) ? "outer" : "child";
122 if (expectedEvents)
123 expectedEvents += " ";
124 expectedEvents += "blur: " + id + "-document " +
125 "blur: " + id + "-window";
126 }
127 }
129 if (getTopWindow(gLastFocusWindow) != getTopWindow(expectedWindow)) {
130 id = getTopWindow(expectedWindow).document.documentElement.id;
131 if (expectedEvents)
132 expectedEvents += " ";
133 expectedEvents += "activate: " + id + "-window";
134 }
136 if (expectedWindow && gLastFocusWindow != expectedWindow) {
137 if (gNewExpectedWindow)
138 id = "frame-" + gNewExpectedWindow.document.documentElement.id;
139 else
140 id = (expectedWindow == window) ? "outer" : "child";
141 if (expectedEvents)
142 expectedEvents += " ";
143 expectedEvents += "focus: " + id + "-document " +
144 "focus: " + id + "-window";
145 }
147 // for this test which fires a mouse event on a label, the document will
148 // be focused first and then the label code will focus the related
149 // control. This doesn't result in different focus events, but a command
150 // update will occur for the document and then a secon command update will
151 // occur when the control is focused.
152 if (testid == "mouse on html label with content inside")
153 expectedEvents += " commandupdate: cu";
155 if (expectedElement &&
156 (!gNewExpectedWindow || gNewExpectedWindow.document.documentElement != expectedElement)) {
157 if (!gNewExpectedWindow) {
158 if (expectedEvents)
159 expectedEvents += " ";
160 expectedEvents += "commandupdate: cu";
161 }
162 if (expectedElement.id != "t" + kChildDocumentRootIndex) {
163 if (expectedEvents)
164 expectedEvents += " ";
165 expectedEvents += "focus: " + expectedElement.id;
166 }
167 }
168 else if (expectedWindow && gLastFocusWindow != expectedWindow &&
169 !expectedElement) {
170 if (expectedEvents)
171 expectedEvents += " ";
172 expectedEvents += "commandupdate: cu";
173 }
174 }
176 gLastFocus = expectedElement;
177 gLastFocusWindow = expectedWindow;
179 callback();
181 compareEvents(expectedEvents, expectedWindow, expectedElement, testid);
182 }
184 function compareEvents(expectedEvents, expectedWindow, expectedElement, testid)
185 {
186 if (!gShowOutput) {
187 gEvents = "";
188 return;
189 }
191 is(gEvents, expectedEvents, testid + " events");
192 gEvents = "";
194 var doc;
195 if (expectedWindow == window)
196 doc = "outer-document";
197 else if (expectedWindow == gChildWindow)
198 doc = "inner-document";
199 else if (gNewExpectedWindow)
200 doc = gNewExpectedWindow.document.body ? gNewExpectedWindow.document.body.id :
201 gNewExpectedWindow.document.documentElement.id;
202 else
203 doc = "other-document";
205 var focusedElement = fm.focusedElement;
206 is(focusedElement ? focusedElement.id : "none",
207 expectedElement ? expectedElement.id : "none", testid + " focusedElement");
208 is(fm.focusedWindow, expectedWindow, testid + " focusedWindow");
209 var focusedWindow = {};
210 is(fm.getFocusedElementForWindow(expectedWindow, false, focusedWindow),
211 expectedElement, testid + " getFocusedElementForWindow");
212 is(focusedWindow.value, expectedWindow, testid + " getFocusedElementForWindow frame");
213 is(expectedWindow.document.hasFocus(), true, testid + " hasFocus");
214 is(expectedWindow.document.activeElement ? expectedWindow.document.activeElement.id : "none",
215 expectedElement ? expectedElement.id : doc, testid + " activeElement");
216 var cdwindow = getTopWindow(expectedWindow);
217 if (cdwindow.document.commandDispatcher) {
218 is(cdwindow.document.commandDispatcher.focusedWindow, expectedWindow, testid + " commandDispatcher focusedWindow");
219 is(cdwindow.document.commandDispatcher.focusedElement, focusedElement, testid + " commandDispatcher focusedElement");
220 }
222 if (gLastFocusMethod != -1) {
223 is(fm.getLastFocusMethod(null), gLastFocusMethod, testid + " lastFocusMethod null");
224 is(fm.getLastFocusMethod(expectedWindow), gLastFocusMethod, testid + " lastFocusMethod window");
225 }
227 // the parent should have the iframe focused
228 if (doc == "inner-document") {
229 is(document.hasFocus(), true, testid + " hasFocus");
230 is(fm.getFocusedElementForWindow(window, false, focusedWindow),
231 $("childframe"), testid + " getFocusedElementForWindow for parent");
232 is(focusedWindow.value, window, testid + " getFocusedElementForWindow for parent frame");
233 is(fm.getFocusedElementForWindow(window, true, focusedWindow),
234 expectedElement, testid + " getFocusedElementForWindow deep for parent");
235 is(focusedWindow.value, gChildWindow, testid + " getFocusedElementForWindow deep for parent frame");
236 is(document.activeElement.id, "childframe", testid + " activeElement for parent");
237 }
239 // compare the selection for the child window. Skip mouse tests as the caret
240 // is adjusted by the selection code for mouse clicks, and not the focus code.
241 if (expectedWindow == window) {
242 var selection = window.getSelection();
243 ok(selection.focusNode == null && selection.focusOffset == 0 &&
244 selection.anchorNode == null && selection.anchorOffset == 0, testid + " selection");
245 }
246 else if ((expectedWindow == gChildWindow) && !testid.indexOf("mouse") == -1) {
247 checkSelection(expectedElement, testid);
248 }
249 }
251 function checkSelection(node, testid)
252 {
253 var selection = gChildWindow.getSelection();
255 var range = gChildWindow.document.createRange();
256 range.selectNodeContents(node);
257 if (!node.firstChild || node.localName == "input" ||
258 node.localName == "select" || node.localName == "button") {
259 range.setStartBefore(node);
260 range.setEndBefore(node);
261 }
263 if (node.firstChild)
264 range.setEnd(range.startContainer, range.startOffset);
266 is(selection.focusNode, range.startContainer, testid + " selection focusNode");
267 is(selection.focusOffset, range.startOffset, testid + " selection focusOffset");
268 is(selection.anchorNode, range.endContainer, testid + " selection anchorNode");
269 is(selection.anchorOffset, range.endOffset, testid + " selection anchorOffset");
270 }
272 function getTopWindow(win)
273 {
274 return win.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
275 getInterface(Components.interfaces.nsIWebNavigation).
276 QueryInterface(Components.interfaces.nsIDocShellTreeItem).rootTreeItem.
277 QueryInterface(Components.interfaces.nsIInterfaceRequestor).
278 getInterface(Components.interfaces.nsIDOMWindow);
279 }
281 function mouseOnElement(element, expectedElement, focusChanged, testid)
282 {
283 var expectedWindow = (element.ownerDocument.defaultView == gChildWindow) ? gChildWindow : window;
284 // on Mac, form elements are not focused when clicking, except for lists and textboxes.
285 var noFocusOnMouse = (navigator.platform.indexOf("Mac") == 0);
286 if (noFocusOnMouse) {
287 if (element.namespaceURI == "http://www.w3.org/1999/xhtml") {
288 // links are special. They can be focused but show no focus ring
289 if (element.localName == "a" || element.localName == "div" ||
290 element.localName == "select" ||
291 element.localName == "input" && (element.type == "text" ||
292 element.type == "password")) {
293 noFocusOnMouse = false;
294 }
295 }
296 else if (element.localName == "listbox") {
297 noFocusOnMouse = false;
298 }
299 }
301 if (noFocusOnMouse) {
302 // no focus so the last focus method will be 0
303 gLastFocusMethod = 0;
304 expectFocusShift(function () synthesizeMouse(element, 4, 4, { }, element.ownerDocument.defaultView),
305 expectedWindow, null, true, testid);
306 gLastFocusMethod = fm.FLAG_BYMOUSE;
307 }
308 else {
309 expectFocusShift(function () synthesizeMouse(element, 4, 4, { }, element.ownerDocument.defaultView),
310 element.ownerDocument.defaultView,
311 expectedElement, focusChanged, testid);
312 }
313 }
315 function done()
316 {
317 var opener = window.opener;
318 window.close();
319 opener.wrappedJSObject.SimpleTest.finish();
320 }
322 var pressTab = function () synthesizeKey("VK_TAB", { });
324 function setFocusTo(id, fwindow)
325 {
326 gLastFocus = getById(id);
327 gLastFocusWindow = fwindow;
328 if (gLastFocus)
329 gLastFocus.focus();
330 else
331 fm.clearFocus(fwindow);
332 gEvents = "";
333 }
335 function getById(id)
336 {
337 if (gNewExpectedWindow)
338 return gNewExpectedWindow.document.getElementById(id);
339 var element = $(id);
340 if (!element)
341 element = $("childframe").contentDocument.getElementById(id);
342 return element;
343 }
345 function startTest()
346 {
347 if (gTestStarted)
348 return;
349 gTestStarted = true;
351 gChildWindow = $("childframe").contentWindow;
352 gShowOutput = true;
354 // synthesize a mousemove over the image to ensure that the imagemap data is
355 // created. Otherwise, the special imagemap frames might not exist, and
356 // won't be focusable.
357 synthesizeMouse(getById("image"), 4, 4, { type: "mousemove" }, gChildWindow);
359 initEvents(window);
361 is(fm.activeWindow, window, "activeWindow");
362 is(gChildWindow.document.hasFocus(), false, " child document hasFocus");
364 // test to see if the Mac Full Keyboard Access setting is set. If t3 is
365 // focused after tab is pressed, then it is set to textboxes and lists only.
366 // Otherwise, all elements are in the tab order.
367 pressTab();
369 if (fm.focusedElement.id == "t3")
370 gPartialTabbing = true;
371 else
372 is(fm.focusedElement.id, "t1", "initial tab key");
374 is(fm.getLastFocusMethod(null), fm.FLAG_BYKEY, "last focus method null start");
375 is(fm.getLastFocusMethod(window), fm.FLAG_BYKEY, "last focus method window start");
377 fm.clearFocus(window);
378 gEvents = "";
380 gLastFocusMethod = fm.FLAG_BYKEY;
381 if (gPartialTabbing) {
382 var partialTabList = ["t3", "t5", "t9", "t10", "t11", "t12", "t13", "t14", "t15",
383 "t16", "t19", "t20", "t21", "t22", "t26", "t27", "t28", "t29", "t30"];
384 for (var idx = 0; idx < partialTabList.length; idx++) {
385 expectFocusShift(pressTab, null, getById(partialTabList[idx]), true, "partial tab key " + partialTabList[idx]);
386 }
387 setFocusTo("last", window);
388 expectFocusShift(pressTab, null, getById(partialTabList[0]), true, "partial tab key wrap to start");
389 expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }),
390 null, getById("last"), true, "partial shift tab key wrap to end");
391 for (var idx = partialTabList.length - 1; idx >= 0; idx--) {
392 expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }),
393 null, getById(partialTabList[idx]), true, "partial tab key " + partialTabList[idx]);
394 }
395 }
396 else {
397 // TAB key
398 for (var idx = 1; idx <= kTabbableSteps; idx++) {
399 expectFocusShift(pressTab, null, getById("t" + idx), true, "tab key t" + idx);
400 }
402 // wrapping around at end with TAB key
403 setFocusTo("last", window);
404 expectFocusShift(pressTab, null, getById("t1"), true, "tab key wrap to start");
405 expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }),
406 null, getById("last"), true, "shift tab key wrap to end");
408 // Shift+TAB key
409 setFocusTo("o5", window);
410 for (idx = kTabbableSteps; idx > 0; idx--) {
411 expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }),
412 null, getById("t" + idx), true, "shift tab key t" + idx);
413 }
414 }
416 var t19 = getById("t19");
417 is(t19.selectionStart, 0, "input focused from tab key selectionStart");
418 is(t19.selectionEnd, 5, "input focused from tab key selectionEnd");
419 t19.setSelectionRange(0, 0);
421 gLastFocusMethod = 0;
422 var selectFired = false;
423 function selectListener() { selectFired = true; }
424 t19.addEventListener("select", selectListener, false);
425 expectFocusShift(function() t19.select(),
426 null, getById("t" + 19), true, "input.select()");
427 t19.removeEventListener("select", selectListener, false);
428 ok(selectFired, "select event fires for input");
430 // mouse clicking
431 gLastFocusMethod = fm.FLAG_BYMOUSE;
432 for (idx = kTabbableSteps; idx >= 1; idx--) {
433 // skip the document root and the overflow element
434 if (idx == kChildDocumentRootIndex || idx == kOverflowElementIndex)
435 continue;
436 if ((navigator.platform.indexOf("Mac") == 0) && (idx == kBeforeTabboxIndex + 1))
437 continue;
439 var element = getById("t" + idx);
440 // skip area elements, as getBoundingClientRect doesn't return their actual coordinates
441 if (element.localName == "area")
442 continue;
444 mouseOnElement(element, getById("t" + idx), true, "mouse on element t" + idx);
445 var expectedWindow = (element.ownerDocument.defaultView == gChildWindow) ? gChildWindow : window;
446 if (element.localName == "listbox" && expectedWindow == window &&
447 navigator.platform.indexOf("Mac") == 0) {
448 // after focusing a listbox on Mac, clear the focus before continuing.
449 setFocusTo(null, window);
450 }
451 }
453 is(t19.selectionStart, 0, "input focused from mouse selectionStart");
454 is(t19.selectionEnd, 0, "input focused from mouse selectionEnd");
456 // mouse clicking on elements that are not tabbable
457 for (idx = 1; idx <= kFocusSteps; idx++) {
458 var element = getById("o" + (idx % 2 ? idx : idx - 1));
460 mouseOnElement(element, element, idx % 2,
461 "mouse on non-tabbable element o" + idx);
462 }
464 // mouse clicking on elements that are not tabbable and have user-focus: none
465 // or are not focusable for other reasons (for instance, being disabled)
466 // These elements will clear the focus when clicked.
467 for (idx = 1; idx <= kNoFocusSteps; idx++) {
468 var element = getById("n" + idx);
469 gLastFocusMethod = idx % 2 ? 0 : fm.FLAG_BYMOUSE;
471 mouseOnElement(element, idx % 2 ? null: element, true, "mouse on unfocusable element n" + idx);
472 }
474 if (idx == kOverflowElementIndex) {
475 gLastFocusMethod = fm.FLAG_BYMOUSE;
476 var element = getById("t" + idx);
477 expectFocusShift(function () synthesizeMouse(element, 4, 4, { }, element.ownerDocument.defaultView),
478 window, null, true, "mouse on scrollable element");
479 }
481 // focus() method
482 gLastFocusMethod = 0;
483 for (idx = kTabbableSteps; idx >= 1; idx--) {
484 if ((navigator.platform.indexOf("Mac") == 0) && (idx == kBeforeTabboxIndex + 1))
485 continue;
486 expectFocusShift(function () getById("t" + idx).focus(),
487 null, getById("t" + idx), true, "focus method on element t" + idx);
488 }
490 $("t1").focus();
491 ok(gEvents === "", "focusing element that is already focused");
493 $("t2").blur();
494 $("t7").blur();
495 ok(gEvents === "", "blurring element that is not focused");
496 is(document.activeElement, $("t1"), "old element still focused after blur() on another element");
498 // focus() method on elements that are not tabbable
499 for (idx = 1; idx <= kFocusSteps; idx++) {
500 var expected = getById("o" + (idx % 2 ? idx : idx - 1));
501 expectFocusShift(function () getById("o" + idx).focus(),
502 expected.ownerDocument.defaultView,
503 expected, idx % 2, "focus method on non-tabbable element o" + idx);
504 }
506 // focus() method on elements that are not tabbable and have user-focus: none
507 // or are not focusable for other reasons (for instance, being disabled)
508 for (idx = 1; idx <= kNoFocusSteps; idx++) {
509 var expected = getById("o" + (idx % 2 ? idx : idx - 1));
510 expectFocusShift(function () getById("o" + idx).focus(),
511 expected.ownerDocument.defaultView,
512 expected, idx % 2, "focus method on unfocusable element n" + idx);
513 }
515 // the focus() method on the legend element should focus the legend if it is
516 // focusable, or the first element after the legend if it is not focusable.
517 if (!gPartialTabbing) {
518 gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
519 var legend = getById("legend");
520 expectFocusShift(function () legend.focus(),
521 null, getById("t28"), true, "focus method on unfocusable legend");
522 gLastFocusMethod = 0;
523 legend.tabIndex = "0";
524 expectFocusShift(function () legend.focus(),
525 null, getById("legend"), true, "focus method on focusable legend");
526 legend.tabIndex = "-1";
527 }
529 var accessKeyDetails = (navigator.platform.indexOf("Mac") >= 0) ?
530 { ctrlKey : true } : { altKey : true };
532 // test accesskeys
533 var keys = ["t26", "t19", "t22", "t29", "t15", "t17", "n6",
534 "t4", "o1", "o9", "n4"];
535 for (var k = 0; k < keys.length; k++) {
536 var key = String.fromCharCode(65 + k);
538 // accesskeys D and G are for labels so get redirected
539 gLastFocusMethod = (key == "D" || key == "G") ? fm.FLAG_BYMOVEFOCUS : fm.FLAG_BYKEY;
541 // on Windows and Linux, the shift key must be pressed for content area access keys
542 // and on Mac, the alt key must be pressed for content area access keys
543 var isContent = (getById(keys[k]).ownerDocument.defaultView == gChildWindow);
544 if (navigator.platform.indexOf("Mac") == -1) {
545 accessKeyDetails.shiftKey = isContent;
546 } else {
547 accessKeyDetails.altKey = isContent;
548 }
550 expectFocusShift(function () synthesizeKey(key, accessKeyDetails),
551 null, getById(keys[k]), true, "accesskey " + key);
552 }
554 // clicking on the labels
555 gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
556 expectFocusShift(function () synthesizeMouse(getById("ad"), 2, 2, { }, gChildWindow),
557 null, getById("t29"), true, "mouse on html label with content inside");
558 expectFocusShift(function () synthesizeMouse(getById("ag"), 2, 2, { }, gChildWindow),
559 null, getById("n6"), true, "mouse on html label with for attribute");
560 gLastFocusMethod = 0;
561 expectFocusShift(function () synthesizeMouse(getById("aj"), 2, 2, { }),
562 null, getById("o9"), true, "mouse on xul label with content inside");
563 expectFocusShift(function () synthesizeMouse(getById("ak"), 2, 2, { }),
564 null, getById("n4"), true, "mouse on xul label with control attribute");
566 // test accesskeys that shouldn't work
567 k = "o".charCodeAt(0);
568 while (k++ < "v".charCodeAt(0)) {
569 var key = String.fromCharCode(k);
570 expectFocusShift(function () synthesizeKey(key, accessKeyDetails),
571 window, getById("n4"), false, "non accesskey " + key);
572 }
573 gLastFocusMethod = -1;
575 // should focus the for element when using the focus method on a label as well
576 expectFocusShift(function () getById("ad").focus(),
577 null, getById("t29"), true, "mouse on html label using focus method");
579 // make sure that the text is selected when clicking a label associated with an input
580 getById("ag").htmlFor = "t19";
581 expectFocusShift(function () synthesizeMouse(getById("ag"), 2, 2, { }, gChildWindow),
582 null, getById("t19"), true, "mouse on html label with for attribute changed");
583 is(t19.selectionStart, 0, "input focused from label, selectionStart");
584 is(t19.selectionEnd, 5, "input focused from label, selectionEnd");
586 // switch to another panel in a tabbox and ensure that tabbing moves between
587 // elements on the new panel.
588 $("tabbox").selectedIndex = 1;
589 expectFocusShift(function () getById("t" + kBeforeTabboxIndex).focus(),
590 null, getById("t" + kBeforeTabboxIndex), true, "focus method on element before tabbox");
592 if (!gPartialTabbing) {
593 expectFocusShift(pressTab, null, getById("tab2"), true, "focus method on tab");
594 expectFocusShift(pressTab, null, getById("htab1"), true, "tab key switch tabpanel 1");
595 expectFocusShift(pressTab, null, getById("htab2"), true, "tab key switch tabpanel 2");
596 expectFocusShift(pressTab, null, getById("t" + (kBeforeTabboxIndex + 4)), true, "tab key switch tabpanel 3");
597 }
598 $("tabbox").selectedIndex = 0;
600 // ---- the following checks when the focus changes during a blur or focus event ----
602 var o5 = $("o5");
603 var o9 = $("o9");
604 var t3 = $("t3");
605 var t17 = getById("t17");
606 var t19 = getById("t19");
607 var shiftFocusParentDocument = function() o9.focus();
608 var shiftFocusChildDocument = function() t17.focus();
610 var trapBlur = function (element, eventListener, blurFunction)
611 {
612 element.focus();
613 gEvents = "";
614 element.addEventListener("blur", eventListener, false);
615 blurFunction();
616 element.removeEventListener("blur", eventListener, false);
617 }
619 var functions = [
620 function(element) element.focus(),
621 function(element) synthesizeMouse(element, 4, 4, { }, element.ownerDocument.defaultView)
622 ];
624 // first, check cases where the focus is adjusted during the blur event. Iterate twice,
625 // once with the focus method and then focusing by mouse clicking
626 for (var l = 0; l < 2; l++) {
627 var adjustFocus = functions[l];
628 var mod = (l == 1) ? " with mouse" : "";
630 // an attempt is made to switch the focus from one element (o5) to another
631 // element (t3) within the same document, yet the focus is shifted to a
632 // third element (o9) in the same document during the blur event for the
633 // first element.
634 trapBlur(o5, shiftFocusParentDocument, function () adjustFocus(t3));
635 compareEvents("commandupdate: cu blur: o5 commandupdate: cu focus: o9",
636 window, o9, "change focus to sibling during element blur, attempted sibling" + mod);
638 // similar, but the third element (t17) is in a child document
639 trapBlur(o9, shiftFocusChildDocument, function () adjustFocus(t3));
640 compareEvents("commandupdate: cu blur: o9 blur: outer-document blur: outer-window " +
641 "focus: child-document focus: child-window commandupdate: cu focus: t17",
642 gChildWindow, t17, "change focus to child document during element blur, attempted sibling" + mod);
644 // similar, but an attempt to switch focus within the same document, but the
645 // third element (t17) is in a parent document
646 trapBlur(t17, shiftFocusParentDocument, function () adjustFocus(t19));
647 compareEvents("commandupdate: cu blur: t17 blur: child-document blur: child-window " +
648 "focus: outer-document focus: outer-window commandupdate: cu focus: o9",
649 window, o9, "change focus to parent document during element blur, attempted sibling" + mod);
651 // similar, but blur is called instead of switching focus
652 trapBlur(t3, shiftFocusParentDocument, function () t3.blur());
653 compareEvents("commandupdate: cu blur: t3 commandupdate: cu focus: o9",
654 window, o9, "change focus to same document during clear focus" + mod);
656 // check when an element in the same document is focused during the
657 // element's blur event, but an attempt was made to focus an element in the
658 // child document. In this case, the focus in the parent document should be
659 // what was set during the blur event, but the actual focus should still
660 // move to the child document.
661 trapBlur(t3, shiftFocusParentDocument, function () adjustFocus(t17));
662 compareEvents("commandupdate: cu blur: t3 commandupdate: cu focus: o9 " +
663 "blur: outer-document blur: outer-window " +
664 "focus: child-document focus: child-window commandupdate: cu focus: t17",
665 gChildWindow, t17, "change focus to sibling during element blur, attempted child" + mod);
666 is(fm.getFocusedElementForWindow(window, false, {}), $("childframe"),
667 "change focus to sibling during element blur, attempted child, focused in parent" + mod);
669 // similar, but with a parent
670 trapBlur(t19, shiftFocusChildDocument, function () adjustFocus(t3));
671 compareEvents("commandupdate: cu blur: t19 commandupdate: cu focus: t17 " +
672 "blur: child-document blur: child-window " +
673 "focus: outer-document focus: outer-window commandupdate: cu focus: t3",
674 window, t3, "change focus to sibling during element blur, attempted parent" + mod);
675 is(fm.getFocusedElementForWindow(gChildWindow, false, {}), t17,
676 "change focus to sibling during element blur, attempted child, focused in child" + mod);
678 // similar, with a child, but the blur event focuses a child element also
679 trapBlur(t3, shiftFocusChildDocument, function () adjustFocus(t19));
680 compareEvents("commandupdate: cu blur: t3 blur: outer-document blur: outer-window " +
681 "focus: child-document focus: child-window commandupdate: cu focus: t17",
682 gChildWindow, t17, "change focus to child during element blur, attempted child" + mod);
684 // similar, with a parent, where the blur event focuses a parent element also
685 trapBlur(t17, shiftFocusParentDocument, function () adjustFocus(t3));
686 compareEvents("commandupdate: cu blur: t17 blur: child-document blur: child-window " +
687 "focus: outer-document focus: outer-window commandupdate: cu focus: o9",
688 window, o9, "change focus to parent during element blur, attempted parent" + mod);
689 }
691 var trapFocus = function (element, eventListener)
692 {
693 element.addEventListener("focus", eventListener, false);
694 element.focus();
695 element.removeEventListener("focus", eventListener, false);
696 }
698 fm.clearFocus(window);
699 gEvents = "";
701 // next, check cases where the focus is adjusted during the focus event
703 // switch focus to an element in the same document
704 trapFocus(o5, shiftFocusParentDocument);
705 compareEvents("commandupdate: cu focus: o5 commandupdate: cu blur: o5 commandupdate: cu focus: o9",
706 window, o9, "change focus to sibling during element focus");
708 // similar, but the new element (t17) is in a child document
709 trapFocus(o5, shiftFocusChildDocument);
710 compareEvents("commandupdate: cu blur: o9 " +
711 "commandupdate: cu focus: o5 commandupdate: cu blur: o5 " +
712 "blur: outer-document blur: outer-window " +
713 "focus: child-document focus: child-window commandupdate: cu focus: t17",
714 gChildWindow, t17, "change focus to child document during element focus");
716 // similar, but the new element (o9) is in a parent document.
717 trapFocus(t19, shiftFocusParentDocument);
718 compareEvents("commandupdate: cu blur: t17 " +
719 "commandupdate: cu focus: t19 commandupdate: cu blur: t19 " +
720 "blur: child-document blur: child-window " +
721 "focus: outer-document focus: outer-window commandupdate: cu focus: o9",
722 window, o9, "change focus to parent document during element focus");
724 // clear the focus during the focus event
725 trapFocus(t3, function () fm.clearFocus(window));
726 compareEvents("commandupdate: cu blur: o9 commandupdate: cu focus: t3 commandupdate: cu blur: t3",
727 window, null, "clear focus during focus event");
729 if (!gPartialTabbing)
730 doCommandDispatcherTests();
732 testMoveFocus();
734 doRemoveTests();
736 // tests various focus manager apis for null checks
737 var exh = false;
738 try {
739 fm.clearFocus(null);
740 }
741 catch (ex) { exh = true; }
742 is(exh, true, "clearFocus with null window causes exception");
744 var exh = false;
745 try {
746 fm.getFocusedElementForWindow(null, false, focusedWindow);
747 }
748 catch (ex) { exh = true; }
749 is(exh, true, "getFocusedElementForWindow with null window causes exception");
751 // just make sure that this doesn't crash
752 fm.moveCaretToFocus(null);
754 // ---- tests for the FLAG_NOSWITCHFRAME flag
755 getById("o5").focus();
756 gLastFocusMethod = 0;
757 gEvents = "";
758 // focus is being shifted in a child, so the focus should not change
759 expectFocusShift(function () fm.setFocus(getById("t20"), fm.FLAG_NOSWITCHFRAME),
760 window, getById("o5"), false, "no switch frame focus to child");
761 setFocusTo("t20", gChildWindow);
763 // here, however, focus is being shifted in a parent, which will have to blur
764 // the child, so the focus will always change
765 expectFocusShift(function () fm.setFocus(getById("o5"), fm.FLAG_NOSWITCHFRAME),
766 window, getById("o5"), true, "no switch frame focus to parent");
768 expectFocusShift(function () fm.setFocus(getById("t1"), fm.FLAG_NOSWITCHFRAME),
769 window, getById("t1"), true, "no switch frame focus to same window");
771 // ---- tests for focus and scrolling into view ----
772 var inscroll = getById("inscroll");
773 inscroll.tabIndex = 0;
774 is(inscroll.parentNode.scrollTop, 0, "scroll position before focus");
775 inscroll.focus();
776 ok(inscroll.parentNode.scrollTop > 5, "scroll position after focus");
777 inscroll.parentNode.scrollTop = 0;
778 fm.setFocus(inscroll, fm.FLAG_NOSCROLL);
779 is(inscroll.parentNode.scrollTop, 0, "scroll position after noscroll focus");
781 getById("t9").focus();
782 getById("inpopup1").focus();
783 is(fm.focusedElement, getById("t9"), "focus in closed popup");
785 // ---- tests to check if tabbing out of a textbox works
787 setFocusTo("t1", window);
789 var textbox1 = document.createElement("textbox");
790 $("innerbox").appendChild(textbox1);
792 var textbox2 = document.createElement("textbox");
793 $("innerbox").appendChild(textbox2);
795 gLastFocusMethod = 0;
796 expectFocusShift(function () textbox2.focus(),
797 null, textbox2.inputField, true, "focus on textbox");
798 gLastFocusMethod = fm.FLAG_BYKEY;
799 expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }),
800 null, textbox1.inputField, true, "shift+tab on textbox");
802 textbox1.tabIndex = 2;
803 textbox2.tabIndex = 2;
804 gLastFocusMethod = 0;
805 expectFocusShift(function () textbox2.focus(),
806 null, textbox2.inputField, true, "focus on textbox with tabindex set");
807 gLastFocusMethod = fm.FLAG_BYKEY;
808 expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }),
809 null, textbox1.inputField, true, "shift+tab on textbox with tabindex set");
811 // ---- test for bug 618907 which ensures that canceling the mousedown event still focuses the
812 // right frame
814 var childContentFrame = document.getElementById("ifa")
815 childContentFrame.style.MozUserFocus = "";
817 var frab = childContentFrame.contentDocument.getElementById("fra-b");
818 var mouseDownListener = function(event) event.preventDefault();
819 frab.addEventListener("mousedown", mouseDownListener, false);
821 var childElementToFocus = childContentFrame.contentDocument.getElementById("fra");
822 gLastFocus = childElementToFocus;
823 gLastFocusWindow = childContentFrame.contentWindow;
824 gLastFocus.focus();
825 gEvents = "";
827 setFocusTo("t1", window);
829 gLastFocusMethod = -1;
830 expectFocusShift(function () synthesizeMouse(frab, 5, 5, { }, childContentFrame.contentWindow),
831 null, childElementToFocus, true,
832 "mousedown event canceled - chrome to content");
834 frab.removeEventListener("mousedown", mouseDownListener, false);
836 var t5 = getById("t5");
837 t5.addEventListener("mousedown", mouseDownListener, false);
838 synthesizeMouse(t5, 10, 10, { })
839 t5.removeEventListener("mousedown", mouseDownListener, false);
840 is(fm.focusedElement, childElementToFocus,
841 "mousedown event cancelled - content to chrome - element");
842 is(fm.focusedWindow, childContentFrame.contentWindow, "mousedown event cancelled - content to chrome - window");
844 // ---- test to check that refocusing an element during a blur event doesn't succeed
846 var t1 = getById("t1");
847 t1.addEventListener("blur", function() t1.focus(), true);
848 t1.focus();
849 var t3 = getById("t3");
850 synthesizeMouse(t3, 2, 2, { });
851 is(fm.focusedElement, t3, "focus during blur");
853 setFocusTo("t9", window);
854 gLastFocusMethod = -1;
855 window.openDialog("focus_window2.xul", "_blank", "chrome", otherWindowFocused);
856 }
858 function doCommandDispatcherTests()
859 {
860 var t19 = getById("t19");
861 t19.focus();
862 gLastFocusWindow = gChildWindow;
863 gLastFocus = t19;
864 gEvents = "";
866 expectFocusShift(function () document.commandDispatcher.focusedElement = getById("o9"),
867 null, getById("o9"), true, "command dispatcher set focusedElement");
868 expectFocusShift(function () document.commandDispatcher.advanceFocus(),
869 null, getById("o13"), true, "command dispatcher advanceFocus");
870 expectFocusShift(function () document.commandDispatcher.rewindFocus(),
871 null, getById("o9"), true, "command dispatcher rewindFocus");
872 expectFocusShift(function () document.commandDispatcher.focusedElement = null,
873 null, null, true, "command dispatcher set focusedElement to null");
874 expectFocusShift(function () document.commandDispatcher.focusedWindow = gChildWindow,
875 null, getById("t19"), true, "command dispatcher set focusedElement to null");
876 expectFocusShift(function () document.commandDispatcher.focusedElement = null,
877 gChildWindow, null, true, "command dispatcher set focusedElement to null in child");
878 expectFocusShift(function () document.commandDispatcher.advanceFocusIntoSubtree(getById("t19")),
879 null, getById("t20"), true, "command dispatcher advanceFocusIntoSubtree child");
880 expectFocusShift(function () document.commandDispatcher.advanceFocusIntoSubtree(null),
881 null, getById("t21"), true, "command dispatcher advanceFocusIntoSubtree null child");
882 expectFocusShift(function () document.commandDispatcher.advanceFocusIntoSubtree(getById("o9").parentNode),
883 null, getById("o9"), true, "command dispatcher advanceFocusIntoSubtree parent");
884 }
886 function doRemoveTests()
887 {
888 // next, some tests which remove elements
889 var t19 = getById("t19");
890 t19.focus();
891 t19.parentNode.removeChild(t19);
893 is(fm.focusedElement, null, "removed element focusedElement");
894 is(fm.focusedWindow, gChildWindow, "removed element focusedWindow");
895 is(gChildWindow.document.hasFocus(), true, "removed element hasFocus");
896 is(gChildWindow.document.activeElement, getById("inner-document"), "removed element activeElement");
898 getById("t15").focus();
899 var abs = getById("abs");
900 abs.parentNode.removeChild(abs);
902 is(fm.focusedElement, null, "removed ancestor focusedElement");
903 is(fm.focusedWindow, gChildWindow, "removed ancestor focusedWindow");
904 is(gChildWindow.document.hasFocus(), true, "removed ancestor hasFocus");
905 is(gChildWindow.document.activeElement, getById("inner-document"), "removed ancestor activeElement");
906 }
908 // tests for the FocusManager moveFocus method
909 function testMoveFocus()
910 {
911 setFocusTo("t6", window);
913 // moving focus while an element is already focused
914 var newFocus;
915 gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
916 var expectedFirst = getById(gPartialTabbing ? "t3" : "t1");
917 expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FIRST, 0),
918 window, expectedFirst, true, "moveFocus to first null window null content");
919 is(newFocus, fm.focusedElement, "moveFocus to first null window null content return value");
921 expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_LAST, 0),
922 window, getById("last"), true, "moveFocus to last null window null content");
923 is(newFocus, fm.focusedElement, "moveFocus to last null window null content return value");
925 gLastFocusMethod = 0;
926 newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_ROOT, 0);
927 is(newFocus, null, "moveFocus to root null window null content return value");
928 is(fm.focusedWindow, window, "moveFocus to root null window null content focusedWindow");
929 is(fm.focusedElement, null, "moveFocus to root null window null content focusedElement");
931 // moving focus while no element is focused
932 fm.clearFocus(window);
933 gEvents = "";
934 gLastFocus = null;
935 gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
936 expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FIRST, 0),
937 window, expectedFirst, true, "moveFocus to first null window null content no focus");
938 is(newFocus, fm.focusedElement, "moveFocus to first null window null content no focus return value");
939 fm.clearFocus(window);
940 gEvents = "";
941 gLastFocus = null;
942 expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_LAST, 0),
943 window, getById("last"), true, "moveFocus to last null window null content no focus");
944 is(newFocus, fm.focusedElement, "moveFocus to last null window null content no focus return value");
945 fm.clearFocus(window);
946 gEvents = "";
947 gLastFocusMethod = 0;
948 newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_ROOT, 0);
949 is(newFocus, null, "moveFocus to root null window null content no focus return value");
950 is(fm.focusedWindow, window, "moveFocus to root null window null content no focus focusedWindow");
951 is(fm.focusedElement, null, "moveFocus to root null window null content no focus focusedElement");
953 // moving focus from a specified element
954 setFocusTo("t6", window);
955 gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
956 expectFocusShift(function () newFocus = fm.moveFocus(null, getById("specialroot"), fm.MOVEFOCUS_FIRST, 0),
957 window, getById("t3"), true, "moveFocus to first null window with content");
958 // XXXndeakin P3 this doesn't work
959 // expectFocusShift(function () newFocus = fm.moveFocus(null, getById("specialroot"), fm.MOVEFOCUS_LAST, 0),
960 // window, getById("o3"), true, "moveFocus to last null window with content");
962 // move focus to first in child window
963 expectFocusShift(function () newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_FIRST, 0),
964 gChildWindow, getById("t" + (kChildDocumentRootIndex + 1)), true,
965 "moveFocus to first child window null content");
966 is(newFocus, getById("t" + (kChildDocumentRootIndex + 1)),
967 "moveFocus to first child window null content return value");
969 // move focus to last in child window
970 setFocusTo("t6", window);
971 var expectedLast = getById(gPartialTabbing ? "t30" : "t" + (kBeforeTabboxIndex - 1));
972 expectFocusShift(function () newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_LAST, 0),
973 gChildWindow, expectedLast, true,
974 "moveFocus to last child window null content");
975 is(newFocus, getById(expectedLast),
976 "moveFocus to last child window null content return value");
978 // move focus to root in child window
979 setFocusTo("t6", window);
980 var childroot = getById("t" + kChildDocumentRootIndex);
981 gLastFocusMethod = 0;
982 newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_ROOT, 0),
983 is(newFocus, childroot, "moveFocus to root child window null content return value");
984 is(fm.focusedWindow, gChildWindow, "moveFocus to root child window null content focusedWindow");
985 is(fm.focusedElement, childroot, "moveFocus to root child window null content focusedElement");
987 // MOVEFOCUS_CARET tests
988 getById("t20").focus();
989 gEvents = "";
991 var selection = gChildWindow.getSelection();
992 selection.removeAllRanges();
994 newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_CARET, 0);
995 is(newFocus, null, "move caret when at document root");
996 is(fm.focusedElement, null, "move caret when at document root");
998 var node = getById("t16").firstChild;
999 var range = gChildWindow.document.createRange();
1000 range.setStart(node, 3);
1001 range.setEnd(node, 3);
1002 selection.addRange(range);
1004 newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_CARET, 0);
1005 is(newFocus, null, "move caret to non-link return value");
1006 is(fm.focusedElement, null, "move caret to non-link");
1008 var t25 = getById("t25");
1009 var node = t25.firstChild;
1010 range.setStart(node, 1);
1011 range.setEnd(node, 1);
1012 newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_CARET, 0);
1014 is(newFocus, t25, "move caret to link return value");
1015 is(fm.focusedElement, t25, "move caret to link focusedElement");
1017 // enable caret browsing temporarily to test caret movement
1018 var prefs = Components.classes["@mozilla.org/preferences-service;1"].
1019 getService(Components.interfaces.nsIPrefBranch);
1020 prefs.setBoolPref("accessibility.browsewithcaret", true);
1022 synthesizeKey("VK_LEFT", { }, gChildWindow);
1023 synthesizeKey("VK_LEFT", { }, gChildWindow);
1024 is(fm.focusedElement, null, "move caret away from link");
1026 synthesizeKey("VK_LEFT", { }, gChildWindow);
1027 is(fm.focusedElement, getById("t24"), "move caret away onto link");
1029 prefs.setBoolPref("accessibility.browsewithcaret", false);
1031 // cases where focus in on a content node with no frame
1033 if (!gPartialTabbing) {
1034 getById("t24").blur();
1035 gEvents = "";
1036 gLastFocus = null;
1037 gLastFocusWindow = gChildWindow;
1038 gLastFocusMethod = fm.FLAG_BYKEY;
1040 selection.selectAllChildren(getById("hiddenspan"));
1041 expectFocusShift(function () synthesizeKey("VK_TAB", { }),
1042 gChildWindow, getById("t26"), true, "tab with selection on hidden content");
1044 setFocusTo($("o15"), window);
1045 $("o15").hidden = true;
1046 document.documentElement.getBoundingClientRect(); // flush after hiding
1047 expectFocusShift(function () synthesizeKey("VK_TAB", { }),
1048 window, $("o17"), true, "tab with focus on hidden content");
1050 $("o17").hidden = true;
1051 document.documentElement.getBoundingClientRect();
1052 expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }),
1053 window, $("o13"), true, "shift+tab with focus on hidden content");
1054 }
1056 // cases with selection in an <input>
1058 var t19 = getById("t19");
1059 t19.setSelectionRange(0, 0);
1060 setFocusTo("t18", gChildWindow);
1062 gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
1063 expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FORWARD, 0),
1064 gChildWindow, t19, true, "moveFocus to next textbox");
1065 is(t19.selectionStart, 0, "input focused after moveFocus selectionStart");
1066 is(t19.selectionEnd, 5, "input focused after moveFocus selectionEnd");
1068 t19.setSelectionRange(0, 0);
1069 setFocusTo("t18", gChildWindow);
1070 gLastFocusMethod = fm.FLAG_BYKEY;
1071 expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FORWARD, fm.FLAG_BYKEY),
1072 gChildWindow, t19, true, "moveFocus to next textbox by key");
1073 is(t19.selectionStart, 0, "input focused after moveFocus by key selectionStart");
1074 is(t19.selectionEnd, 5, "input focused after moveFocus by key selectionEnd");
1075 }
1077 function otherWindowFocused(otherWindow)
1078 {
1079 var expectedElement = getById("t9");
1081 is(fm.activeWindow, otherWindow, "other activeWindow");
1082 is(fm.focusedWindow, otherWindow, "other focusedWindow");
1083 is(window.document.hasFocus(), false, "when lowered document hasFocus");
1084 var focusedWindow = {};
1085 is(fm.getFocusedElementForWindow(window, false, focusedWindow),
1086 expectedElement, "when lowered getFocusedElementForWindow");
1087 is(focusedWindow.value, window, "when lowered getFocusedElementForWindow frame");
1088 is(document.activeElement.id, expectedElement.id, "when lowered activeElement");
1089 is(window.document.commandDispatcher.focusedWindow, window, " commandDispatcher in other window focusedWindow");
1090 is(window.document.commandDispatcher.focusedElement, expectedElement, " commandDispatcher in other window focusedElement");
1092 compareEvents("deactivate: outer-document-window blur: t9 blur: outer-document blur: outer-window",
1093 otherWindow, null, "other window opened");
1095 otherWindow.document.getElementById("other").focus();
1097 for (var idx = kTabbableSteps; idx >= 1; idx--) {
1098 expectedElement = getById("t" + idx);
1099 if (!expectedElement) // skip elements that were removed in doRemoveTests()
1100 continue;
1101 if ((navigator.platform.indexOf("Mac") == 0) && (idx == kBeforeTabboxIndex + 1))
1102 continue;
1104 expectedElement.focus();
1106 is(fm.focusedElement.id, "other", "when lowered focusedElement t" + idx);
1107 is(fm.focusedWindow, otherWindow, "when lowered focusedWindow t" + idx);
1109 var checkWindow = expectedElement.ownerDocument.defaultView;
1110 is(fm.getFocusedElementForWindow(checkWindow, false, {}).id, expectedElement.id,
1111 "when lowered getFocusedElementForWindow t" + idx);
1112 is(checkWindow.document.activeElement.id, expectedElement.id, "when lowered activeElement t" + idx);
1113 if (checkWindow != window) {
1114 is(fm.getFocusedElementForWindow(window, false, {}), $("childframe"),
1115 "when lowered parent getFocusedElementForWindow t" + idx);
1116 is(document.activeElement.id, "childframe",
1117 "when lowered parent activeElement t" + idx);
1118 }
1119 }
1121 gEvents = gEvents.replace(/commandupdate: cu\s?/g, "");
1122 is(gEvents, "", "when lowered no events fired");
1124 var other = otherWindow.document.getElementById("other");
1125 other.focus();
1126 is(fm.focusedElement, other, "focus method in second window");
1128 otherWindow.close();
1130 getById("n2").focus();
1132 // next, check modal dialogs
1133 // XXXndeakin Bug 621399 - the modal dialog test as well as later tests sometime fail
1134 // on Windows 8 so just end the test here.
1135 if (navigator.userAgent.indexOf("Windows NT 6.2") >= 0) {
1136 done();
1137 }
1138 else {
1139 window.openDialog("focus_window2.xul", "_blank", "chrome,modal", modalWindowOpened);
1140 }
1141 }
1143 function modalWindowOpened(modalWindow)
1144 {
1145 var elem = modalWindow.document.getElementById("other");
1146 if (gPartialTabbing)
1147 elem.focus();
1148 else
1149 synthesizeKey("VK_TAB", { }, modalWindow);
1150 is(fm.activeWindow, modalWindow, "modal activeWindow");
1151 is(fm.focusedElement, elem, "modal focusedElement");
1153 modalWindow.close();
1154 SimpleTest.waitForFocus(modalWindowClosed);
1155 }
1157 function modalWindowClosed()
1158 {
1159 is(fm.activeWindow, window, "modal window closed activeWindow");
1160 is(fm.focusedElement, getById("n2"), "modal window closed focusedElement");
1162 window.open("focus_frameset.html", "_blank", "width=400,height=400,toolbar=no");
1163 }
1165 function framesetWindowLoaded(framesetWindow)
1166 {
1167 gLastFocus = null;
1168 gLastFocusWindow = framesetWindow;
1169 gEvents = "";
1171 is(fm.activeWindow, getTopWindow(framesetWindow), "frameset window active");
1172 gOldExpectedWindow = getTopWindow(framesetWindow);
1174 gMoveToFocusFrame = true;
1175 for (var idx = 1; idx <= 8; idx++) {
1176 gNewExpectedWindow = framesetWindow.frames[(idx - 1) >> 1];
1177 if (idx % 2)
1178 initEvents(gNewExpectedWindow);
1179 expectFocusShift(function () synthesizeKey("VK_TAB", { }, framesetWindow),
1180 gNewExpectedWindow, getById("f" + idx), true, "frameset tab key f" + idx);
1181 gMoveToFocusFrame = false;
1182 gOldExpectedWindow = gNewExpectedWindow;
1183 }
1185 gNewExpectedWindow = framesetWindow.frames[0];
1186 expectFocusShift(function () synthesizeKey("VK_TAB", { }, framesetWindow),
1187 gNewExpectedWindow, getById("f1"), true, "frameset tab key wrap to start");
1188 gOldExpectedWindow = gNewExpectedWindow;
1189 gNewExpectedWindow = framesetWindow.frames[3];
1190 expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }, framesetWindow),
1191 gNewExpectedWindow, getById("f8"), true, "frameset shift tab key wrap to end");
1193 for (idx = 7; idx >= 1; idx--) {
1194 gOldExpectedWindow = gNewExpectedWindow;
1195 gNewExpectedWindow = framesetWindow.frames[(idx - 1) >> 1];
1196 expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }, framesetWindow),
1197 gNewExpectedWindow, getById("f" + idx), true, "frameset shift tab key f" + idx);
1198 }
1200 // document shifting
1201 // XXXndeakin P3 ctrl+tab doesn't seem to be testable currently for some reason
1202 gNewExpectedWindow = framesetWindow.frames[1];
1203 expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true }, framesetWindow),
1204 gNewExpectedWindow, getById("f3"), true, "switch document forward with f6");
1205 gOldExpectedWindow = gNewExpectedWindow;
1206 gNewExpectedWindow = framesetWindow.frames[2];
1207 expectFocusShift(function () synthesizeKey("VK_F6", { }, framesetWindow),
1208 gNewExpectedWindow, getById("f5"), true, "switch document forward with ctrl+tab");
1209 gOldExpectedWindow = gNewExpectedWindow;
1210 gNewExpectedWindow = framesetWindow.frames[3];
1211 expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true }, framesetWindow),
1212 gNewExpectedWindow, getById("f7"), true, "switch document forward with ctrl+f6");
1213 gOldExpectedWindow = gNewExpectedWindow;
1214 gNewExpectedWindow = framesetWindow.frames[0];
1215 expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true }, framesetWindow),
1216 gNewExpectedWindow, getById("f1"), true, "switch document forward and wrap");
1218 // going backwards by document and wrapping doesn't currently work, but didn't work
1219 // before the focus reworking either
1221 /*
1222 gOldExpectedWindow = gNewExpectedWindow;
1223 gNewExpectedWindow = framesetWindow.frames[3];
1224 expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true, shiftKey: true }, framesetWindow),
1225 gNewExpectedWindow, getById("f7"), true, "switch document backward and wrap");
1226 */
1228 fm.moveFocus(framesetWindow.frames[3], null, fm.MOVEFOCUS_ROOT, 0);
1229 gEvents = "";
1231 gOldExpectedWindow = gNewExpectedWindow;
1232 gNewExpectedWindow = framesetWindow.frames[2];
1233 expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true, shiftKey: true }, framesetWindow),
1234 gNewExpectedWindow, getById("f5"), true, "switch document backward with f6");
1235 gOldExpectedWindow = gNewExpectedWindow;
1236 gNewExpectedWindow = framesetWindow.frames[1];
1237 expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true, shiftKey: true }, framesetWindow),
1238 gNewExpectedWindow, getById("f3"), true, "switch document backward with ctrl+tab");
1239 gOldExpectedWindow = gNewExpectedWindow;
1240 gNewExpectedWindow = framesetWindow.frames[0];
1241 expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true, shiftKey: true }, framesetWindow),
1242 gNewExpectedWindow, getById("f1"), true, "switch document backward with ctrl+f6");
1244 // skip the window switching tests for now on Linux, as raising and lowering
1245 // a window is asynchronous there
1246 if (navigator.platform.indexOf("Linux") == -1) {
1247 window.openDialog("focus_window2.xul", "_blank", "chrome", switchWindowTest, framesetWindow);
1248 }
1249 else {
1250 gOldExpectedWindow = null;
1251 gNewExpectedWindow = null;
1252 framesetWindow.close();
1253 SimpleTest.waitForFocus(doWindowNoRootTest);
1254 }
1255 }
1257 // test switching between two windows
1258 function switchWindowTest(otherWindow, framesetWindow)
1259 {
1260 initEvents(otherWindow);
1261 var otherElement = otherWindow.document.getElementById("other");
1262 otherElement.focus();
1264 framesetWindow.frames[1].document.getElementById("f4").focus();
1266 is(fm.focusedElement, otherElement, "focus after inactive window focus");
1268 gLastFocus = otherElement;
1269 gLastFocusWindow = otherWindow;
1270 gEvents = "";
1271 gOldExpectedWindow = otherWindow;
1272 gNewExpectedWindow = framesetWindow.frames[1];
1274 expectFocusShift(function () gNewExpectedWindow.focus(),
1275 gNewExpectedWindow, getById("f4"), true, "switch to frame in another window");
1276 is(fm.getFocusedElementForWindow(otherWindow, false, {}).id, "other", "inactive window has focused element");
1278 gOldExpectedWindow = framesetWindow.frames[1];
1279 gNewExpectedWindow = otherWindow;
1280 expectFocusShift(function () otherWindow.focus(),
1281 gNewExpectedWindow, getById("other"), true, "switch to another window");
1283 var exh = false;
1284 try {
1285 fm.activeWindow = framesetWindow.frames[0];
1286 }
1287 catch (ex) { exh = true; }
1288 is(exh, true, "activeWindow set to non top-level window");
1290 exh = false;
1291 try {
1292 fm.activeWindow = null;
1293 }
1294 catch (ex) { exh = true; }
1295 is(exh, true, "activeWindow set to null");
1296 is(fm.activeWindow, otherWindow, "window not changed when activeWindow set to null");
1298 var topWindow = getTopWindow(framesetWindow);
1300 ok(topWindow.document.commandDispatcher.getControllerForCommand("cmd_copy"),
1301 "getControllerForCommand for focused window set");
1302 ok(otherWindow.document.commandDispatcher.getControllerForCommand("cmd_copy"),
1303 "getControllerForCommand for non-focused window set");
1304 ok(topWindow.document.commandDispatcher.getControllerForCommand("cmd_copy") !=
1305 otherWindow.document.commandDispatcher.getControllerForCommand("cmd_copy"),
1306 "getControllerForCommand for two windows different");
1307 ok(topWindow.document.commandDispatcher.getControllers() !=
1308 otherWindow.document.commandDispatcher.getControllers(),
1309 "getControllers for two windows different");
1311 gOldExpectedWindow = otherWindow;
1312 gNewExpectedWindow = framesetWindow.frames[1];
1313 expectFocusShift(function () fm.activeWindow = topWindow,
1314 gNewExpectedWindow, getById("f4"), true, "switch to frame activeWindow");
1316 fm.clearFocus(otherWindow);
1317 gOldExpectedWindow = gNewExpectedWindow;
1318 gNewExpectedWindow = otherWindow;
1319 expectFocusShift(function () fm.setFocus(otherElement, fm.FLAG_RAISE),
1320 gNewExpectedWindow, getById("other"), true, "switch to window with raise");
1322 getTopWindow(framesetWindow).document.commandDispatcher.focusedWindow = gOldExpectedWindow;
1323 is(fm.activeWindow, gNewExpectedWindow, "setting commandDispatcher focusedWindow doesn't raise window");
1325 fm.moveFocus(otherWindow, null, fm.MOVEFOCUS_FORWARD, 0);
1326 var otherTextbox = otherWindow.document.getElementById("other-textbox");
1327 otherTextbox.setSelectionRange(2, 3);
1328 fm.activeWindow = topWindow;
1329 fm.activeWindow = otherWindow;
1330 is(otherTextbox.selectionStart, 2, "selectionStart after textbox focus and window raise");
1331 is(otherTextbox.selectionEnd, 3, "selectionEnd after textbox focus and window raise");
1332 is(fm.getLastFocusMethod(null), fm.FLAG_BYMOVEFOCUS, "last focus method after textbox focus and window raise");
1334 fm.clearFocus(otherWindow);
1336 // test to ensure that a synthetic event works
1337 var synevent = document.createEvent("Event");
1338 synevent.initEvent("focus", false, false);
1339 otherTextbox.inputField.dispatchEvent(synevent);
1340 is(synevent.type, "focus", "event.type after synthetic focus event");
1341 is(synevent.target, otherTextbox, "event.target after synthetic focus event");
1342 is(fm.focusedElement, null, "focusedElement after synthetic focus event");
1343 is(otherWindow.document.activeElement, otherWindow.document.documentElement,
1344 "document.activeElement after synthetic focus event");
1346 // check accessing a focus event after the event has finishing firing
1347 function continueTest(event) {
1348 is(event.type, "focus", "event.type after accessing focus event in timeout");
1349 is(event.target, otherTextbox, "event.target after accessing focus event in timeout");
1351 gOldExpectedWindow = null;
1352 gNewExpectedWindow = null;
1353 otherWindow.close();
1354 framesetWindow.close();
1356 SimpleTest.waitForFocus(doWindowNoRootTest);
1357 }
1359 function textboxFocused(event) {
1360 otherTextbox.removeEventListener("focus", textboxFocused, true);
1361 setTimeout(continueTest, 0, event);
1362 }
1364 otherTextbox.addEventListener("focus", textboxFocused, true);
1365 otherTextbox.focus();
1366 }
1368 // open a window with no root element
1369 var noRootWindow = null;
1370 function doWindowNoRootTest()
1371 {
1372 var data = "data:application/vnd.mozilla.xul+xml," + unescape(
1373 "<window onfocus='dostuff()' xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'" +
1374 " style='-moz-user-focus: normal;'>" +
1375 "<script>function dostuff() { setTimeout(function() { " +
1376 "document.documentElement.focus(); document.removeChild(document.documentElement);" +
1377 "window.opener.focus(); }, 100); }</script></window>");
1379 addEventListener("focus", doFrameSwitchingTests, true);
1380 noRootWindow = window.open(data, "_blank", "chrome,width=100,height=100");
1381 }
1383 // these tests check when focus is moved between a tree of frames to ensure
1384 // that the focus is in the right place at each event step.
1385 function doFrameSwitchingTests()
1386 {
1387 removeEventListener("focus", doFrameSwitchingTests, true);
1388 noRootWindow.close();
1390 var framea = document.getElementById("ifa");
1391 var frameb = document.getElementById("ifb");
1392 framea.style.MozUserFocus = "";
1393 frameb.style.MozUserFocus = "";
1395 window.removeEventListener("focus", eventOccured, true);
1396 window.removeEventListener("blur", eventOccured, true);
1398 var inputa = framea.contentDocument.body.firstChild;
1399 inputa.focus();
1401 addFrameSwitchingListeners(framea);
1402 addFrameSwitchingListeners(frameb);
1403 var framec = framea.contentDocument.body.lastChild;
1404 addFrameSwitchingListeners(framec);
1406 var framed = framec.contentDocument.body.lastChild;
1407 addFrameSwitchingListeners(framed);
1409 var inputc = framec.contentDocument.body.firstChild;
1411 var expectedMainWindowFocus = framea;
1413 // An element in the immediate parent frame is focused. Focus an element in
1414 // the child. The child should be focused and the parent's current focus should
1415 // be the child iframe.
1416 gEventMatched = true;
1417 is(fm.getFocusedElementForWindow(window, false, {}), expectedMainWindowFocus,
1418 "parent of framea has iframe focused");
1419 gExpectedEvents = [[inputa, "blur", null, framea.contentWindow, window, framea],
1420 [framea.contentDocument, "blur", null, null, window, framea],
1421 [framea.contentWindow, "blur", null, null, window, framea],
1422 [framec.contentDocument, "focus", null, framec.contentWindow, window, framea],
1423 [framec.contentWindow, "focus", null, framec.contentWindow, window, framea],
1424 [inputc, "focus", inputc, framec.contentWindow, window, framea]];
1425 inputc.focus();
1426 ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from parent input to child input" + gExpectedEvents);
1428 // An element in a child is focused. Focus an element in the immediate
1429 // parent.
1430 gEventMatched = true;
1431 gExpectedEvents = [[inputc, "blur", null, framec.contentWindow, window, framea],
1432 [framec.contentDocument, "blur", null, null, window, framea],
1433 [framec.contentWindow, "blur", null, null, window, framea],
1434 [framea.contentDocument, "focus", null, framea.contentWindow, window, framea],
1435 [framea.contentWindow, "focus", null, framea.contentWindow, window, framea],
1436 [inputa, "focus", inputa, framea.contentWindow, window, framea]];
1437 inputa.focus();
1438 ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from child input to parent input");
1440 // An element in a frame is focused. Focus an element in a sibling frame.
1441 // The common ancestor of the two frames should have its focused node
1442 // cleared after the element is blurred.
1443 var inputb = frameb.contentDocument.body.firstChild;
1445 gEventMatched = true;
1446 gExpectedEvents = [[inputa, "blur", null, framea.contentWindow, window, framea],
1447 [framea.contentDocument, "blur", null, null, window, null],
1448 [framea.contentWindow, "blur", null, null, window, null],
1449 [frameb.contentDocument, "focus", null, frameb.contentWindow, window, frameb],
1450 [frameb.contentWindow, "focus", null, frameb.contentWindow, window, frameb],
1451 [inputb, "focus", inputb, frameb.contentWindow, window, frameb]];
1452 inputb.focus();
1453 ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from input to sibling frame");
1454 is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), inputa,
1455 "blurred frame still has input as focus");
1457 // focus a descendant in a sibling
1458 var inputd = framed.contentDocument.body.firstChild;
1459 gEventMatched = true;
1460 gExpectedEvents = [[inputb, "blur", null, frameb.contentWindow, window, frameb],
1461 [frameb.contentDocument, "blur", null, null, window, null],
1462 [frameb.contentWindow, "blur", null, null, window, null],
1463 [framed.contentDocument, "focus", null, framed.contentWindow, window, framea],
1464 [framed.contentWindow, "focus", null, framed.contentWindow, window, framea],
1465 [inputd, "focus", inputd, framed.contentWindow, window, framea]];
1466 inputd.focus();
1467 ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from input to sibling descendant");
1468 is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), framec,
1469 "sibling parent focus has shifted to frame");
1471 // focus an ancestor
1472 gEventMatched = true;
1473 gExpectedEvents = [[inputd, "blur", null, framed.contentWindow, window, framea],
1474 [framed.contentDocument, "blur", null, null, window, framea],
1475 [framed.contentWindow, "blur", null, null, window, framea],
1476 [framea.contentDocument, "focus", null, framea.contentWindow, window, framea],
1477 [framea.contentWindow, "focus", null, framea.contentWindow, window, framea],
1478 [inputa, "focus", inputa, framea.contentWindow, window, framea]];
1479 inputa.focus();
1480 ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from child input to ancestor");
1482 // focus a descendant
1483 gEventMatched = true;
1484 gExpectedEvents = [[inputa, "blur", null, framea.contentWindow, window, framea],
1485 [framea.contentDocument, "blur", null, null, window, framea],
1486 [framea.contentWindow, "blur", null, null, window, framea],
1487 [framed.contentDocument, "focus", null, framed.contentWindow, window, framea],
1488 [framed.contentWindow, "focus", null, framed.contentWindow, window, framea],
1489 [inputd, "focus", inputd, framed.contentWindow, window, framea]];
1490 inputd.focus();
1491 ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from child input to ancestor");
1492 is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), framec,
1493 "parent focus has shifted to frame");
1495 // focus a sibling frame by setting focusedWindow
1496 gEventMatched = true;
1497 gExpectedEvents = [[inputd, "blur", null, framed.contentWindow, window, framea],
1498 [framed.contentDocument, "blur", null, null, window, null],
1499 [framed.contentWindow, "blur", null, null, window, null],
1500 [frameb.contentDocument, "focus", null, frameb.contentWindow, window, frameb],
1501 [frameb.contentWindow, "focus", null, frameb.contentWindow, window, frameb],
1502 [inputb, "focus", inputb, frameb.contentWindow, window, frameb]];
1503 fm.focusedWindow = frameb.contentWindow;
1504 ok(gEventMatched && gExpectedEvents.length == 0, "frame switch using focusedWindow");
1506 // clear the focus in an unfocused frame
1507 gEventMatched = true;
1508 gExpectedEvents = [];
1509 fm.clearFocus(framec.contentWindow);
1510 ok(gEventMatched && gExpectedEvents.length == 0, "clearFocus in unfocused frame");
1512 // focus a sibling frame by setting focusedWindow when no element is focused in that frame
1513 gEventMatched = true;
1514 gExpectedEvents = [[inputb, "blur", null, frameb.contentWindow, window, frameb],
1515 [frameb.contentDocument, "blur", null, null, window, null],
1516 [frameb.contentWindow, "blur", null, null, window, null],
1517 [framec.contentDocument, "focus", null, framec.contentWindow, window, framea],
1518 [framec.contentWindow, "focus", null, framec.contentWindow, window, framea]];
1519 fm.focusedWindow = framec.contentWindow;
1520 ok(gEventMatched && gExpectedEvents.length == 0, "frame switch using focusedWindow with no element focused");
1521 is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), framec,
1522 "parent focus has shifted to frame using focusedWindow");
1524 // focus the parent frame by setting focusedWindow. This should have no effect.
1525 gEventMatched = true;
1526 gExpectedEvents = [];
1527 fm.focusedWindow = framea.contentWindow;
1528 ok(gEventMatched && gExpectedEvents.length == 0, "frame switch to parent using focusedWindow");
1530 // clear the focus in the parent frame
1531 gEventMatched = true;
1532 gExpectedEvents = [[framec.contentDocument, "blur", null, null, window, framea],
1533 [framec.contentWindow, "blur", null, null, window, framea],
1534 [framea.contentDocument, "focus", null, framea.contentWindow, window, framea],
1535 [framea.contentWindow, "focus", null, framea.contentWindow, window, framea]];
1536 fm.clearFocus(framea.contentWindow);
1537 ok(gEventMatched && gExpectedEvents.length == 0, "clearFocus in parent frame");
1539 // clear the focus in an unfocused child frame
1540 gEventMatched = true;
1541 gExpectedEvents = [];
1542 fm.clearFocus(framed.contentWindow);
1543 ok(gEventMatched && gExpectedEvents.length == 0, "clearFocus in unfocused child frame");
1545 var exh = false;
1546 try {
1547 fm.focusedWindow = null;
1548 }
1549 catch (ex) { exh = true; }
1550 is(exh, true, "focusedWindow set to null");
1551 is(fm.focusedWindow, framea.contentWindow, "window not changed when focusedWindow set to null");
1553 doFrameHistoryTests()
1554 }
1556 function doFrameHistoryTests()
1557 {
1558 var t20 = getById("t20");
1559 t20.focus();
1561 gChildWindow.addEventListener("focus",
1562 function(event) {
1563 if (event.target == t20) {
1564 is(fm.focusedElement, t20, "focus restored after history back"); done();
1565 }
1566 }, true);
1568 // make sure that loading a new page and then going back maintains the focus
1569 gChildWindow.location = "data:text/html,<script>window.onload=function() {setTimeout(function () {window.back();}, 0);}</script>";
1570 }
1572 function addFrameSwitchingListeners(frame)
1573 {
1574 frame.contentWindow.addEventListener("focus", frameSwitchingEventOccured, false);
1575 frame.contentWindow.addEventListener("blur", frameSwitchingEventOccured, false);
1576 frame.contentDocument.addEventListener("focus", frameSwitchingEventOccured, false);
1577 frame.contentDocument.addEventListener("blur", frameSwitchingEventOccured, false);
1579 var node = frame.contentDocument.body.firstChild;
1580 node.addEventListener("focus", frameSwitchingEventOccured, false);
1581 node.addEventListener("blur", frameSwitchingEventOccured, false);
1582 }
1584 function frameSwitchingEventOccured(event)
1585 {
1586 if (!gExpectedEvents.length) {
1587 gEventMatched = false;
1588 return;
1589 }
1591 try {
1592 var events = gExpectedEvents.shift();
1593 is(event.target, events[0], "event target");
1594 is(event.type, events[1], "event type");
1595 is(fm.focusedElement, events[2], "focused element");
1596 is(fm.focusedWindow, events[3], "focused frame");
1597 if (events[4])
1598 is(fm.getFocusedElementForWindow(events[4], false, {}), events[5], "focused element in frame");
1600 if (gEventMatched && event.target == events[0] && event.type == events[1] &&
1601 fm.focusedElement == events[2] && fm.focusedWindow == events[3]) {
1602 if (!events[4] || fm.getFocusedElementForWindow(events[4], false, {}) == events[5])
1603 return;
1604 }
1605 } catch (ex) { ok(ex, "exception"); }
1607 gEventMatched = false;
1608 }
1610 SimpleTest.waitForExplicitFinish();
1611 SimpleTest.waitForFocus(startTest);
1613 ]]>
1614 </script>
1616 <commandset id="cu"
1617 commandupdater="true"
1618 events="focus"
1619 oncommandupdate="eventOccured(event)"/>
1621 <!--
1622 The elements with ids starting with t are focusable and in the taborder.
1623 The elements with ids starting with o are:
1624 odd numbered ids - focusable but not part of the tab order
1625 even numbered ids - not focusable with -moz-user-focus: ignore or disabled
1626 The elements with ids starting with n are:
1627 odd numbered ids - not focusable with -moz-user-focus: none
1628 even numbered ids - focusable but not part of the tab order
1629 -->
1630 <vbox id="buttonbox">
1631 <hbox id="innerbox">
1632 <button id="t4" accesskey="h" label="no tabindex"/>
1633 <button id="o1" accesskey="i" label="tabindex = -1" tabindex="-1"/>
1634 <listbox id="t5" label="tabindex = 0" tabindex="0" rows="1">
1635 <listitem/>
1636 </listbox>
1637 <button id="t1" label="tabindex = 2" tabindex="2"/>
1638 </hbox>
1639 <hbox>
1640 <button id="o2" accesskey="o" style="-moz-user-focus: ignore;" label="no tabindex"/>
1641 <button id="o4" style="-moz-user-focus: ignore;" label="tabindex = -1" tabindex="-1"/>
1642 <button id="t6" style="-moz-user-focus: ignore;" label="tabindex = 0" tabindex="0"/>
1643 <button id="t2" style="-moz-user-focus: ignore;" label="tabindex = 2" tabindex="2"/>
1644 </hbox>
1645 <hbox id="specialroot">
1646 <button id="t7" style="-moz-user-focus: normal;" label="no tabindex"/>
1647 <button id="o3" style="-moz-user-focus: normal;" label="tabindex = -1" tabindex="-1"/>
1648 <button id="t8" style="-moz-user-focus: normal;" label="tabindex = 0" tabindex="0"/>
1649 <listbox id="t3" style="-moz-user-focus: normal;" label="tabindex = 2" tabindex="2" rows="1">
1650 <listitem/>
1651 </listbox>
1652 </hbox>
1653 <hbox>
1654 <button accesskey="p" style="display: none;"/> <button accesskey="q" style="visibility: collapse;"/>
1655 <button style="display: none;" tabindex="2"/> <button style="visibility: collapse;" tabindex="2"/>
1656 </hbox>
1657 <hbox>
1658 <button id="o20" accesskey="s" label="no tabindex" disabled="true"/>
1659 <button id="o22" label="tabindex = -1" tabindex="-1" disabled="true"/>
1660 <button id="o24" label="tabindex = 0" tabindex="0" disabled="true"/>
1661 <button id="o26" label="tabindex = 2" tabindex="2" disabled="true"/>
1662 </hbox>
1663 </vbox>
1664 <vbox>
1665 <hbox>
1666 <dropmarker id="o6" value="no tabindex"/>
1667 <dropmarker id="o8" value="tabindex = -1" tabindex="-1"/>
1668 <dropmarker id="o10" value="tabindex = 0" tabindex="0"/>
1669 <dropmarker id="o12" value="tabindex = 2" tabindex="2"/>
1670 <dropmarker id="t9" accesskey="r" style="-moz-user-focus: normal;" value="no tabindex" />
1671 <dropmarker id="t10" style="-moz-user-focus: normal;" value="tabindex = -1" tabindex="-1" />
1672 <dropmarker id="t11" style="-moz-user-focus: normal;" value="tabindex = 0" tabindex="0" />
1673 <dropmarker id="t12" style="-moz-user-focus: normal;" value="tabindex = 2" tabindex="2" />
1674 <dropmarker id="o14" style="-moz-user-focus: ignore;" value="no tabindex"/>
1675 <dropmarker id="o16" style="-moz-user-focus: ignore;" value="tabindex = -1" tabindex="-1"/>
1676 <dropmarker id="n1" style="-moz-user-focus: none;" value="tabindex = 0" tabindex="0"/>
1677 <dropmarker id="n3" style="-moz-user-focus: none;" value="tabindex = 2" tabindex="2"/>
1678 </hbox>
1679 </vbox>
1680 <browser id="childframe" type="content" src="child_focus_frame.html" width="300" height="195"/>
1681 <button id="t34"/>
1682 <tabbox id="tabbox">
1683 <tabs><tab id="t35" label="One"/><tab id="tab2" label="Two"/></tabs>
1684 <tabpanels>
1685 <tabpanel>
1686 <checkbox id="t36"/>
1687 <button id="t37"/>
1688 </tabpanel>
1689 <tabpanel>
1690 <checkbox id="htab1"/>
1691 <button id="nohtab2" tabindex="7"/>
1692 <checkbox id="htab2" tabindex="0"/>
1693 </tabpanel>
1694 </tabpanels>
1695 </tabbox>
1696 <hbox>
1697 <panel>
1698 <button id="inpopup1" label="One"/>
1699 <textbox label="Two"/>
1700 </panel>
1701 <description label="o" accesskey="v"/>
1702 <button id="t38"/>
1703 <!-- The 't' element tests end here so it doesn't matter that these elements are tabbable -->
1704 <label id="aj" value="j" accesskey="j" control="o9"/>
1705 <label id="ak" accesskey="k" control="n4">k</label>
1706 <checkbox id="o5"/><checkbox id="o7"/><hbox><checkbox id="o9"/></hbox>
1707 <checkbox id="o13"/><checkbox id="o15"/><checkbox id="o17"/><checkbox id="o19"/><checkbox id="o21"/><checkbox id="o23"/><checkbox id="o25"/>
1708 <checkbox id="n2"/><checkbox id="n4"/>
1709 <listbox id="last" width="20" rows="1"/>
1711 <iframe id="ifa" width="40" height="60" style="-moz-user-focus: ignore;" type="content"
1712 src="data:text/html,<input id=fra size='2'><input id='fra-b' size='2'>
1713 <iframe src='data:text/html,<input id=frc><iframe src="data:text/html,<input id=frd>"></iframe>'></iframe>"/>
1714 <iframe id="ifb" width="20" height="20" style="-moz-user-focus: ignore;"
1715 src="data:text/html,<input id=frd></iframe>"/>
1717 </hbox>
1718 </window>