summaryrefslogtreecommitdiffstats
path: root/dom/tests/mochitest/chrome
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /dom/tests/mochitest/chrome
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/tests/mochitest/chrome')
-rw-r--r--dom/tests/mochitest/chrome/489127.html268
-rw-r--r--dom/tests/mochitest/chrome/DOMWindowCreated_chrome.xhtml33
-rw-r--r--dom/tests/mochitest/chrome/DOMWindowCreated_content.html9
-rw-r--r--dom/tests/mochitest/chrome/child_focus_frame.html57
-rw-r--r--dom/tests/mochitest/chrome/chrome.ini91
-rw-r--r--dom/tests/mochitest/chrome/file_DOM_element_instanceof.xhtml32
-rw-r--r--dom/tests/mochitest/chrome/file_bug1224790-1_modal.xhtml34
-rw-r--r--dom/tests/mochitest/chrome/file_bug1224790-1_nonmodal.xhtml28
-rw-r--r--dom/tests/mochitest/chrome/file_bug1224790-2_modal.xhtml36
-rw-r--r--dom/tests/mochitest/chrome/file_bug1224790-2_nonmodal.xhtml42
-rw-r--r--dom/tests/mochitest/chrome/file_bug800817.xhtml79
-rw-r--r--dom/tests/mochitest/chrome/file_bug830858.xhtml66
-rw-r--r--dom/tests/mochitest/chrome/file_clipboard_events_chrome.html1
-rw-r--r--dom/tests/mochitest/chrome/file_popup_blocker_chrome.html6
-rw-r--r--dom/tests/mochitest/chrome/file_resize_move_windows_1.html19
-rw-r--r--dom/tests/mochitest/chrome/file_resize_move_windows_2.html8
-rw-r--r--dom/tests/mochitest/chrome/file_subscript_bindings.js1
-rw-r--r--dom/tests/mochitest/chrome/focus_dialog.xhtml71
-rw-r--r--dom/tests/mochitest/chrome/focus_frameset.html25
-rw-r--r--dom/tests/mochitest/chrome/focus_window2.xhtml26
-rw-r--r--dom/tests/mochitest/chrome/queryCaretRectUnix.html209
-rw-r--r--dom/tests/mochitest/chrome/queryCaretRectWin.html218
-rw-r--r--dom/tests/mochitest/chrome/selectAtPoint-innerframe.html6
-rw-r--r--dom/tests/mochitest/chrome/selectAtPoint.html278
-rw-r--r--dom/tests/mochitest/chrome/sizemode_attribute.xhtml87
-rw-r--r--dom/tests/mochitest/chrome/test_DOMWindowCreated.xhtml29
-rw-r--r--dom/tests/mochitest/chrome/test_DOM_element_instanceof.xhtml34
-rw-r--r--dom/tests/mochitest/chrome/test_activation.xhtml42
-rw-r--r--dom/tests/mochitest/chrome/test_bug1224790-1.xhtml69
-rw-r--r--dom/tests/mochitest/chrome/test_bug1224790-2.xhtml70
-rw-r--r--dom/tests/mochitest/chrome/test_bug800817.xhtml43
-rw-r--r--dom/tests/mochitest/chrome/test_bug830858.xhtml36
-rw-r--r--dom/tests/mochitest/chrome/test_callback_wrapping.xhtml22
-rw-r--r--dom/tests/mochitest/chrome/test_clipboard_events_chrome.html60
-rw-r--r--dom/tests/mochitest/chrome/test_clonewrapper.xhtml117
-rw-r--r--dom/tests/mochitest/chrome/test_cyclecollector.xhtml54
-rw-r--r--dom/tests/mochitest/chrome/test_docshell_swap.xhtml71
-rw-r--r--dom/tests/mochitest/chrome/test_elements_proto.xhtml29
-rw-r--r--dom/tests/mochitest/chrome/test_focus.xhtml32
-rw-r--r--dom/tests/mochitest/chrome/test_focus_dialog.xhtml33
-rw-r--r--dom/tests/mochitest/chrome/test_focus_docnav.xhtml27
-rw-r--r--dom/tests/mochitest/chrome/test_focused_link_scroll.xhtml46
-rw-r--r--dom/tests/mochitest/chrome/test_geolocation.xhtml54
-rw-r--r--dom/tests/mochitest/chrome/test_getTransformTo.html117
-rw-r--r--dom/tests/mochitest/chrome/test_indexedSetter.html38
-rw-r--r--dom/tests/mochitest/chrome/test_intlUtils_getDisplayNames.html351
-rw-r--r--dom/tests/mochitest/chrome/test_intlUtils_isAppLocaleRTL.html37
-rw-r--r--dom/tests/mochitest/chrome/test_moving_nodeList.xhtml44
-rw-r--r--dom/tests/mochitest/chrome/test_moving_xhr.xhtml40
-rw-r--r--dom/tests/mochitest/chrome/test_nodesFromPoint.html119
-rw-r--r--dom/tests/mochitest/chrome/test_nodesFromRect.html21
-rw-r--r--dom/tests/mochitest/chrome/test_parsingMode.html72
-rw-r--r--dom/tests/mochitest/chrome/test_popup_blocker_chrome.xhtml66
-rw-r--r--dom/tests/mochitest/chrome/test_queryCaretRect.html22
-rw-r--r--dom/tests/mochitest/chrome/test_resize_move_windows.xhtml249
-rw-r--r--dom/tests/mochitest/chrome/test_sandbox_bindings.xhtml317
-rw-r--r--dom/tests/mochitest/chrome/test_sandbox_eventhandler.xhtml37
-rw-r--r--dom/tests/mochitest/chrome/test_sandbox_image.xhtml37
-rw-r--r--dom/tests/mochitest/chrome/test_sandbox_postMessage.html36
-rw-r--r--dom/tests/mochitest/chrome/test_selectAtPoint.html21
-rw-r--r--dom/tests/mochitest/chrome/test_sizemode_attribute.xhtml26
-rw-r--r--dom/tests/mochitest/chrome/test_subscript_bindings.xhtml44
-rw-r--r--dom/tests/mochitest/chrome/test_window_getRegionalPrefsLocales.html28
-rw-r--r--dom/tests/mochitest/chrome/test_xray_event_constructor.xhtml35
-rw-r--r--dom/tests/mochitest/chrome/window_activation.xhtml37
-rw-r--r--dom/tests/mochitest/chrome/window_callback_wrapping.xhtml21
-rw-r--r--dom/tests/mochitest/chrome/window_docshell_swap.xhtml8
-rw-r--r--dom/tests/mochitest/chrome/window_focus.xhtml1699
-rw-r--r--dom/tests/mochitest/chrome/window_focus_docnav.xhtml124
-rw-r--r--dom/tests/mochitest/chrome/window_focus_inner.xhtml12
70 files changed, 6256 insertions, 0 deletions
diff --git a/dom/tests/mochitest/chrome/489127.html b/dom/tests/mochitest/chrome/489127.html
new file mode 100644
index 0000000000..0e2fd4efd4
--- /dev/null
+++ b/dom/tests/mochitest/chrome/489127.html
@@ -0,0 +1,268 @@
+<!DOCTYPE HTML>
+<title>nsIDOMWindowUtils::nodesFromRect test - bug 489127</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+<script>
+ var SimpleTest = window.opener.SimpleTest;
+ function ok() { window.opener.ok.apply(window.opener, arguments); }
+ function done() { window.opener.done.apply(window.opener, arguments); }
+ function info() { window.opener.info.apply(window.opener, arguments); }
+
+ let e = {};
+
+ let dwu = window.windowUtils;
+
+ function check(x, y, top, right, bottom, left, onlyVisible, list, aListIsComplete = false, aOpacityThreshold = 1.0) {
+ let nodes = dwu.nodesFromRect(x, y, top, right, bottom, left, /* aIgnoreRootScrollFrame = */ true, /* aFlushLayout = */ true, onlyVisible, aOpacityThreshold);
+
+ if (!aListIsComplete) {
+ list.push(e.body);
+ list.push(e.html);
+ }
+
+ if (nodes.length != list.length) {
+ ok(false, "Different number of nodes (" + nodes.length + " vs. " + list.length +
+ ") for rect [" + x + "," + y + "], " +
+ "[" + top + "," + right + "," + bottom + "," + left + "]");
+ return;
+ }
+
+ for (var i = 0; i < nodes.length; i++) {
+ if (nodes[i] != list[i]) {
+ ok(false, `Unexpected node #${i} (${nodes[i].id} vs. ${list[i].id}) ` +
+ `[${x}, ${y}] [${top}, ${right}, ${bottom}, ${left}]`);
+ return;
+ }
+ }
+ ok(true, "All correct nodes found for rect " +
+ "[" + x + "," + y + "], " +
+ "[" + top + "," + right + "," + bottom + "," + left + "]");
+ }
+
+ function doTest() {
+ // Set up shortcut access to elements
+ e.html = document.documentElement;
+ ['h1', 'd1', 'd2', 'p1', 'p2', 'p3', 'p4', 'p5', 'p6', 'span',
+ 'a1', 'a2', 'a3', 'transf', 'iframe1', 'body', 'opacity', 'host'].forEach(function(a) {
+ e[a] = document.getElementById(a);
+ });
+
+ let shadow = e.host.attachShadow({ mode: "open" });
+ shadow.innerHTML = `
+ <style>
+ #host-inner { height: 100px; width: 100px; background-color: blue }
+ </style>
+ <div id="host-inner"></div>
+ `;
+
+ window.scrollTo(0, 0);
+
+ // Top, Right, Bottom, Left directions:
+ check(53, 71, 0, 0, 0, 0, false, []);
+ check(53, 71, 10, 0, 0, 0, false, [e.h1]);
+ check(53, 71, 0, 10, 0, 0, false, [e.p3]);
+ check(53, 71, 0, 0, 10, 0, false, [e.d1]);
+ check(152, 105, 0, 0, 0, 10, false, [e.d1]);
+ check(152, 105, 10, 10, 10, 10, false, [e.p4, e.p3, e.d1]);
+
+ // e.p1 is invisible and shouldn't appear:
+ check(153,193,0,0,0,0,false,[e.p5]);
+ check(153,193,0,20,0,20, false, [e.p5, e.d2]);
+
+ // Precise pixel checks:
+ check(144, 183, 0, 0, 0, 0, false, []);
+ check(144, 183, 0, 0, 1, 0, false, [e.p5]);
+ check(144, 183, 0, 0, 0, 1, false, [e.d2]);
+ check(144, 183, 0, 0, 1, 1, false, [e.p5, e.d2]);
+ check(77, 240, 0, 0, 0, 0, false, [e.p2]);
+ check(77, 240, 1, 0, 0, 0, false, [e.p5, e.p2]);
+ check(77, 240, 0, 0, 1, 0, false, [e.span, e.p2]);
+ check(77, 240, 1, 0, 1, 0, false, [e.p5, e.span, e.p2]);
+
+ // Expanding area checks:
+ check(39, 212, 0, 0, 0, 0, false, []);
+ check(39, 212, 10, 0, 0, 0, false, [e.d2]);
+ check(39, 212, 0, 0, 10, 0, false, [e.p2]);
+ check(39, 212, 10, 1, 30, 0, false, [e.d2, e.p2]);
+ check(39, 212, 10, 5, 30, 0, false, [e.span, e.d2, e.p2]);
+ check(39, 212, 10, 15, 30, 0, false, [e.p5, e.span, e.d2, e.p2]);
+
+ // Elements inside iframe shouldn't be returned:
+ check(15, 410, 0, 30, 50, 0, false, [e.iframe1]);
+
+ // Area with links and text nodes:
+ let [x1, y1] = getCenterFor(e.a1);
+ let [x2, y2] = getCenterFor(e.a2);
+ let [x3, y3] = getCenterFor(e.a3);
+ let [xt, yt] = [(x2 + x1) / 2, y1]; //text node between a1 and a2
+
+ check(x1, y1, 0, 0, 0, 0, false, [e.a1.firstChild, e.a1, e.p6]);
+ check(x1, y1, 0, 0, y3 - y1, 0, false, [e.a3.firstChild, e.a3, e.a1.firstChild, e.a1, e.p6]);
+ check(x1, y1, 0, xt - x1, 0, 0, false, [e.p6.childNodes[1], e.a1.firstChild, e.a1, e.p6]);
+ check(x1, y1, 0, x2 - x1, 0, 0, false, [e.a2.firstChild, e.a2, e.p6.childNodes[1], e.a1.firstChild, e.a1, e.p6]);
+ check(x1, y1, 0, x2 - x1, y3 - y1, 0, false, [e.a3.firstChild, e.a3, e.a2.firstChild, e.a2, e.p6.childNodes[1], e.a1.firstChild, e.a1, e.p6]);
+
+ // 2d transform:
+ check(61, 671, 0, 0, 0, 0, false, []);
+ check(61, 671, 0, 30, 0, 10, false, [e.transf]);
+ check(61, 671, 0, 30, 90, 10, false, [e.transf.firstChild, e.transf]);
+
+ {
+ info("opacity: with and without aVisibleOnly = true");
+ let [x, y] = getCenterFor(e.opacity);
+ check(x, y, 1, 1, 1, 1, false, [e.opacity]);
+ check(x, y, 1, 1, 1, 1, true, []);
+ }
+
+ // Check elements behind opaque backgrounds of other elements don't show up
+ // in the list when aVisibleOnly = true.
+ {
+ info("elements behind opaque backgrounds of other elements with aVisibleOnly=true");
+ let container = document.getElementById('obscured-test');
+ let fg = document.getElementById('obscured-test-foreground');
+ let bg = document.getElementById('obscured-test-background');
+
+ let [x, y] = getCenterFor(container);
+ check(x, y, 1, 1, 1, 1, false, [fg, bg, container]);
+
+ const kListIsComplete = true;
+
+ check(x, y, 1, 1, 1, 1, true, [fg], kListIsComplete);
+ check(x, y, 1, 1, 1, 1, true, [fg], kListIsComplete, 0.5);
+
+ info("Occluded with different opacity thresholds, with background colors and opacity");
+ fg.style.backgroundColor = "rgba(0, 255, 0, 0.5)";
+ check(x, y, 1, 1, 1, 1, true, [fg], kListIsComplete, 0.4);
+ check(x, y, 1, 1, 1, 1, true, [fg, bg], kListIsComplete, 0.6);
+
+ fg.style.backgroundColor = "";
+ fg.style.opacity = "0.5";
+
+ check(x, y, 1, 1, 1, 1, true, [fg], kListIsComplete, 0.4);
+ check(x, y, 1, 1, 1, 1, true, [fg, bg], kListIsComplete, 0.6);
+ }
+
+ {
+ info("Shadow DOM retargeting");
+
+ let [x, y] = getCenterFor(e.host);
+ let inner = shadow.getElementById("host-inner");
+ check(x, y, 1, 1, 1, 1, false, [inner, e.host]);
+ }
+
+ done();
+ }
+
+ function getCenterFor(element) {
+ let rect = element.getBoundingClientRect();
+ return [(rect.left + rect.right) / 2, (rect.top + rect.bottom) / 2];
+ }
+
+ addLoadEvent(doTest);
+</script>
+<style>
+body {
+ margin: 8px;
+ padding: 0;
+}
+
+h1, div, p, span, iframe {
+ display: block;
+ width: 100px;
+ height: 30px;
+ border: 3px solid black;
+ padding: 10px;
+ margin: 10px;
+}
+
+span {
+ display: inline-block;
+}
+
+#iframe1 {
+ height: 100px;
+ margin-top: 60px;
+}
+
+#p6 {
+ height: 50px;
+ margin-top: 30px;
+}
+
+#transf {
+ margin-top: 60px;
+ -moz-transform: rotate(-45deg);
+}
+
+#opacity {
+ opacity: 0;
+ margin-top: 60px;
+}
+
+#decimal {
+ position: relative;
+ left: 0.5px;
+ top: 50.5px;
+}
+
+#obscured-test {
+ position: relative;
+ width: 500px;
+ height: 500px;
+}
+
+#obscured-test-background {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ z-index: 0;
+ background: red;
+}
+
+#obscured-test-foreground {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ z-index: 1;
+ background: green;
+}
+</style>
+<body id="body">
+ <h1 id="h1"></h1>
+ <div id="d1"></div>
+
+ <!-- floated element -->
+ <div id="d2" style="float: left"></div>
+
+ <!-- hidden element -->
+ <p id="p1" style="float: left; visibility: hidden"></p>
+
+ <p id="p2" style="clear: left"><span id="span"></span></p>
+
+ <!-- absolute position -->
+ <p id="p3" style="position:absolute; top: 10px; left:50px; height:50px;"></p>
+
+ <!-- fixed position -->
+ <p id="p4" style="position: fixed; top: 30px; left: 150px; height: 50px; background-color: blue;"></p>
+
+ <!-- relative position -->
+ <p id="p5" style="position:relative; top: -100px; left: 30px; margin-bottom: -70px; background-color: green"></p>
+
+ <!-- decimal CSS pixels -->
+ <div id="decimal"></div>
+
+ <iframe id="iframe1" src="data:text/html,<div>div</div><p>p</p>"></iframe>
+
+ <p id="p6"><a href="#" id="a1">A</a> / <a href="#" id="a2">A</a><br/><a href="#" id="a3">A</a></p>
+
+ <div id="transf">text</div>
+
+ <div id="opacity">text</div>
+
+ <div id="host"></div>
+
+ <div id="obscured-test">
+ <div id="obscured-test-background"></div>
+ <div id="obscured-test-foreground"></div>
+ </div>
+</body>
diff --git a/dom/tests/mochitest/chrome/DOMWindowCreated_chrome.xhtml b/dom/tests/mochitest/chrome/DOMWindowCreated_chrome.xhtml
new file mode 100644
index 0000000000..3ce8724fa0
--- /dev/null
+++ b/dom/tests/mochitest/chrome/DOMWindowCreated_chrome.xhtml
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+<!--
+ Test for Persistent Storage in chrome
+ -->
+<window id="sample-window" width="400" height="400"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript"
+ src="chrome://mochikit/content/chrome-harness.js"></script>
+
+<script type="application/javascript">
+var SimpleTest = window.arguments[0].SimpleTest;
+
+document.addEventListener("DOMWindowCreated", function(e) {
+ var otherWindow = e.target.defaultView.wrappedJSObject;
+ SimpleTest.is(e.type, "DOMWindowCreated", "DOMWindowCreated: " + otherWindow);
+ otherWindow.doneFunction = function() {
+ SimpleTest.ok(true, "doneFunction was called");
+ SimpleTest.finish();
+ window.close();
+ };
+}, false);
+
+var root = getRootDirectory(window.location.href);
+var el = document.createXULElement("iframe");
+el.setAttribute('type', 'content');
+el.setAttribute('src', root + 'DOMWindowCreated_content.html');
+document.documentElement.appendChild(el);
+</script>
+</window>
diff --git a/dom/tests/mochitest/chrome/DOMWindowCreated_content.html b/dom/tests/mochitest/chrome/DOMWindowCreated_content.html
new file mode 100644
index 0000000000..acb6b0582e
--- /dev/null
+++ b/dom/tests/mochitest/chrome/DOMWindowCreated_content.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+ <title>DOMWindowCreated helper</title>
+
+ <script type="application/javascript">
+ window.doneFunction();
+ </script>
+<body>
+ <h1>DOMWindowCreated Helper</h1>
diff --git a/dom/tests/mochitest/chrome/child_focus_frame.html b/dom/tests/mochitest/chrome/child_focus_frame.html
new file mode 100644
index 0000000000..d7f0ff63cd
--- /dev/null
+++ b/dom/tests/mochitest/chrome/child_focus_frame.html
@@ -0,0 +1,57 @@
+<html id="t13">
+<body id="inner-document">
+
+<input id="t19" value="Input" accesskey="b">
+<input id="t14" tabindex="2" type="password" value="test">
+<button id="t20">Button</button>
+<div style="float: left; margin-top: 30px;">
+ <button id="t21">Button 2</button>
+</div>
+<div id="abs" style="position: absolute; top: 40px; left: 250px;">
+ <button id="t22" accesskey="c">Button 3</button>
+ <p><span>
+ <select id="t15" tabindex="2" accesskey="e">
+ <option>One
+ </select>
+ </span></p>
+</div>
+<div id="t16" tabindex="2" style="overflow: scroll; max-height: 20px;">
+ This is a scrollable area with some sufficiently long text contained within it.
+</div>
+<img id="n5" src="happy.png"/>
+<img id="t23" tabindex="0" src="happy.png"/>
+<a id="t17" tabindex="2" accesskey="f">1</a>
+<a id="t24" tabindex="0" href="#">2</a>
+<a id="t25" href="#">Link 3</a>
+<br>
+<span id="hiddenspan" style="display: none;"></span>
+<input id="t26" tabindex="0" type="checkbox" accesskey="a">
+<input id="o11" tabindex="-1" type="checkbox">
+<div style="display: none;"><input/></div>
+<div id="t27" style="overflow: scroll; max-height: 20px;">
+ This is a scrollable area with some sufficiently long text contained within it.
+ This is a scrollable area with some sufficiently long text contained within it.
+ <button id="inscroll" tabindex="-1">Button 4</button>
+</div>
+<map name="map1">
+ <area id="t31" href="#" shape="rect" coords="0,0,5,5">
+ <area id="t32" href="#" shape="rect" coords="10,10,15,15">
+ <area id="t18" href="#" shape="circle" coords="0,8,4" tabindex="2">Button 5</area>
+ <area id="t33" href="#" shape="poly" coords="10,1,16,3,14,10,7,10,10,1">
+</map>
+<input type="hidden"/>
+<fieldset style="float: right;">
+<legend id="legend">Options</legend>
+ <input id="t28" type="radio" name="options" value="optionone">One
+ <label id="ad" accesskey="d">Label:<input id="t29" type="radio" name="options" value="optiontwo">Two</label>
+</fieldset>
+<div id="t30" tabindex="0">abc</div>
+<input id="o18" accesskey="u" disabled size="3"/>
+<label id="ag" accesskey="g" for="n6">L</label>
+<input id="n6" tabindex="-1" type="button"/>
+<span id="n7" accesskey="t">s</span>
+<img id="image" src="data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%18%00%00%00%18%02%03%00%00%00%9D%19%D5k%00%00%00%04gAMA%00%00%B1%8F%0B%FCa%05%00%00%00%0CPLTE%FF%FF%FF%FF%FF%FF%F7%DC%13%00%00%00%03%80%01X%00%00%00%01tRNS%08N%3DPT%00%00%00%01bKGD%00%88%05%1DH%00%00%00%09pHYs%00%00%0B%11%00%00%0B%11%01%7Fd_%91%00%00%00%07tIME%07%D2%05%0C%14%0C%0D%D8%3F%1FQ%00%00%00%5CIDATx%9C%7D%8E%CB%09%C0%20%10D%07r%B7%20%2F%E9wV0%15h%EA%D9%12D4%BB%C1x%CC%5C%1E%0C%CC%07%C0%9C0%9Dd7()%C0A%D3%8D%E0%B8%10%1DiCHM%D0%AC%D2d%C3M%F1%B4%E7%FF%10%0BY%AC%25%93%CD%CBF%B5%B2%C0%3Alh%CD%AE%13%DF%A5%F7%E0%03byW%09A%B4%F3%E2%00%00%00%00IEND%AEB%60%82"
+ usemap="#map1" ismap>
+
+</body>
+</html>
diff --git a/dom/tests/mochitest/chrome/chrome.ini b/dom/tests/mochitest/chrome/chrome.ini
new file mode 100644
index 0000000000..098d49a49b
--- /dev/null
+++ b/dom/tests/mochitest/chrome/chrome.ini
@@ -0,0 +1,91 @@
+[DEFAULT]
+skip-if = os == 'android'
+support-files =
+ 489127.html
+ DOMWindowCreated_chrome.xhtml
+ DOMWindowCreated_content.html
+ child_focus_frame.html
+ file_clipboard_events_chrome.html
+ file_DOM_element_instanceof.xhtml
+ file_bug800817.xhtml
+ file_bug830858.xhtml
+ file_bug1224790-1_modal.xhtml
+ file_bug1224790-1_nonmodal.xhtml
+ file_bug1224790-2_modal.xhtml
+ file_bug1224790-2_nonmodal.xhtml
+ file_popup_blocker_chrome.html
+ file_subscript_bindings.js
+ focus_frameset.html
+ focus_window2.xhtml
+ focus_dialog.xhtml
+ queryCaretRectUnix.html
+ queryCaretRectWin.html
+ selectAtPoint.html
+ selectAtPoint-innerframe.html
+ sizemode_attribute.xhtml
+ window_activation.xhtml
+ window_callback_wrapping.xhtml
+ window_docshell_swap.xhtml
+ window_focus.xhtml
+ window_focus_inner.xhtml
+ window_focus_docnav.xhtml
+ !/dom/tests/mochitest/general/file_clonewrapper.html
+ !/dom/tests/mochitest/general/file_moving_nodeList.html
+ !/dom/tests/mochitest/general/file_moving_xhr.html
+ !/dom/tests/mochitest/geolocation/network_geolocation.sjs
+
+[test_DOMWindowCreated.xhtml]
+[test_DOM_element_instanceof.xhtml]
+[test_activation.xhtml]
+tags = fullscreen
+[test_bug800817.xhtml]
+[test_bug830858.xhtml]
+[test_bug1224790-1.xhtml]
+tags = openwindow
+skip-if = os != 'mac'
+[test_bug1224790-2.xhtml]
+tags = openwindow
+skip-if = os != 'mac'
+[test_callback_wrapping.xhtml]
+[test_clonewrapper.xhtml]
+[test_cyclecollector.xhtml]
+[test_docshell_swap.xhtml]
+[test_elements_proto.xhtml]
+[test_focus.xhtml]
+skip-if =
+ os == 'linux' # bug 1296622, Bug 1605253
+ os == "mac" && !debug # Bug 1828622
+ os == "win" && !debug # Bug 1828622
+[test_focus_dialog.xhtml]
+[test_focus_docnav.xhtml]
+[test_focused_link_scroll.xhtml]
+[test_geolocation.xhtml]
+[test_getTransformTo.html]
+[test_indexedSetter.html]
+[test_intlUtils_getDisplayNames.html]
+[test_intlUtils_isAppLocaleRTL.html]
+[test_moving_nodeList.xhtml]
+[test_moving_xhr.xhtml]
+[test_nodesFromPoint.html]
+[test_nodesFromRect.html]
+[test_parsingMode.html]
+[test_popup_blocker_chrome.xhtml]
+[test_queryCaretRect.html]
+[test_resize_move_windows.xhtml]
+support-files =
+ file_resize_move_windows_1.html
+ file_resize_move_windows_2.html
+# disabled on linux for timeouts--bug-834716
+skip-if = os == 'linux'
+[test_sandbox_bindings.xhtml]
+[test_sandbox_eventhandler.xhtml]
+[test_sandbox_image.xhtml]
+[test_sandbox_postMessage.html]
+[test_selectAtPoint.html]
+[test_sizemode_attribute.xhtml]
+tags = fullscreen
+skip-if = os != 'win'
+[test_subscript_bindings.xhtml]
+[test_xray_event_constructor.xhtml]
+[test_clipboard_events_chrome.html]
+[test_window_getRegionalPrefsLocales.html]
diff --git a/dom/tests/mochitest/chrome/file_DOM_element_instanceof.xhtml b/dom/tests/mochitest/chrome/file_DOM_element_instanceof.xhtml
new file mode 100644
index 0000000000..92290016f0
--- /dev/null
+++ b/dom/tests/mochitest/chrome/file_DOM_element_instanceof.xhtml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<window title="Mozilla Bug 824917"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <iframe type="content"></iframe>
+
+ <script type="application/javascript">
+ <![CDATA[
+ /** Test for Bug 799299 **/
+ var SimpleTest = window.arguments[0].SimpleTest;
+ var ok = window.arguments[0].ok;
+
+ // Note: We can't use frames[0] here because the type="content" attribute
+ // isolates it into a separate browsing context hierarchy.
+ var doc = document.querySelector("iframe").contentDocument;
+ ok(HTMLBodyElement.isInstance(doc.createElement("body")),
+ "Should be instance of HTMLBodyElement");
+ ok(HTMLDivElement.isInstance(doc.createElement("div")),
+ "Should be instance of HTMLDivElement");
+ ok(HTMLFrameSetElement.isInstance(doc.createElement("frameset")),
+ "Should be instance of HTMLFrameSetElement");
+ ok(HTMLHeadingElement.isInstance(doc.createElement("h1")),
+ "Should be instance of HTMLHeadingElement");
+ ok(HTMLLabelElement.isInstance(doc.createElement("label")),
+ "Should be instance of HTMLLabelElement");
+
+ window.close();
+ window.arguments[0].SimpleTest.finish();
+ ]]>
+ </script>
+</window>
diff --git a/dom/tests/mochitest/chrome/file_bug1224790-1_modal.xhtml b/dom/tests/mochitest/chrome/file_bug1224790-1_modal.xhtml
new file mode 100644
index 0000000000..2093ba9c67
--- /dev/null
+++ b/dom/tests/mochitest/chrome/file_bug1224790-1_modal.xhtml
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1224790
+-->
+<window title="Mozilla Bug 1224790"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+<dialog buttons="accept">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ /** Test for Bug 1224790 **/
+
+ function runTests() {
+ window.openDialog('file_bug1224790-1_nonmodal.xhtml', '', 'dialog=no');
+ }
+
+ function nonModalClosed() {
+ window.close();
+ window.arguments[0].modalClosed();
+ }
+
+ SimpleTest.waitForFocus(runTests);
+ ]]>
+ </script>
+</dialog>
+</window>
diff --git a/dom/tests/mochitest/chrome/file_bug1224790-1_nonmodal.xhtml b/dom/tests/mochitest/chrome/file_bug1224790-1_nonmodal.xhtml
new file mode 100644
index 0000000000..01995a916c
--- /dev/null
+++ b/dom/tests/mochitest/chrome/file_bug1224790-1_nonmodal.xhtml
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1224790
+-->
+<window title="Mozilla Bug 1224790"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ /** Test for Bug 1224790 **/
+
+ function runTests() {
+ window.close();
+ opener.wrappedJSObject.nonModalClosed();
+ }
+
+ SimpleTest.waitForFocus(runTests);
+ ]]>
+ </script>
+</window>
diff --git a/dom/tests/mochitest/chrome/file_bug1224790-2_modal.xhtml b/dom/tests/mochitest/chrome/file_bug1224790-2_modal.xhtml
new file mode 100644
index 0000000000..74906a05f8
--- /dev/null
+++ b/dom/tests/mochitest/chrome/file_bug1224790-2_modal.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1224790
+-->
+<window title="Mozilla Bug 1224790"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+<dialog buttons="accept">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ /** Test for Bug 1224790 **/
+
+ var nonModal = null;
+
+ function runTests() {
+ nonModal = window.openDialog('file_bug1224790-2_nonmodal.xhtml', '', 'dialog=no');
+ }
+
+ function nonModalOpened() {
+ window.close();
+ nonModal.modalClosed(window.arguments[0]);
+ }
+
+ SimpleTest.waitForFocus(runTests);
+ ]]>
+ </script>
+</dialog>
+</window>
diff --git a/dom/tests/mochitest/chrome/file_bug1224790-2_nonmodal.xhtml b/dom/tests/mochitest/chrome/file_bug1224790-2_nonmodal.xhtml
new file mode 100644
index 0000000000..5e3c737676
--- /dev/null
+++ b/dom/tests/mochitest/chrome/file_bug1224790-2_nonmodal.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1224790
+-->
+<window title="Mozilla Bug 1224790"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ /** Test for Bug 1224790 **/
+
+ function runTests() {
+ opener.wrappedJSObject.nonModalOpened()
+ }
+
+ function modalClosed(grandparent) {
+ // Request cycle collection to trigger destructor for parent modal window,
+ // that mutates mAncestorLink of this window.
+ var windowUtils = window.windowUtils;
+
+ Services.obs.notifyObservers(null, "child-cc-request");
+ windowUtils.cycleCollect();
+
+ // Wait for a while.
+ setTimeout(function() {
+ window.close();
+ grandparent.wrappedJSObject.nonModalClosed();
+ }, 3000);
+ }
+
+ SimpleTest.waitForFocus(runTests);
+ ]]>
+ </script>
+</window>
diff --git a/dom/tests/mochitest/chrome/file_bug800817.xhtml b/dom/tests/mochitest/chrome/file_bug800817.xhtml
new file mode 100644
index 0000000000..bcd64b3ca7
--- /dev/null
+++ b/dom/tests/mochitest/chrome/file_bug800817.xhtml
@@ -0,0 +1,79 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=800817
+-->
+<window title="Mozilla Bug 800817"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+ <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=800817"
+ target="_blank">Mozilla Bug 800817</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ /** Test for Bug 800817 **/
+
+ function sendClick(win) {
+ var wu = win.windowUtils;
+ wu.sendMouseEventToWindow("mousedown", 10, 10, 0, 0, 0);
+ wu.sendMouseEventToWindow("mouseup", 10, 10, 0, 0, 0);
+ }
+
+ function runTests() {
+ var b1 = document.getElementById("b1");
+ var b2 = document.getElementById("b2");
+
+ var testMozBrowser = window.arguments[0].testMozBrowser;
+ if (testMozBrowser) {
+ b1.setAttribute("mozbrowser", "true");
+ b2.setAttribute("mozbrowser", "true");
+ }
+
+ if (testMozBrowser)
+ window.arguments[0].info("Testing with mozbrowser=true");
+ else
+ window.arguments[0].info("Testing without mozbrowser");
+
+ b1.contentWindow.focus();
+ window.arguments[0].is(document.activeElement, b1,
+ "Focused first iframe");
+
+ var didCallDummy = false;
+ b2.contentWindow.addEventListener("mousedown", function(e) { didCallDummy = true; });
+ sendClick(b2.contentWindow);
+ window.arguments[0].ok(didCallDummy, "dummy mousedown handler should fire");
+ window.arguments[0].is(document.activeElement, b2,
+ "Focus shifted to second iframe");
+
+ b1.contentWindow.focus();
+ window.arguments[0].is(document.activeElement, b1,
+ "Re-focused first iframe for the first time");
+
+ var didCallListener = false;
+ b2.contentWindow.addEventListener("mousedown", function(e) { didCallListener = true; e.preventDefault(); });
+ sendClick(b2.contentWindow);
+ window.arguments[0].ok(didCallListener, "mousedown handler should fire");
+ window.arguments[0].is(document.activeElement, b1,
+ "Did not move focus to the second iframe");
+
+ window.close();
+ window.arguments[0].finishedTests();
+ }
+
+ SimpleTest.waitForFocus(runTests);
+ ]]>
+ </script>
+ <iframe xmlns="http://www.w3.org/1999/xhtml"
+ id="b1" type="content" src="about:blank"
+ style="width: 300px; height: 550px; border: 1px solid black;"/>
+ <iframe xmlns="http://www.w3.org/1999/xhtml"
+ id="b2" type="content" src="about:blank"
+ style="width: 300px; height: 550px; border: 1px solid black;"/>
+</window>
diff --git a/dom/tests/mochitest/chrome/file_bug830858.xhtml b/dom/tests/mochitest/chrome/file_bug830858.xhtml
new file mode 100644
index 0000000000..1865f52ac3
--- /dev/null
+++ b/dom/tests/mochitest/chrome/file_bug830858.xhtml
@@ -0,0 +1,66 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=830858
+-->
+<window title="Mozilla Bug 830858"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+ <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=830858"
+ target="_blank">Mozilla Bug 830858</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ /** Test for Bug 830858 **/
+
+ function runTests() {
+ var b = document.getElementById("b");
+ var win = b.contentWindow;
+ var doc = win.document;
+ var wu = win.windowUtils;
+
+ var docListenerCalled = 0;
+ doc.addEventListener("foo", function() { ++docListenerCalled; }, true);
+ var winListenerCalled = 0;
+ win.addEventListener("foo", function() { ++winListenerCalled; }, true);
+ var iframeListenerCalled = 0;
+ b.addEventListener("foo", function() { ++iframeListenerCalled; }, true);
+
+ doc.dispatchEvent(new Event("foo"));
+ window.arguments[0].is(docListenerCalled, 1, "Normal dispatch to Document");
+ window.arguments[0].is(winListenerCalled, 1, "Normal dispatch to Document");
+ window.arguments[0].is(iframeListenerCalled, 1, "Normal dispatch to Document");
+
+ win.dispatchEvent(new Event("foo"));
+ window.arguments[0].is(docListenerCalled, 1, "Normal dispatch to Window");
+ window.arguments[0].is(winListenerCalled, 2, "Normal dispatch to Window");
+ window.arguments[0].is(iframeListenerCalled, 2, "Normal dispatch to Window");
+
+ wu.dispatchEventToChromeOnly(doc, new Event("foo"));
+ window.arguments[0].is(docListenerCalled, 1, "Chrome-only dispatch to Document");
+ window.arguments[0].is(winListenerCalled, 2, "Chrome-only dispatch to Document");
+ window.arguments[0].is(iframeListenerCalled, 3, "Chrome-only dispatch to Document");
+
+ wu.dispatchEventToChromeOnly(win, new Event("foo"));
+ window.arguments[0].is(docListenerCalled, 1, "Chrome-only dispatch to Window");
+ window.arguments[0].is(winListenerCalled, 2, "Chrome-only dispatch to Window");
+ window.arguments[0].is(iframeListenerCalled, 4, "Chrome-only dispatch to Window");
+
+ window.close();
+ window.arguments[0].finishedTests();
+ }
+
+ SimpleTest.waitForFocus(runTests);
+ ]]>
+ </script>
+ <iframe xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ id="b" type="content" src="about:blank"
+ style="width: 300px; height: 550px; border: 1px solid black;"/>
+</window>
diff --git a/dom/tests/mochitest/chrome/file_clipboard_events_chrome.html b/dom/tests/mochitest/chrome/file_clipboard_events_chrome.html
new file mode 100644
index 0000000000..652d1e981f
--- /dev/null
+++ b/dom/tests/mochitest/chrome/file_clipboard_events_chrome.html
@@ -0,0 +1 @@
+<body onload='window.arguments[0].doChecks(this)'><input id='i' value='Sample Text'></body>
diff --git a/dom/tests/mochitest/chrome/file_popup_blocker_chrome.html b/dom/tests/mochitest/chrome/file_popup_blocker_chrome.html
new file mode 100644
index 0000000000..28463b14a6
--- /dev/null
+++ b/dom/tests/mochitest/chrome/file_popup_blocker_chrome.html
@@ -0,0 +1,6 @@
+<html>
+<body onload="window.opener.next()">
+foobar
+</script>
+</body>
+</html>
diff --git a/dom/tests/mochitest/chrome/file_resize_move_windows_1.html b/dom/tests/mochitest/chrome/file_resize_move_windows_1.html
new file mode 100644
index 0000000000..2c3b1b9c8f
--- /dev/null
+++ b/dom/tests/mochitest/chrome/file_resize_move_windows_1.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Helper file for test_resize_move_windows.html</title>
+<script>
+function check(next) {
+ var is_range = function(aTest, aValue, aRange, aMsg) {
+ ok(aTest < aValue + aRange && aTest > aValue - aRange, aMsg);
+ };
+ is_range(window.innerWidth, 170, 5, 'parameter width should be taken into account');
+ is_range(window.innerHeight, 170, 5, 'parameter height should be taken into account');
+ is_range(window.screenX, 25, 5, 'parameter screenX should be taken into account');
+ is_range(window.screenY, 25, 5, 'parameter screenY should be taken into account');
+}
+</script>
+</head>
+<body onload="console.log('load')">
+</body>
+</html>
diff --git a/dom/tests/mochitest/chrome/file_resize_move_windows_2.html b/dom/tests/mochitest/chrome/file_resize_move_windows_2.html
new file mode 100644
index 0000000000..81b67587a7
--- /dev/null
+++ b/dom/tests/mochitest/chrome/file_resize_move_windows_2.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Helper file for test_resize_move_windows.xhtml</title>
+</head>
+<body>
+</body>
+</html>
diff --git a/dom/tests/mochitest/chrome/file_subscript_bindings.js b/dom/tests/mochitest/chrome/file_subscript_bindings.js
new file mode 100644
index 0000000000..cfc9128d31
--- /dev/null
+++ b/dom/tests/mochitest/chrome/file_subscript_bindings.js
@@ -0,0 +1 @@
+new window.XMLHttpRequest();
diff --git a/dom/tests/mochitest/chrome/focus_dialog.xhtml b/dom/tests/mochitest/chrome/focus_dialog.xhtml
new file mode 100644
index 0000000000..24eda7ad1b
--- /dev/null
+++ b/dom/tests/mochitest/chrome/focus_dialog.xhtml
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="other-document"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+<dialog buttons="accept">
+
+<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+
+<button id="button-1" label="Something"/>
+<button id="button-2" label="Something else"/>
+
+<script>
+<![CDATA[
+
+window.is = window.arguments[0].is;
+window.isnot = window.arguments[0].isnot;
+window.ok = window.arguments[0].ok;
+window.SimpleTest = window.arguments[0].SimpleTest;
+
+(async function() {
+ await new Promise(resolve => {
+ window.onload = resolve;
+ });
+
+ await new Promise(resolve => SimpleTest.waitForFocus(resolve, window));
+
+ let dialog = document.querySelector("dialog");
+ let shadow = dialog.shadowRoot;
+
+ let button = document.getElementById("button-1");
+ let button2 = document.getElementById("button-2");
+ let forwardSequence = [];
+
+ button.focus();
+
+ is(document.activeElement, button, "Should've focused the button");
+ forwardSequence.push(button);
+
+ synthesizeKey("KEY_Tab");
+
+ is(document.activeElement, button2, "Should've moved to the second button");
+ forwardSequence.push(button2);
+
+ synthesizeKey("KEY_Tab");
+
+ isnot(shadow.activeElement, null, "Should've focused the shadow root button");
+ is(document.activeElement, dialog, "document.focusedElement should be the dialog because retargeting");
+ forwardSequence.push(shadow.activeElement);
+
+ synthesizeKey("KEY_Tab");
+
+ is(document.activeElement, button, "Should properly wrap around going forward");
+
+ while (forwardSequence.length) {
+ synthesizeKey("KEY_Tab", { shiftKey: true });
+ is(
+ shadow.activeElement || document.activeElement,
+ forwardSequence.pop(),
+ "Should travel backwards correctly: " + forwardSequence.length
+ );
+ }
+
+ window.close();
+ SimpleTest.finish();
+}());
+
+]]>
+</script>
+</dialog>
+</window>
diff --git a/dom/tests/mochitest/chrome/focus_frameset.html b/dom/tests/mochitest/chrome/focus_frameset.html
new file mode 100644
index 0000000000..4032575552
--- /dev/null
+++ b/dom/tests/mochitest/chrome/focus_frameset.html
@@ -0,0 +1,25 @@
+<html id="outer">
+
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+if (opener)
+ SimpleTest.waitForFocus(() => opener.framesetWindowLoaded(window));
+// Don't try to call finish() in this frame, since it will get upset that we
+// ran no tests.
+SimpleTest.waitForExplicitFinish();
+</script>
+
+<frameset rows="30%, 70%">
+ <frame src="data:text/html,&lt;html id='f1' &gt;&lt;body id='framebody1'&gt;&lt;input id='f2'&gt;&lt;body&gt;&lt;/html&gt;">
+ <frameset cols="30%, 33%, 34%">
+ <frame src="data:text/html,&lt;html id='f3'&gt;&lt;body id='framebody2'&gt;&lt;input id='f4'&gt;&lt;body&gt;&lt;/html&gt;">
+ <frame src="data:text/html,&lt;html id='f5'&gt;&lt;body id='framebody3'&gt;&lt;input id='f6' tabindex='2'&gt;&lt;body&gt;&lt;/html&gt;">
+ <frame src="data:text/html,&lt;html id='f7'&gt;&lt;body id='framebody4'&gt;&lt;input id='f8'&gt;&lt;body&gt;&lt;/html&gt;">
+ </frameset>
+ <noframes>
+ <input id="unused1"/>
+ <input id="unused2" tabindex="1"/>
+ </noframes>
+</frameset>
+
+</html>
diff --git a/dom/tests/mochitest/chrome/focus_window2.xhtml b/dom/tests/mochitest/chrome/focus_window2.xhtml
new file mode 100644
index 0000000000..63f973b1dc
--- /dev/null
+++ b/dom/tests/mochitest/chrome/focus_window2.xhtml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="other-document"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<script>
+<![CDATA[
+
+function focused()
+{
+ if (window.arguments)
+ setTimeout(() => window.arguments[0](window, window.arguments[1]), 0);
+}
+
+SimpleTest.waitForFocus(focused);
+
+]]>
+</script>
+
+<button id="other" label="OK"/>
+<input xmlns="http://www.w3.org/1999/xhtml" id="other-input" value="test"/>
+
+</window>
diff --git a/dom/tests/mochitest/chrome/queryCaretRectUnix.html b/dom/tests/mochitest/chrome/queryCaretRectUnix.html
new file mode 100644
index 0000000000..0f06f838de
--- /dev/null
+++ b/dom/tests/mochitest/chrome/queryCaretRectUnix.html
@@ -0,0 +1,209 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>nsIDOMWindowUtils::sendQueryContentEvent w/QUERY_CARET_RECT test</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+
+<style>
+ #text {
+ position: absolute;
+ left: 0em;
+ top: 0em;
+ font-size: 10pt;
+ font-family: monospace;
+ line-height: 20px;
+ letter-spacing: 0px;
+ margin-top:-1px; /* nix the text area border */
+ overflow: hidden;
+ width:800px;
+ height:400px;
+ }
+ #div-hor {
+ position: absolute;
+ left: 0em;
+ border-top:1px solid lightgray;
+ width: 1000px;
+ pointer-events:none;
+ }
+ #div-ver {
+ position: absolute;
+ top: 0em;
+ border-left:1px solid lightgray;
+ height: 500px;
+ pointer-events:none;
+ }
+</style>
+
+<script type="application/javascript">
+ var SimpleTest = window.opener.SimpleTest;
+
+ function ok() { window.opener.ok.apply(window.opener, arguments); }
+ function done() { window.opener.done.apply(window.opener, arguments); }
+
+ function dumpLn() {
+ for (let idx = 0; idx < arguments.length; idx++)
+ dump(arguments[idx] + " ");
+ dump("\n");
+ }
+
+ // drawn grid is 20x20
+ function drawGrid() {
+ for (var idx = 0; idx < 20; idx++) {
+ var e = document.createElement("div");
+ e.setAttribute("id", "div-hor");
+ e.style.top = (idx*20) + "px";
+ document.getElementById("container").appendChild(e);
+ }
+ for (var idx = 0; idx < 40; idx++) {
+ var e = document.createElement("div");
+ e.setAttribute("id", "div-ver");
+ e.style.left = (idx*20) + "px";
+ document.getElementById("container").appendChild(e);
+ }
+ }
+
+ function getSelection(aElement) {
+ // aElement is known to be a textarea here.
+ return aElement.editor.selection;
+ }
+
+ function testCaretPosition(aDomWinUtils, aOffset, aRectDims) {
+ let rect = aDomWinUtils.sendQueryContentEvent(
+ aDomWinUtils.QUERY_CARET_RECT,
+ aOffset, 0, 0, 0,
+ aDomWinUtils.QUERY_CONTENT_FLAG_USE_XP_LINE_BREAK);
+ ok(rect, "rect returned");
+ ok(rect.succeeded, "call succeeded");
+
+ info("left:" + rect.left + " top:" + rect.top);
+
+ ok(rect.left > aRectDims.min.left, "rect.left > " + aRectDims.min.left);
+ ok(rect.left < aRectDims.max.left, "rect.left < " + aRectDims.max.left);
+ ok(rect.top > aRectDims.min.top, "rect.top > " + aRectDims.min.top);
+ ok(rect.top < aRectDims.max.top, "rect.top < " + aRectDims.max.top);
+ }
+
+ function doTest() {
+ let domWinUtils = window.windowUtils;
+
+ let text = document.getElementById("text");
+
+ text.focus();
+
+ let textrect = text.getBoundingClientRect();
+
+ let cp = document.caretPositionFromPoint(10, 395);
+ let input = cp.offsetNode;
+ let offset = cp.offset;
+ input.selectionStart = input.selectionEnd = offset;
+
+ let selection = getSelection(text);
+
+ testCaretPosition(domWinUtils, input.selectionStart, {
+ min: { left: 5, top: 380 },
+ max: { left: 25, top: 390 },
+ });
+
+ testCaretPosition(domWinUtils, input.selectionEnd, {
+ min: { left: 5, top: 380 },
+ max: { left: 25, top: 390 },
+ });
+
+ testCaretPosition(domWinUtils, text.selectionStart, {
+ min: { left: 5, top: 380 },
+ max: { left: 25, top: 390 },
+ });
+
+ testCaretPosition(domWinUtils, text.selectionEnd, {
+ min: { left: 5, top: 380 },
+ max: { left: 25, top: 390 },
+ });
+
+ testCaretPosition(domWinUtils, selection.anchorOffset, {
+ min: { left: 5, top: 380 },
+ max: { left: 25, top: 390 },
+ });
+
+ testCaretPosition(domWinUtils, selection.focusOffset, {
+ min: { left: 5, top: 380 },
+ max: { left: 25, top: 390 },
+ });
+
+ cp = document.caretPositionFromPoint(395, 395);
+ input = cp.offsetNode;
+ offset = cp.offset;
+ input.selectionStart = input.selectionEnd = offset;
+
+ selection = getSelection(text);
+
+ testCaretPosition(domWinUtils, input.selectionStart, {
+ min: { left: 390, top: 380 },
+ max: { left: 400, top: 390 },
+ });
+
+ testCaretPosition(domWinUtils, input.selectionEnd, {
+ min: { left: 390, top: 380 },
+ max: { left: 400, top: 390 },
+ });
+
+ testCaretPosition(domWinUtils, text.selectionStart, {
+ min: { left: 390, top: 380 },
+ max: { left: 400, top: 390 },
+ });
+
+ testCaretPosition(domWinUtils, text.selectionEnd, {
+ min: { left: 390, top: 380 },
+ max: { left: 400, top: 390 },
+ });
+
+ testCaretPosition(domWinUtils, selection.anchorOffset, {
+ min: { left: 390, top: 380 },
+ max: { left: 400, top: 390 },
+ });
+
+ testCaretPosition(domWinUtils, selection.focusOffset, {
+ min: { left: 390, top: 380 },
+ max: { left: 400, top: 390 },
+ });
+
+ done();
+ }
+
+</script>
+
+<body onload="doTest()">
+<textarea id="text" wrap="on">
+Alice was beginning to get very tired of sitting by her sister on the bank,
+and of having nothing to do: once or twice she had peeped into the book
+her sister was reading, but it had no pictures or conversations in it,
+`and what is the use of a book,' thought Alice `without pictures or
+conversation?'
+
+So she was considering in her own mind (as well as she could, for the
+hot day made her feel very sleepy and stupid), whether the pleasure of
+making a daisy-chain would be worth the trouble of getting up and
+picking the daisies, when suddenly a White Rabbit with pink In another
+moment down went Alice after it, never once considering how in the world
+she was to get out again.
+
+The rabbit-hole went straight on like a tunnel for some way, and then
+dipped suddenly down, so suddenly that Alice had not a moment to think
+about stopping herself before she found herself falling down a very deep
+well.
+
+Either the well was very deep, or she fell very slowly, for she had
+plenty of time as she went down to look about her and to wonder what was
+ going to happen next. First, she tried to look down and make out what
+she was coming to, but it was too dark to see anything; then she looked
+at the sides of the well, and noticed that they were filled with
+cupboards and book-shelves; here and there she saw maps and pictures
+hung upon pegs. She took down a jar from one of the shelves as she
+passed; it was labelled `ORANGE MARMALADE', but to her great
+disappointment it was empty: she did not like to drop the jar for fear
+of killing somebody, so managed to put it into one of the cupboards as
+she fell past it.
+</textarea>
+<div id="container"></div>
+</body>
+</html>
diff --git a/dom/tests/mochitest/chrome/queryCaretRectWin.html b/dom/tests/mochitest/chrome/queryCaretRectWin.html
new file mode 100644
index 0000000000..27708aad58
--- /dev/null
+++ b/dom/tests/mochitest/chrome/queryCaretRectWin.html
@@ -0,0 +1,218 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>nsIDOMWindowUtils::sendQueryContentEvent w/QUERY_CARET_RECT test</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+
+<!--
+ #########################################################
+ # WARNING: this file has Windows line endings. If you
+ # update this file please maintain them. Line endings are
+ # taken into account when calculating query caret rect
+ # values.
+ #########################################################
+-->
+
+<style>
+ #text {
+ position: absolute;
+ left: 0em;
+ top: 0em;
+ font-size: 10pt;
+ font-family: monospace;
+ line-height: 20px;
+ letter-spacing: 0px;
+ margin-top:-1px; /* nix the text area border */
+ overflow: hidden;
+ width:800px;
+ height:400px;
+ }
+ #div-hor {
+ position: absolute;
+ left: 0em;
+ border-top:1px solid lightgray;
+ width: 1000px;
+ pointer-events:none;
+ }
+ #div-ver {
+ position: absolute;
+ top: 0em;
+ border-left:1px solid lightgray;
+ height: 500px;
+ pointer-events:none;
+ }
+</style>
+
+<script type="application/javascript">
+ var SimpleTest = window.opener.SimpleTest;
+
+ function ok() { window.opener.ok.apply(window.opener, arguments); }
+ function done() { window.opener.done.apply(window.opener, arguments); }
+
+ function dumpLn() {
+ for (let idx = 0; idx < arguments.length; idx++)
+ dump(arguments[idx] + " ");
+ dump("\n");
+ }
+
+ // drawn grid is 20x20
+ function drawGrid() {
+ for (var idx = 0; idx < 20; idx++) {
+ var e = document.createElement("div");
+ e.setAttribute("id", "div-hor");
+ e.style.top = (idx*20) + "px";
+ document.getElementById("container").appendChild(e);
+ }
+ for (var idx = 0; idx < 40; idx++) {
+ var e = document.createElement("div");
+ e.setAttribute("id", "div-ver");
+ e.style.left = (idx*20) + "px";
+ document.getElementById("container").appendChild(e);
+ }
+ }
+
+ function getSelection(aElement) {
+ // aElement is know to be a textarea.
+ return aElement.editor.selection;
+ }
+
+ function testCaretPosition(aDomWinUtils, aOffset, aRectDims) {
+ let rect = aDomWinUtils.sendQueryContentEvent(
+ aDomWinUtils.QUERY_CARET_RECT,
+ aOffset, 0, 0, 0,
+ aDomWinUtils.QUERY_CONTENT_FLAG_USE_XP_LINE_BREAK);
+ ok(rect, "rect returned");
+ ok(rect.succeeded, "call succeeded");
+
+ info("left:" + rect.left + " top:" + rect.top);
+
+ ok(rect.left > aRectDims.min.left, "rect.left > " + aRectDims.min.left);
+ ok(rect.left < aRectDims.max.left, "rect.left < " + aRectDims.max.left);
+ ok(rect.top > aRectDims.min.top, "rect.top > " + aRectDims.min.top);
+ ok(rect.top < aRectDims.max.top, "rect.top < " + aRectDims.max.top);
+ }
+
+ function doTest() {
+ let domWinUtils = window.windowUtils;
+
+ let text = document.getElementById("text");
+
+ text.focus();
+
+ let textrect = text.getBoundingClientRect();
+
+ let cp = document.caretPositionFromPoint(10, 395);
+ let input = cp.offsetNode;
+ let offset = cp.offset;
+ input.selectionStart = input.selectionEnd = offset;
+
+ let selection = getSelection(text);
+
+ testCaretPosition(domWinUtils, input.selectionStart, {
+ min: { left: 10, top: 380 },
+ max: { left: 25, top: 390 },
+ });
+
+ testCaretPosition(domWinUtils, input.selectionEnd, {
+ min: { left: 10, top: 380 },
+ max: { left: 25, top: 390 },
+ });
+
+ testCaretPosition(domWinUtils, text.selectionStart, {
+ min: { left: 10, top: 380 },
+ max: { left: 25, top: 390 },
+ });
+
+ testCaretPosition(domWinUtils, text.selectionEnd, {
+ min: { left: 10, top: 380 },
+ max: { left: 25, top: 390 },
+ });
+
+ testCaretPosition(domWinUtils, selection.anchorOffset, {
+ min: { left: 10, top: 380 },
+ max: { left: 25, top: 390 },
+ });
+
+ testCaretPosition(domWinUtils, selection.focusOffset, {
+ min: { left: 10, top: 380 },
+ max: { left: 25, top: 390 },
+ });
+
+ cp = document.caretPositionFromPoint(395, 395);
+ input = cp.offsetNode;
+ offset = cp.offset;
+ input.selectionStart = input.selectionEnd = offset;
+
+ selection = getSelection(text);
+
+ testCaretPosition(domWinUtils, input.selectionStart, {
+ min: { left: 390, top: 380 },
+ max: { left: 400, top: 390 },
+ });
+
+ testCaretPosition(domWinUtils, input.selectionEnd, {
+ min: { left: 390, top: 380 },
+ max: { left: 400, top: 390 },
+ });
+
+ testCaretPosition(domWinUtils, text.selectionStart, {
+ min: { left: 390, top: 380 },
+ max: { left: 400, top: 390 },
+ });
+
+ testCaretPosition(domWinUtils, text.selectionEnd, {
+ min: { left: 390, top: 380 },
+ max: { left: 400, top: 390 },
+ });
+
+ testCaretPosition(domWinUtils, selection.anchorOffset, {
+ min: { left: 390, top: 380 },
+ max: { left: 400, top: 390 },
+ });
+
+ testCaretPosition(domWinUtils, selection.focusOffset, {
+ min: { left: 390, top: 380 },
+ max: { left: 400, top: 390 },
+ });
+
+ done();
+ }
+
+</script>
+
+<body onload="doTest()">
+<textarea id="text" wrap="on">
+Alice was beginning to get very tired of sitting by her sister on the bank,
+and of having nothing to do: once or twice she had peeped into the book
+her sister was reading, but it had no pictures or conversations in it,
+`and what is the use of a book,' thought Alice `without pictures or
+conversation?'
+
+So she was considering in her own mind (as well as she could, for the
+hot day made her feel very sleepy and stupid), whether the pleasure of
+making a daisy-chain would be worth the trouble of getting up and
+picking the daisies, when suddenly a White Rabbit with pink In another
+moment down went Alice after it, never once considering how in the world
+she was to get out again.
+
+The rabbit-hole went straight on like a tunnel for some way, and then
+dipped suddenly down, so suddenly that Alice had not a moment to think
+about stopping herself before she found herself falling down a very deep
+well.
+
+Either the well was very deep, or she fell very slowly, for she had
+plenty of time as she went down to look about her and to wonder what was
+ going to happen next. First, she tried to look down and make out what
+she was coming to, but it was too dark to see anything; then she looked
+at the sides of the well, and noticed that they were filled with
+cupboards and book-shelves; here and there she saw maps and pictures
+hung upon pegs. She took down a jar from one of the shelves as she
+passed; it was labelled `ORANGE MARMALADE', but to her great
+disappointment it was empty: she did not like to drop the jar for fear
+of killing somebody, so managed to put it into one of the cupboards as
+she fell past it.
+</textarea>
+<div id="container"></div>
+</body>
+</html>
diff --git a/dom/tests/mochitest/chrome/selectAtPoint-innerframe.html b/dom/tests/mochitest/chrome/selectAtPoint-innerframe.html
new file mode 100644
index 0000000000..34a8055cce
--- /dev/null
+++ b/dom/tests/mochitest/chrome/selectAtPoint-innerframe.html
@@ -0,0 +1,6 @@
+<html>
+<body style='margin: 0; padding: 0; font-family: monospace;' onload='window.parent.onFrameLoad();'>
+<div id='sel2'>ttestselection2 Lorem ipsum dolor sit amet, at duo debet graeci, vivendum vulputate per ut.</div>
+<br/><br/>
+</body>
+</html>">
diff --git a/dom/tests/mochitest/chrome/selectAtPoint.html b/dom/tests/mochitest/chrome/selectAtPoint.html
new file mode 100644
index 0000000000..6f5f08801b
--- /dev/null
+++ b/dom/tests/mochitest/chrome/selectAtPoint.html
@@ -0,0 +1,278 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>nsIDOMWindowUtils::selectAtPoint test</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+
+<script type="application/javascript">
+ var SimpleTest = window.opener.SimpleTest;
+
+ function ok() { window.opener.ok.apply(window.opener, arguments); }
+ function done() { window.opener.done.apply(window.opener, arguments); }
+
+ function dumpLn() {
+ for (let idx = 0; idx < arguments.length; idx++)
+ dump(arguments[idx] + " ");
+ dump("\n");
+ }
+
+ function getCharacterDims() {
+ let span = document.getElementById("measure");
+ let rect = span.getBoundingClientRect();
+ // Subtract 2 from each dimension because of 1px border on all sides
+ // of the frame.
+ return { width: rect.width - 2, height: rect.height - 2 };
+ }
+
+ function setStart(aDWU, aX, aY, aSelectType)
+ {
+ // Clear any existing selection
+ let selection = document.getSelection();
+ selection.removeAllRanges();
+
+ // Select text
+ let result = aDWU.selectAtPoint(aX, aY, aSelectType);
+ ok(result == true, "selectAtPoint succeeded?");
+ }
+
+ function setEnd(aDWU, aX, aY, aSelectType)
+ {
+ // Select text
+ let result = aDWU.selectAtPoint(aX, aY, aSelectType);
+ ok(result == true, "selectAtPoint succeeded?");
+ }
+
+ function setSingle(aDWU, aX, aY, aSelectType, aSelectTypeStr, aExpectedSelectionText) {
+ // Clear any existing selection
+ let selection = document.getSelection();
+ selection.removeAllRanges();
+
+ // Select text
+ let result = aDWU.selectAtPoint(aX, aY, aSelectType);
+ ok(result == true, "selectAtPoint succeeded?");
+ }
+
+ function checkSelection(aDoc, aSelectTypeStr, aExpectedSelectionText) {
+ // Retrieve text selected
+ let selection = aDoc.getSelection();
+ let text = selection.toString();
+
+ // Test
+ let result = (text == aExpectedSelectionText);
+ ok(result, aSelectTypeStr + " selection text matches?");
+ if (!result) {
+ dumpLn(aSelectTypeStr + " selection text:", "[" + text + "] expected:[" + aExpectedSelectionText + "]" );
+ }
+ }
+
+ function doTest() {
+ let dwu = window.windowUtils;
+
+ let os = Cc["@mozilla.org/xre/app-info;1"]
+ .getService(Ci.nsIXULRuntime).OS;
+ let isLinux = (os == "Linux");
+ let isMac = (os == "Darwin");
+ let isWindows = (os == "WINNT");
+
+ if (!isLinux && !isMac && !isWindows) {
+ done();
+ return;
+ }
+
+ window.scrollTo(0, 0);
+
+ // Trick to get character spacing - get the bounds around a
+ // single character trapped in a div.
+ let charDims = getCharacterDims();
+ // dumpLn("character dims:", charDims.width, charDims.height);
+
+ //
+ // Root frame selection
+ //
+
+ // First div in the main page
+
+ let div = document.getElementById("div1");
+ let rect = div.getBoundingClientRect();
+ rect.x += 1; rect.y += 1; rect.width -= 2; rect.height -= 2; // remove border
+
+ // Centered on the first character in the sentence div
+ let targetPoint = { xPos: rect.left + (charDims.width / 2),
+ yPos: rect.top + (charDims.height / 2) };
+
+ setSingle(dwu, targetPoint.xPos, targetPoint.yPos, Ci.nsIDOMWindowUtils.SELECT_WORDNOSPACE);
+ checkSelection(document, "SELECT_WORDNOSPACE", "ttestselection1");
+ setSingle(dwu, targetPoint.xPos, targetPoint.yPos, Ci.nsIDOMWindowUtils.SELECT_WORD);
+ if (isLinux || isMac) {
+ checkSelection(document, "SELECT_WORD", "ttestselection1");
+ } else if (isWindows) {
+ checkSelection(document, "SELECT_WORD", "ttestselection1 ");
+ }
+ setSingle(dwu, targetPoint.xPos, targetPoint.yPos, Ci.nsIDOMWindowUtils.SELECT_PARAGRAPH);
+ checkSelection(document, "SELECT_PARAGRAPH", "ttestselection1 Lorem ipsum dolor sit amet, at duo debet graeci, vivendum vulputate per ut. Ne labore incorrupte vix. Cu copiosae postulant tincidunt ius, in illud appetere contentiones eos. Ei munere officiis assentior pro, nibh decore ius at.");
+
+ // Within the 10th character "c" in the sentence div
+ targetPoint = { xPos: rect.left + 9.6 * charDims.width,
+ yPos: rect.top + (charDims.height / 2) };
+ // The expectations here are incorrect, because selectAtPoint selects two characters
+ // when it should only get one. https://bugzilla.mozilla.org/show_bug.cgi?id=1696176
+ setSingle(dwu, targetPoint.xPos, targetPoint.yPos, Ci.nsIDOMWindowUtils.SELECT_CHARACTER);
+ checkSelection(document, "SELECT_CHARACTER", "c");
+ setSingle(dwu, targetPoint.xPos, targetPoint.yPos, Ci.nsIDOMWindowUtils.SELECT_CLUSTER);
+ checkSelection(document, "SELECT_CLUSTER", "c");
+
+ // Separate character blocks in a word 'ttestse(l)ection(1)'
+ targetPoint = { xPos: rect.left + 7.6 * charDims.width,
+ yPos: rect.top + (charDims.height / 2) };
+ setStart(dwu, targetPoint.xPos, targetPoint.yPos, Ci.nsIDOMWindowUtils.SELECT_CHARACTER);
+ targetPoint = { xPos: rect.left + 14.6 * charDims.width,
+ yPos: rect.top + (charDims.height / 2) };
+ setEnd(dwu, targetPoint.xPos, targetPoint.yPos, Ci.nsIDOMWindowUtils.SELECT_CHARACTER);
+ checkSelection(document, "split selection", "l1");
+
+ // Trying to select where there's no text, should fail but not throw
+ let result = dwu.selectAtPoint(rect.left - 20, rect.top - 20, Ci.nsIDOMWindowUtils.SELECT_CHARACTER, false);
+ ok(result == false, "couldn't select?");
+
+ // Second div in the main page
+
+ div = document.getElementById("div2");
+ rect = div.getBoundingClientRect();
+ rect.x += 1; rect.y += 1; rect.width -= 2; rect.height -= 2; // remove border
+
+ // Centered on the first line, first character in the paragraph div
+ targetPoint = { xPos: rect.left + (charDims.width / 2),
+ yPos: rect.top + (charDims.height / 2) };
+ setSingle(dwu, targetPoint.xPos + 50, targetPoint.yPos, Ci.nsIDOMWindowUtils.SELECT_PARAGRAPH);
+ checkSelection(document, "SELECT_PARAGRAPH", "Lorem ipsum dolor sit amet, at duo debet graeci, vivendum vulputate per ut. Ne labore incorrupte vix. Cu copiosae postulant tincidunt ius, in illud appetere contentiones eos.");
+
+ //
+ // Inner IFRAME selection tests
+ //
+
+ let frame = document.getElementById("frame1");
+ let dwuFrame = frame.contentDocument
+ .defaultView
+ .windowUtils;
+
+ frame.contentWindow.scrollTo(0, 0);
+
+ rect = frame.getBoundingClientRect();
+ rect.x += 1; rect.y += 1; rect.width -= 2; rect.height -= 2; // remove border
+
+ targetPoint = { xPos: charDims.width / 2,
+ yPos: charDims.height / 2 };
+ setSingle(dwuFrame, targetPoint.xPos, targetPoint.yPos, Ci.nsIDOMWindowUtils.SELECT_WORDNOSPACE);
+ checkSelection(frame.contentWindow.document, "SELECT_WORDNOSPACE", "ttestselection2");
+ setSingle(dwuFrame, targetPoint.xPos, targetPoint.yPos, Ci.nsIDOMWindowUtils.SELECT_WORD);
+ if (isLinux || isMac) {
+ checkSelection(frame.contentWindow.document, "SELECT_WORD", "ttestselection2");
+ } else if (isWindows) {
+ checkSelection(frame.contentWindow.document, "SELECT_WORD", "ttestselection2 ");
+ }
+ setSingle(dwuFrame, targetPoint.xPos, targetPoint.yPos, Ci.nsIDOMWindowUtils.SELECT_PARAGRAPH);
+ checkSelection(frame.contentWindow.document, "SELECT_PARAGRAPH", "ttestselection2 Lorem ipsum dolor sit amet, at duo debet graeci, vivendum vulputate per ut.");
+
+ // Outside the frame should throw. This is a failure in coordinate setup of
+ // nsDOMWindowUtils::SelectAtPoint.
+ let thr = false;
+ try {
+ dwuFrame.selectAtPoint(rect.right + 50, rect.top, Ci.nsIDOMWindowUtils.SELECT_WORD, false);
+ } catch (ex) { thr = true; }
+ ok(thr == true, "selectAtPoint expected throw?");
+
+ done();
+ }
+
+ let frameLoad = false;
+ let pageLoad = false;
+ let painted = false;
+ function testReady() {
+ if (frameLoad && pageLoad && painted)
+ doTest();
+ }
+
+ function onFrameLoad() {
+ // Exit the onload handler before trying the test, because we need
+ // to ensure that paint unsupression has happened.
+ setTimeout(function() {
+ frameLoad = true;
+ testReady();
+ }, 0);
+ }
+
+ function onPageLoad() {
+ // Exit the onload handler before trying the test, because we need
+ // to ensure that paint unsupression has happened
+ // XXXroc why do we need to separately test for the loading of the frame
+ // and a paint? That should not be necessary for this test.
+ setTimeout(function() {
+ pageLoad = true;
+ testReady();
+ }, 0);
+ }
+
+ function onPaint() {
+ window.removeEventListener("MozAfterPaint", onPaint);
+ painted = true;
+ testReady();
+ }
+
+ window.addEventListener("MozAfterPaint", onPaint);
+</script>
+
+<style type="text/css">
+
+body {
+ font-family: monospace;
+ margin-left: 40px;
+ margin-top: 40px;
+ padding: 0;
+}
+
+#div1 {
+ border: 1px solid red;
+ width: 400px;
+ height: 100px;
+}
+
+#frame1 {
+ display: block;
+ height: 100px;
+ width: 300px;
+ border: 1px solid blue;
+ padding: 0;
+ margin: 0;
+}
+
+#div2 {
+ border: 1px solid green;
+}
+
+#measure {
+ padding: 0px;
+ margin: 0px;
+ border: 1px solid red;
+}
+
+</style>
+</head>
+<body id="body" onload="onPageLoad();">
+
+<div id="div1">ttestselection1 Lorem ipsum dolor sit amet, at duo debet graeci, vivendum vulputate per ut. Ne labore incorrupte vix. Cu copiosae postulant tincidunt ius, in illud appetere contentiones eos. Ei munere officiis assentior pro, nibh decore ius at.</div>
+
+<br />
+
+<iframe id="frame1" src="selectAtPoint-innerframe.html"></iframe>
+
+<br/>
+
+<div id="div2">Lorem ipsum dolor sit amet, at duo debet graeci, vivendum vulputate per ut. Ne labore incorrupte vix. Cu copiosae postulant tincidunt ius, in illud appetere contentiones eos.</div>
+
+<br />
+
+<span id="measure">t</span>
+
+</body>
+</html>
diff --git a/dom/tests/mochitest/chrome/sizemode_attribute.xhtml b/dom/tests/mochitest/chrome/sizemode_attribute.xhtml
new file mode 100644
index 0000000000..3dbde68064
--- /dev/null
+++ b/dom/tests/mochitest/chrome/sizemode_attribute.xhtml
@@ -0,0 +1,87 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+<!--
+ Test for fullscreen sizemode in chrome
+ -->
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ persist="sizemode"
+ sizemode="normal"
+ onload="nextStep()">
+
+<script type="text/javascript">
+let tests = [
+ function test1() {
+ checkAndContinue("normal");
+ },
+
+ function test2() {
+ listen("fullscreen", () => checkAndContinue("fullscreen"));
+ window.fullScreen = true;
+ },
+
+ function test3() {
+ listen("fullscreen", () => checkAndContinue("normal"));
+ window.fullScreen = false;
+ },
+
+ function test4() {
+ listen("resize", () => checkAndContinue("maximized"));
+ window.maximize();
+ },
+
+ function test5() {
+ listen("fullscreen", () => checkAndContinue("fullscreen"));
+ window.fullScreen = true;
+ },
+
+ function test6() {
+ listen("fullscreen", () => checkAndContinue("maximized"));
+ window.fullScreen = false;
+ },
+
+ function test7() {
+ listen("resize", () => checkAndContinue("normal"));
+ window.restore();
+ },
+
+ function test8() {
+ window.arguments[0].done();
+ }
+];
+
+function nextStep() {
+ tests.shift()();
+}
+
+function listen(event, fn) {
+ window.addEventListener(event, function listener() {
+ window.removeEventListener(event, listener, false);
+ fn();
+ }, false);
+}
+
+function checkAndContinue(sizemode) {
+
+ let windowStates = {
+ "fullscreen": window.STATE_FULLSCREEN,
+ "normal": window.STATE_NORMAL,
+ "maximized": window.STATE_MAXIMIZED
+ };
+
+ setTimeout(function() {
+ is(window.document.documentElement.getAttribute("sizemode"), sizemode, "sizemode attribute should match actual window state");
+ is(window.fullScreen, sizemode == "fullscreen", "window.fullScreen should match actual window state");
+ is(window.windowState, windowStates[sizemode], "window.sizeMode should match actual window state");
+ nextStep();
+ }, 0);
+}
+
+let is = window.arguments[0].is;
+
+</script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+
+</body>
+</window>
diff --git a/dom/tests/mochitest/chrome/test_DOMWindowCreated.xhtml b/dom/tests/mochitest/chrome/test_DOMWindowCreated.xhtml
new file mode 100644
index 0000000000..4ad119b7f5
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_DOMWindowCreated.xhtml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+<!--
+ Test for Persistent Storage in chrome
+ -->
+<window id="sample-window" width="400" height="400"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript"
+ src="chrome://mochikit/content/chrome-harness.js"></script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<p id="display">
+</p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script>
+SimpleTest.waitForExplicitFinish();
+var root = getRootDirectory(window.location.href);
+window.openDialog(root + "DOMWindowCreated_chrome.xhtml", "_blank", "chrome,width=600,height=550,noopener", window);
+</script>
+
+</window>
diff --git a/dom/tests/mochitest/chrome/test_DOM_element_instanceof.xhtml b/dom/tests/mochitest/chrome/test_DOM_element_instanceof.xhtml
new file mode 100644
index 0000000000..9efdaab158
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_DOM_element_instanceof.xhtml
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=824917
+-->
+<window title="Mozilla Bug 824917"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=824917"
+ target="_blank">Mozilla Bug 824917</a>
+ </body>
+
+ <iframe type="content"></iframe>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ /** Test for Bug 824917 **/
+
+ function runTests() {
+ window.openDialog("file_DOM_element_instanceof.xhtml", "_blank", "chrome,width=600,height=550,noopener", window);
+ }
+
+ addLoadEvent(runTests);
+
+ SimpleTest.waitForExplicitFinish();
+
+ ]]>
+ </script>
+</window>
diff --git a/dom/tests/mochitest/chrome/test_activation.xhtml b/dom/tests/mochitest/chrome/test_activation.xhtml
new file mode 100644
index 0000000000..2bc5a7d98d
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_activation.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+<?xml-stylesheet href="data:text/css,
+
+%23box {
+ background: blue;
+}
+
+%23box:-moz-window-inactive {
+ background: cyan;
+}
+
+" type="text/css"?>
+<!--
+ Test for the :-moz-window-inactive pseudoclass
+ -->
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ sizemode="fullscreen">
+
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<box id="box" height="100"/>
+
+<script>
+SimpleTest.waitForExplicitFinish();
+
+newwindow = window.browsingContext.topChromeWindow.openDialog("window_activation.xhtml", "_blank","chrome,width=300,height=200", window);
+
+function complete()
+{
+ newwindow.close();
+ SimpleTest.finish();
+}
+
+</script>
+
+
+<body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
+
+</window>
diff --git a/dom/tests/mochitest/chrome/test_bug1224790-1.xhtml b/dom/tests/mochitest/chrome/test_bug1224790-1.xhtml
new file mode 100644
index 0000000000..9f2c345f5c
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_bug1224790-1.xhtml
@@ -0,0 +1,69 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1224790
+-->
+<window title="Mozilla Bug 1224790"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+ <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+
+ /** Test for Bug 1224790 **/
+ /*
+ * 1. Opens modal dialog
+ * 2. Open non-modal window from modal dialog
+ * 3. Close non-modal window
+ * 4. Close modal dialog
+ * 5. Click button to ensure mouse event is working
+ */
+
+ function startTest() {
+ window.openDialog('file_bug1224790-1_modal.xhtml', '', 'modal,noopener', window);
+ }
+
+ function modalClosed() {
+ SimpleTest.waitForFocus(gotFocus);
+ }
+
+ var timer = null;
+ function gotFocus() {
+ var button = document.getElementById('button');
+ synthesizeMouseAtCenter(button, { type: 'mousemove' }, window);
+ function click() {
+ // The bug is not reproducible with synthesizeMouseAtCenter.
+ synthesizeNativeMouseEvent({ type: "click", target: button, atCenter: true });
+ }
+ click();
+ // On debug build, it's possible that the click event handler is not
+ // triggered by the first click in case the click is dispatched too early
+ // before Firefox gets ready for input.
+ // Click the button again after 1 sec when we don't get click event.
+ timer = setTimeout(click, 1000);
+ }
+
+ function onClick() {
+ if (timer) {
+ // Avoid clicking unrelated thing.
+ clearTimeout(timer);
+ }
+ ok(true, "Click event should be fired");
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ SimpleTest.waitForFocus(startTest);
+ ]]>
+ </script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1224790"
+ target="_blank">Mozilla Bug 1224790</a>
+ </body>
+ <button id="button" label="button" oncommand="onClick()" />
+</window>
diff --git a/dom/tests/mochitest/chrome/test_bug1224790-2.xhtml b/dom/tests/mochitest/chrome/test_bug1224790-2.xhtml
new file mode 100644
index 0000000000..7b4983fd37
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_bug1224790-2.xhtml
@@ -0,0 +1,70 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1224790
+-->
+<window title="Mozilla Bug 1224790"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+ <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+
+ /** Test for Bug 1224790 **/
+ /*
+ * 1. Opens modal dialog
+ * 2. Open non-modal window from modal dialog
+ * 3. Close modal dialog
+ * 4. Wait for a while for destructor for modal dialog
+ * 5. Close non-modal window
+ * 6. Click button to ensure mouse event is working
+ */
+
+ function startTest() {
+ window.openDialog('file_bug1224790-2_modal.xhtml', '', 'modal,noopener', window);
+ }
+
+ function nonModalClosed() {
+ SimpleTest.waitForFocus(gotFocus);
+ }
+
+ var timer = null;
+ function gotFocus() {
+ var button = document.getElementById('button');
+ synthesizeMouseAtCenter(button, { type: 'mousemove' }, window);
+ function click() {
+ // The bug is not reproducible with synthesizeMouseAtCenter.
+ synthesizeNativeMouseEvent({ type: "click", target: button, atCenter: true });
+ }
+ click();
+ // On debug build, it's possible that the click event handler is not
+ // triggered by the first click in case the click is dispatched too early
+ // before Firefox gets ready for input.
+ // Click the button again after 1 sec when we don't get click event.
+ timer = setTimeout(click, 1000);
+ }
+
+ function onClick() {
+ if (timer) {
+ // Avoid clicking unrelated thing.
+ clearTimeout(timer);
+ }
+ ok(true, "Click event should be fired");
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ SimpleTest.waitForFocus(startTest);
+ ]]>
+ </script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1224790"
+ target="_blank">Mozilla Bug 1224790</a>
+ </body>
+ <button id="button" label="button" oncommand="onClick()" />
+</window>
diff --git a/dom/tests/mochitest/chrome/test_bug800817.xhtml b/dom/tests/mochitest/chrome/test_bug800817.xhtml
new file mode 100644
index 0000000000..fefaf2c155
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_bug800817.xhtml
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=800817
+-->
+<window title="Mozilla Bug 800817" onload="runTests()"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+ <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=800817"
+ target="_blank">Mozilla Bug 800817</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ /** Test for Bug 800817 **/
+
+ var testMozBrowser = false;
+ function runTests() {
+ // Run a first round of tests for non-mozbrowser iframes.
+ window.openDialog("file_bug800817.xhtml", "_blank", "chrome,width=600,height=550,noopener", window);
+ }
+
+ function finishedTests() {
+ if (!testMozBrowser) {
+ testMozBrowser = true;
+ // Run a second round of tests for mozbrowser iframes.
+ window.openDialog("file_bug800817.xhtml", "_blank", "chrome,width=600,height=550,noopener", window);
+ } else {
+ SimpleTest.finish();
+ }
+ }
+
+ SimpleTest.waitForExplicitFinish();
+
+ ]]>
+ </script>
+</window>
diff --git a/dom/tests/mochitest/chrome/test_bug830858.xhtml b/dom/tests/mochitest/chrome/test_bug830858.xhtml
new file mode 100644
index 0000000000..9afc51bdef
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_bug830858.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=830858
+-->
+<window title="Mozilla Bug 830858"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="runTests()">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+
+ /** Test for Bug 830858 **/
+
+ function runTests() {
+ window.openDialog("file_bug830858.xhtml", "_blank", "chrome,width=600,height=550,noopener", window);
+ }
+
+ function finishedTests() {
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+
+ ]]>
+ </script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=830858"
+ target="_blank">Mozilla Bug 830858</a>
+ </body>
+</window>
diff --git a/dom/tests/mochitest/chrome/test_callback_wrapping.xhtml b/dom/tests/mochitest/chrome/test_callback_wrapping.xhtml
new file mode 100644
index 0000000000..28b7b89b43
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_callback_wrapping.xhtml
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=742222
+-->
+<window title="Mozilla Bug 742222"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=742222"
+ target="_blank">Mozilla Bug 742222</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ SimpleTest.waitForExplicitFinish();
+ window.open("window_callback_wrapping.xhtml");
+ </script>
+</window>
diff --git a/dom/tests/mochitest/chrome/test_clipboard_events_chrome.html b/dom/tests/mochitest/chrome/test_clipboard_events_chrome.html
new file mode 100644
index 0000000000..0c67d5e280
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_clipboard_events_chrome.html
@@ -0,0 +1,60 @@
+<html>
+<body onload="runTest()">
+
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+
+<script>
+// This test checks that the dom.event.clipboardevents.enabled does not apply to chrome shells.
+
+SimpleTest.waitForExplicitFinish();
+function runTest()
+{
+ SpecialPowers.pushPrefEnv({"set": [['dom.event.clipboardevents.enabled', false]]}, function() {
+ window.openDialog("file_clipboard_events_chrome.html", "_blank", "chrome,width=200,height=200,noopener", window);
+ });
+}
+
+var event_fired = false;
+
+function doChecks(win)
+{
+ var windowFocused = function() {
+ var textbox = win.document.getElementById("i");
+ textbox.value = "Sample Text";
+
+ textbox.oncut = function() { event_fired = true; };
+ textbox.oncopy = function() { event_fired = true; };
+ textbox.onpaste = function() { event_fired = true; };
+
+ textbox.select();
+ textbox.focus();
+
+ textbox.setSelectionRange(1, 4);
+ synthesizeKey("x", {accelKey: 1}, win);
+ is(textbox.value, "Sle Text", "cut changed text when preference is disabled");
+ ok(event_fired, "cut event fired when preference is disabled")
+
+ event_fired = false;
+ textbox.setSelectionRange(4, 6);
+ synthesizeKey("c", {accelKey: 1}, win);
+ is(textbox.value, "Sle Text", "cut changed text when preference is disabled");
+ ok(event_fired, "copy event fired when preference is disabled")
+
+ event_fired = false;
+ textbox.setSelectionRange(1, 4);
+ synthesizeKey("v", {accelKey: 1}, win);
+ is(textbox.value, "STeText", "paste changed text when preference is disabled");
+ ok(event_fired, "paste event fired when preference is disabled")
+
+ win.close();
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForFocus(windowFocused, win);
+}
+
+</script>
+
+<p id="display"></p>
+</body></html>
diff --git a/dom/tests/mochitest/chrome/test_clonewrapper.xhtml b/dom/tests/mochitest/chrome/test_clonewrapper.xhtml
new file mode 100644
index 0000000000..41d7661fb1
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_clonewrapper.xhtml
@@ -0,0 +1,117 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=667388
+-->
+<window title="Mozilla Bug 667388"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+
+ // Setup.
+ SimpleTest.waitForExplicitFinish();
+ window.testObject = { myNumber: 42,
+ myDomain: window.location.domain };
+
+
+ // Wait for both frames to load before proceeding.
+ var framesLoaded = [null, false, false, false];
+ function onFrameLoaded(id) {
+
+ // Mark this frame as loaded.
+ framesLoaded[id] = true;
+
+ // Allow it to call various helpers.
+ window.frames[id].wrappedJSObject.is = is;
+ window.frames[id].wrappedJSObject.ok = ok;
+ window.frames[id].wrappedJSObject.info = info;
+
+ // If all the frames are loaded, start the test.
+ if (framesLoaded[1] && framesLoaded[2] && framesLoaded[3])
+ startTest();
+ }
+
+ function reject(e) {
+ ok(false, "Rejected Promise: " + e);
+ SimpleTest.finish();
+ }
+
+ function startTest() {
+
+ runChromeContentTest(window.frames[1]).then(
+ runContentContentTest.bind(null, window.frames[1], window.frames[2],
+ true, "Should be able to clone same-origin"), reject).then(
+ runContentContentTest.bind(null, window.frames[2], window.frames[3],
+ false, "Should not be able to clone cross-origin"), reject).then(function() {
+ // Colaborate with document.domain, then try again.
+ frames[2].document.domain = 'example.org';
+ frames[3].document.domain = 'example.org';
+ return runContentContentTest(window.frames[2], window.frames[3],
+ false, "Should be able to clone cross-origin with document.domain, but can't because of cached CCWs")
+ }, reject).then(SimpleTest.finish.bind(SimpleTest), reject);
+ }
+
+ // Tests cloning between chrome and content.
+ function runChromeContentTest(contentWin) {
+
+ // We should be able to clone a content object.
+ tryToClone(contentWin.wrappedJSObject.testObject,
+ true,
+ "Chrome should be able to clone content object");
+
+ return Promise.resolve();
+ }
+
+ // Test cloning between content and content.
+ //
+ // Note - the way we do this is kind of sketchy. Because we're grabbing the
+ // test object from win1 by waiving Xray (via .wrappedJSObject), the object
+ // we're passing from win1 to win2 is actually the waived object (which has
+ // a distinct identity in the compartment of win2). So this means that we're
+ // actually giving win2 Xray waivers to win1! This doesn't affect things as
+ // long as the security wrappers check documentDomainMakesSameOrigin directly
+ // for the puncture case rather than checking IsTransparent(), but it still
+ // gives rise to a situation that wouldn't really happen in practice.
+ function runContentContentTest(win1, win2, shouldSucceed, msg) {
+
+ var p = win1.wrappedJSObject.tryToClone(win2.wrappedJSObject.testObject,
+ shouldSucceed, msg);
+ if (!shouldSucceed)
+ return;
+ return new Promise(function(resolve) {
+ p.then(function(cloneResult) {
+ is(JSON.stringify(Cu.waiveXrays(cloneResult)),
+ JSON.stringify(win2.wrappedJSObject.testObject),
+ "Clone should create an identical object");
+ resolve();
+ });
+ });
+ }
+
+ function tryToClone(obj, shouldSucceed, message) {
+ var success = false;
+ var sink = window.frames[0];
+ try { sink.postMessage(obj, '*'); success = true; }
+ catch (e) { message = message + ' (threw: ' + e.message + ')'; }
+ is(success, shouldSucceed, message);
+ }
+
+ ]]>
+ </script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=667388"
+ target="_blank">Mozilla Bug 667388</a>
+ <iframe id="sink" />
+ <!-- The first two are same-origin, the third is not. -->
+ <iframe id="frame1" onload="onFrameLoaded(1);" src="http://test1.example.org/tests/dom/tests/mochitest/general/file_clonewrapper.html" />
+ <iframe id="frame2" onload="onFrameLoaded(2);" src="http://test1.example.org/tests/dom/tests/mochitest/general/file_clonewrapper.html" />
+ <iframe id="frame3" onload="onFrameLoaded(3);" src="http://test2.example.org/tests/dom/tests/mochitest/general/file_clonewrapper.html" />
+ </body>
+
+</window>
diff --git a/dom/tests/mochitest/chrome/test_cyclecollector.xhtml b/dom/tests/mochitest/chrome/test_cyclecollector.xhtml
new file mode 100644
index 0000000000..89302f37cc
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_cyclecollector.xhtml
@@ -0,0 +1,54 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=
+-->
+<window title="Mozilla Bug "
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id="
+ target="_blank">Mozilla Bug </a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ /** Test for Bug **/
+ var obs = Cc["@mozilla.org/observer-service;1"]
+ .getService(Ci.nsIObserverService);
+ var didCall = false;
+ var observer = {
+ QueryInterface: function QueryInterface(aIID) {
+ if (aIID.equals(Ci.nsIObserver) ||
+ aIID.equals(Ci.nsISupports))
+ return this;
+ throw Components.Exception("", Cr.NS_NOINTERFACE);
+ },
+ observe: function(subject, topic, data) {
+ obs.removeObserver(observer, "cycle-collector-begin");
+ observer = null;
+ didCall = true;
+ }
+ };
+
+ // Start an incremental GC, to make sure that calling ccSlice
+ // when an IGC is running finishes the GC.
+ SpecialPowers.Cu.getJSTestingFunctions().gcslice(1);
+
+ // Make sure that we call the observer even if we're in the middle
+ // of an ICC when we add the observer. See bug 981033.
+ SpecialPowers.finishCC();
+ SpecialPowers.ccSlice(1);
+
+ obs.addObserver(observer, "cycle-collector-begin");
+
+ SpecialPowers.DOMWindowUtils.cycleCollect();
+
+ ok(didCall, "Observer should have been called!");
+ ]]>
+ </script>
+</window>
diff --git a/dom/tests/mochitest/chrome/test_docshell_swap.xhtml b/dom/tests/mochitest/chrome/test_docshell_swap.xhtml
new file mode 100644
index 0000000000..120f179cd2
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_docshell_swap.xhtml
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<window title="Docshell swap test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+
+ SimpleTest.waitForExplicitFinish();
+
+ // Create two identical windows, each with a <browser> element.
+ let win1 = window.browsingContext.topChromeWindow.openDialog("window_docshell_swap.xhtml", "_blank","chrome,width=300,height=200");
+ let win2 = window.browsingContext.topChromeWindow.openDialog("window_docshell_swap.xhtml", "_blank","chrome,width=300,height=200");
+
+ let loadCount = 0;
+ function loadHandler() {
+ loadCount++;
+ if (loadCount < 2)
+ return;
+
+ let browser1 = win1.document.getElementById("browser");
+ let browser2 = win2.document.getElementById("browser");
+
+ let pongCount = 0;
+
+ function gotPong(target_ok) {
+ pongCount++;
+ ok(target_ok, "message went to correct target");
+ if (pongCount == 1) {
+ win1.close();
+ win2.close();
+ SimpleTest.finish();
+ }
+ }
+
+ let mm1 = browser1.frameLoader.messageManager;
+ let mm2 = browser2.frameLoader.messageManager;
+
+ // Swap docshells. Everything should be identical to before, since there was nothing to
+ // distinguish these docshells.
+ browser1.swapFrameLoaders(browser2);
+
+ // mm1 shouldn't change here, but we update it in case it does due to a bug.
+ mm1 = browser1.frameLoader.messageManager;
+
+ // Load ping-pong code into first window.
+ mm1.loadFrameScript("data:,addMessageListener('ping', () => sendAsyncMessage('pong'));", false);
+
+ // A pong message received in win1 means success.
+ win1.messageManager.addMessageListener("pong", () => { gotPong(true); });
+
+ // A pong message received in win2 means failure!
+ win2.messageManager.addMessageListener("pong", () => { gotPong(false); });
+
+ // Send the ping to win1.
+ mm1.sendAsyncMessage("ping");
+ }
+
+ win1.addEventListener("load", loadHandler, false);
+ win2.addEventListener("load", loadHandler, false);
+ ]]>
+ </script>
+</window>
diff --git a/dom/tests/mochitest/chrome/test_elements_proto.xhtml b/dom/tests/mochitest/chrome/test_elements_proto.xhtml
new file mode 100644
index 0000000000..c95bda7beb
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_elements_proto.xhtml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+
+<window title="Mozilla Bug 861493"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ </body>
+
+ <script type="application/javascript">
+ <![CDATA[
+ const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+
+ SimpleTest.waitForExplicitFinish();
+
+ addLoadEvent(() => {
+ ok(XULTextElement.isInstance(document.createElementNS(XUL_NS, "label")),
+ `<label> should be of XULTextElement type`);
+
+ ok(XULTextElement.isInstance(document.createElementNS(XUL_NS, "description")),
+ `<description> should be of XULTextElement type`);
+
+ SimpleTest.finish();
+ });
+ ]]>
+ </script>
+</window>
diff --git a/dom/tests/mochitest/chrome/test_focus.xhtml b/dom/tests/mochitest/chrome/test_focus.xhtml
new file mode 100644
index 0000000000..3e30104af4
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_focus.xhtml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+
+<window title="Focus Tests"
+ onload="setTimeout(runTest, 0);"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+<script>
+if (navigator.platform.startsWith("Win")) {
+ SimpleTest.expectAssertions(0, 1);
+}
+
+SimpleTest.waitForExplicitFinish();
+async function runTest()
+{
+ window.openDialog("window_focus.xhtml", "_blank", "chrome,width=600,height=550,noopener", window);
+}
+</script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<p id="display">
+</p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+</body>
+
+</window>
diff --git a/dom/tests/mochitest/chrome/test_focus_dialog.xhtml b/dom/tests/mochitest/chrome/test_focus_dialog.xhtml
new file mode 100644
index 0000000000..0d9d886e26
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_focus_dialog.xhtml
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+
+<window title="Focus Tests"
+ onload="setTimeout(runTest, 0);"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+<script>
+if (navigator.platform.startsWith("Win")) {
+ SimpleTest.expectAssertions(0, 1);
+}
+
+SimpleTest.waitForExplicitFinish();
+async function runTest() {
+ // Enable full tab focus model on mac.
+ await SpecialPowers.pushPrefEnv({ set: [["accessibility.tabfocus", 7]] });
+ window.openDialog("focus_dialog.xhtml", "_blank", "chrome,modal,noopener", window);
+}
+</script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<p id="display">
+</p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+</body>
+
+</window>
diff --git a/dom/tests/mochitest/chrome/test_focus_docnav.xhtml b/dom/tests/mochitest/chrome/test_focus_docnav.xhtml
new file mode 100644
index 0000000000..7067da3d1d
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_focus_docnav.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+
+<window onload="runTest();"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+<script>
+SimpleTest.waitForExplicitFinish();
+function runTest()
+{
+ window.openDialog("window_focus_docnav.xhtml", "_blank", "chrome,width=600,height=550,noopener", window);
+}
+</script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<p id="display">
+</p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+</body>
+
+</window>
diff --git a/dom/tests/mochitest/chrome/test_focused_link_scroll.xhtml b/dom/tests/mochitest/chrome/test_focused_link_scroll.xhtml
new file mode 100644
index 0000000000..717da1b51b
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_focused_link_scroll.xhtml
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+
+<window title="Focus Scroll Tests"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+ <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<div id="div" style="width:500px;height:48px;overflow:auto;font-size:16px;line-height:16px;">
+aaaaaaaaa<br/>bbbbbbbb<br/>
+<a href="about:blank;" id="a">ccccccccc<br/>ddddddddd</a>
+</div>
+<p id="display">
+</p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script>
+
+SimpleTest.waitForExplicitFinish();
+
+function runTest()
+{
+ var fm = Components.classes["@mozilla.org/focus-manager;1"].
+ getService(Components.interfaces.nsIFocusManager);
+ var div = document.getElementById('div');
+ var a = document.getElementById('a');
+ synthesizeMouse(a, 4, 4, { type: "mousedown" }, window);
+ is(fm.focusedElement, a,
+ "The anchor element isn't set focus by the mouse down event");
+ is(div.scrollTop, 0,
+ "The div element was scrolled by the mouse down event");
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForFocus(runTest);
+
+</script>
+
+</window>
diff --git a/dom/tests/mochitest/chrome/test_geolocation.xhtml b/dom/tests/mochitest/chrome/test_geolocation.xhtml
new file mode 100644
index 0000000000..482b36ea20
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_geolocation.xhtml
@@ -0,0 +1,54 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+<!--
+ Test for Geolocation in chrome
+ -->
+<window
+ id="sample-window"
+ width="400"
+ height="400"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+>
+ <script
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"
+ ></script>
+
+ <script>
+ SimpleTest.waitForExplicitFinish();
+ async function test() {
+ /** @type {Geolocation} */
+ const geolocation = Cc["@mozilla.org/geolocation;1"].getService(
+ Ci.nsISupports
+ );
+ try {
+ // Watch position
+ let watchId;
+ let position = await new Promise((resolve, reject) => {
+ watchId = geolocation.watchPosition(resolve, reject, { timeout: 0 });
+ });
+ ok(position, "watchPosition() callable from chrome");
+ geolocation.clearWatch(watchId);
+
+ // Get position
+ position = await new Promise((resolve, reject) =>
+ geolocation.getCurrentPosition(resolve, reject)
+ );
+ ok(position, "getCurrentPosition() callable from chrome");
+ } catch (err) {
+ ok(
+ false,
+ "error occurred trying to get geolocation from chrome: " + err.message
+ );
+ } finally {
+ SimpleTest.finish();
+ }
+ }
+ </script>
+
+ <body
+ xmlns="http://www.w3.org/1999/xhtml"
+ style="height: 300px; overflow: auto;"
+ onload="test()"
+ />
+</window>
diff --git a/dom/tests/mochitest/chrome/test_getTransformTo.html b/dom/tests/mochitest/chrome/test_getTransformTo.html
new file mode 100644
index 0000000000..1fc4e4749b
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_getTransformTo.html
@@ -0,0 +1,117 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test Element::getTransformToViewport</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+<style>
+body {
+ margin: 0px;
+}
+.box {
+ background-color: red;
+ height: 20px;
+ width: 80px;
+}
+.a {
+ margin: 10px;
+}
+.b {
+ margin: 20px;
+}
+.c {
+ transform: translate(11px, -11px);
+}
+.d {
+ transform: skewx(-45deg);
+}
+
+</style>
+<script>
+'use strict';
+
+SimpleTest.waitForExplicitFinish();
+
+function testTransformToParent() {
+ let expectedData = [
+ ["boxA", "1,0,0,0,0,1,0,0,0,0,1,0,10,0,0,1"],
+ ["boxB", "1,0,0,0,0,1,0,0,0,0,1,0,20,0,0,1"],
+ ["boxC", "1,0,0,0,0,1,0,0,0,0,1,0,11,-11,0,1"],
+ ["boxD", "1,0,0,0,-1,1,0,0,0,0,1,0,10,0,0,1"],
+ ];
+
+ // Test transform to parent.
+ for (let i = 0; i < expectedData.length; ++i) {
+ let expected = expectedData[i];
+ let element = document.getElementById(expected[0]);
+
+ let transform = element.getTransformToParent();
+ let transformFloats = transform.toFloat32Array();
+ let transformString = transformFloats.toString();
+ is(transformString, expected[1], "Element " + expected[0] + " has expected transform to parent.");
+ }
+}
+
+function testTransformToAncestorAndViewport() {
+ let expectedData = [
+ ["boxA", "1,0,0,0,0,1,0,0,0,0,1,0,10,10,0,1"],
+ ["boxB", "1,0,0,0,0,1,0,0,0,0,1,0,20,50,0,1"],
+ ["boxC", "1,0,0,0,0,1,0,0,0,0,1,0,11,79,0,1"],
+ ];
+
+ // Test transform to document (an actual ancestor unchanged by embedding within the mochitest framework).
+ for (let i = 0; i < expectedData.length; ++i) {
+ let expected = expectedData[i];
+ let element = document.getElementById(expected[0]);
+
+ let transform = element.getTransformToAncestor(document.documentElement);
+ let transformFloats = transform.toFloat32Array();
+ let transformString = transformFloats.toString();
+ is(transformString, expected[1], "Element " + expected[0] + " has expected transform to ancestor.");
+ }
+
+ // Test transform to a non-ancestor is equivalent to transform to viewport.
+ let nonAncestorElement = document.getElementById("nonAncestor");
+ for (let i = 0; i < expectedData.length; ++i) {
+ let expected = expectedData[i];
+ let element = document.getElementById(expected[0]);
+
+ let transform = element.getTransformToAncestor(nonAncestorElement);
+ let transformFloats = transform.toFloat32Array();
+ let transformString = transformFloats.toString();
+
+ let transformToViewport = element.getTransformToViewport();
+ let transformToViewportFloats = transformToViewport.toFloat32Array();
+ let transformToViewportString = transformToViewportFloats.toString();
+ is(transformString, transformToViewportString, "Element " + expected[0] + " transform to non-ancestor is equivalent to transform to viewport.");
+ }
+}
+
+function runTests() {
+ testTransformToParent();
+ testTransformToAncestorAndViewport();
+
+ SimpleTest.finish();
+}
+</script>
+</head>
+<body onLoad="runTests();">
+
+<div id="boxAParent">
+ <div id="boxA" class="box a">boxA</div>
+</div>
+<div id="boxBParent">
+ <div id="boxB" class="box b">boxB</div>
+</div>
+<div id="boxCParent">
+ <div id="boxC" class="box c">boxC</div>
+</div>
+<div id="boxDParent">
+ <div id="boxD" class="box d">boxD</div>
+</div>
+
+<div id="nonAncestor">This div is not an ancestor of any of the boxes.</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/dom/tests/mochitest/chrome/test_indexedSetter.html b/dom/tests/mochitest/chrome/test_indexedSetter.html
new file mode 100644
index 0000000000..16bff02030
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_indexedSetter.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=715156
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 715156</title>
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+ <script type="application/javascript">
+
+ /** Test for Bug 715156 **/
+
+ function runTests() {
+ var doc = document.getElementById("testFrame").contentDocument;
+ var options = doc.createElement("select").options;
+ ok(Cu.isXrayWrapper(options), "should be an Xray wrapper");
+ var option = doc.createElement("option");
+ options[4] = option;
+ is(options.length, 5, "setting an indexed property through an Xray wrapper should work")
+ is(options[4], option, "setting an indexed property through an Xray wrapper should work")
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(runTests);
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=715156">Mozilla Bug 715156</a>
+<p id="display"></p>
+<iframe id="testFrame"></iframe>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/tests/mochitest/chrome/test_intlUtils_getDisplayNames.html b/dom/tests/mochitest/chrome/test_intlUtils_getDisplayNames.html
new file mode 100644
index 0000000000..2f4c6e41d1
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_intlUtils_getDisplayNames.html
@@ -0,0 +1,351 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1341994
+-->
+<head>
+ <title>Test for Bug 1341994 </title>
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1341994 ">Mozilla Bug 1341994</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<script>
+
+var testData = [
+ {
+ locales: ["en-US"],
+ options: {
+ type: "language",
+ },
+ expected: {
+ locale: "en-US",
+ type: "language",
+ style: "long",
+ calendar: "gregory",
+ values: [],
+ }
+ },
+ {
+ locales: ["en-US"],
+ options: {
+ type: "weekday",
+ style: "narrow",
+ calendar: "gregory",
+ keys: [3],
+ },
+ expected: {
+ locale: "en-US",
+ type: "weekday",
+ style: "narrow",
+ calendar: "gregory",
+ values: ["W"]
+ }
+ },
+
+ {
+ locales: ["fr"],
+ options: {
+ type: "dateTimeField",
+ keys: ["year", "day"],
+ },
+ expected: {
+ locale: "fr",
+ type: "dateTimeField",
+ style: "long",
+ calendar: "gregory",
+ values: ["année", "jour"],
+ }
+ },
+ {
+ locales: ["fr"],
+ options: {
+ type: "month",
+ keys: [10],
+ },
+ expected: {
+ locale: "fr",
+ type: "month",
+ style: "long",
+ calendar: "gregory",
+ values: ["octobre"],
+ }
+ },
+ {
+ locales: ["fr"],
+ options: {
+ type: "weekday",
+ keys: [6],
+ },
+ expected: {
+ locale: "fr",
+ type: "weekday",
+ style: "long",
+ calendar: "gregory",
+ values: ["samedi"],
+ }
+ },
+ {
+ locales: ["fr"],
+ options: {
+ type: "dayPeriod",
+ keys: ["pm"],
+ },
+ expected: {
+ locale: "fr",
+ type: "dayPeriod",
+ style: "long",
+ calendar: "gregory",
+ values: ["PM"],
+ }
+ },
+
+ {
+ locales: ["it"],
+ options: {
+ type: "weekday",
+ style: "short",
+ keys: [4],
+ },
+ expected: {
+ locale: "it",
+ type: "weekday",
+ style: "short",
+ calendar: "gregory",
+ values: ["gio"],
+ }
+ },
+ {
+ locales: ["it"],
+ options: {
+ type: "month",
+ style: "short",
+ keys: [8],
+ },
+ expected: {
+ locale: "it",
+ type: "month",
+ style: "short",
+ calendar: "gregory",
+ values: ["ago"],
+ }
+ },
+ {
+ locales: ["it"],
+ options: {
+ type: "dayPeriod",
+ style: "short",
+ keys: ["am"],
+ },
+ expected: {
+ locale: "it",
+ type: "dayPeriod",
+ style: "short",
+ calendar: "gregory",
+ values: ["AM"],
+ }
+ },
+ {
+ locales: ["it"],
+ options: {
+ type: "dateTimeField",
+ style: "short",
+ keys: ["month"],
+ },
+ expected: {
+ locale: "it",
+ type: "dateTimeField",
+ style: "short",
+ calendar: "gregory",
+ values: ["mese"],
+ }
+ },
+
+ {
+ locales: ["ar"],
+ options: {
+ type: "weekday",
+ style: "long",
+ keys: [4],
+ },
+ expected: {
+ locale: "ar",
+ type: "weekday",
+ style: "long",
+ calendar: "gregory",
+ values: ["الخميس"],
+ }
+ },
+ {
+ locales: ["ar"],
+ options: {
+ type: "month",
+ style: "long",
+ keys: [8],
+ },
+ expected: {
+ locale: "ar",
+ type: "month",
+ style: "long",
+ calendar: "gregory",
+ values: ["أغسطس"],
+ }
+ },
+ {
+ locales: ["ar"],
+ options: {
+ type: "dayPeriod",
+ style: "long",
+ keys: ["am"],
+ },
+ expected: {
+ locale: "ar",
+ type: "dayPeriod",
+ style: "long",
+ calendar: "gregory",
+ values: ["ص"],
+ }
+ },
+ {
+ locales: ["ar"],
+ options: {
+ type: "dateTimeField",
+ style: "long",
+ keys: ["month"],
+ },
+ expected: {
+ locale: "ar",
+ type: "dateTimeField",
+ style: "long",
+ calendar: "gregory",
+ values: ["الشهر"],
+ }
+ },
+
+ {
+ locales: ["zh-TW"],
+ options: {
+ type: "weekday",
+ style: "abbreviated",
+ keys: [4],
+ },
+ expected: {
+ locale: "zh-TW",
+ type: "weekday",
+ style: "abbreviated",
+ calendar: "gregory",
+ values: ["週四"],
+ }
+ },
+ {
+ locales: ["zh-TW"],
+ options: {
+ type: "month",
+ style: "short",
+ keys: [8],
+ },
+ expected: {
+ locale: "zh-TW",
+ type: "month",
+ style: "short",
+ calendar: "gregory",
+ values: ["8月"],
+ }
+ },
+ {
+ locales: ["zh-TW"],
+ options: {
+ type: "dayPeriod",
+ style: "short",
+ keys: ["am"],
+ },
+ expected: {
+ locale: "zh-TW",
+ type: "dayPeriod",
+ style: "short",
+ calendar: "gregory",
+ values: ["上午"],
+ }
+ },
+ {
+ locales: ["zh-TW"],
+ options: {
+ type: "dateTimeField",
+ style: "short",
+ keys: ["month"],
+ },
+ expected: {
+ locale: "zh-TW",
+ type: "dateTimeField",
+ style: "short",
+ calendar: "gregory",
+ values: ["月"],
+ }
+ },
+
+ /* Invalid input */
+
+ {
+ locales: ["en-US"],
+ options: {
+ type: "weekday",
+ style: "",
+ keys: [4]
+ },
+ expected: {
+ exception: true
+ }
+ },
+ {
+ locales: ["foo-X"],
+ options: {
+ type: "weekday",
+ keys: [4]
+ },
+ expected: {
+ exception: true
+ }
+ },
+ {
+ locales: ["en-US"],
+ options: {
+ keys: [
+ ""
+ ],
+ },
+ expected: {
+ exception: true
+ }
+ },
+]
+
+let intlUtils = window.intlUtils;
+ok(intlUtils, "window.intlUtils should exist");
+
+for (let { locales, options, expected } of testData) {
+ try {
+ let result = intlUtils.getDisplayNames(locales, options);
+
+ is(result.locale, expected.locale, "locale is " + expected.locale);
+ is(result.type, expected.type, "type is " + expected.type);
+ is(result.style, expected.style, "style is " + expected.style);
+ is(result.calendar, expected.calendar, "calendar is " + expected.calendar);
+
+ let values = result.values;
+ let expectedValues = expected.values;
+
+ is(values.length, expectedValues.length, "values' length is " + expectedValues.length);
+
+ for (let i = 0; i < expectedValues.length; ++i) {
+ is(values[i], expectedValues[i], "value is " + expectedValues[i]);
+ }
+ } catch (e) {
+ ok(expected.exception, "Exception expected : " + e);
+ }
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/tests/mochitest/chrome/test_intlUtils_isAppLocaleRTL.html b/dom/tests/mochitest/chrome/test_intlUtils_isAppLocaleRTL.html
new file mode 100644
index 0000000000..fc6e8e2fb4
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_intlUtils_isAppLocaleRTL.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1673054
+-->
+<head>
+ <title>Test for Bug 1673054 </title>
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+</head>
+<body onload="test()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1673054 ">Mozilla Bug 1673054</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<script>
+async function test() {
+ SimpleTest.waitForExplicitFinish();
+
+ let intlUtils = window.intlUtils;
+ ok(intlUtils, "window.intlUtils should exist");
+
+ let originalValue = intlUtils.isAppLocaleRTL();
+ ok(originalValue == false, "window.intlUtils.isAppLocaleRTL should exist");
+
+ await SpecialPowers.pushPrefEnv({ set: [["intl.l10n.pseudo", "bidi"]] });
+ let currentValue = intlUtils.isAppLocaleRTL();
+ ok(currentValue == true, "If pseudolocale is bidi, isAppLocaleRTL should be true");
+
+ await SpecialPowers.clearUserPref("intl.l10n.pseudo");
+ currentValue = intlUtils.isAppLocaleRTL();
+ ok(originalValue == currentValue, "Without override, isAppLocaleRTL should be default");
+
+ SimpleTest.finish();
+}
+</script>
+</body>
+</html>
diff --git a/dom/tests/mochitest/chrome/test_moving_nodeList.xhtml b/dom/tests/mochitest/chrome/test_moving_nodeList.xhtml
new file mode 100644
index 0000000000..0a3f20eeac
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_moving_nodeList.xhtml
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=684115
+-->
+<window title="Mozilla Bug 684115"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=654370"
+ target="_blank">Mozilla Bug 684115</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+ SimpleTest.waitForExplicitFinish();
+
+ var firstWindow, secondWindow;
+ function iframe_loaded() {
+ if (!firstWindow || !secondWindow)
+ return;
+ var nodeList = firstWindow.document.childNodes;
+ ok(!("expando" in nodeList), "shouldn't be able to see expandos on the NodeList");
+ nodeList = firstWindow.wrappedJSObject.getNodeList();
+ ok(("expando" in nodeList), "should be able to see expandos on the NodeList");
+ options = firstWindow.wrappedJSObject.getOptions();
+ is(options.selectedIndex, -1, "can access selectedIndex in chrome");
+ secondWindow.wrappedJSObject.tryToUseNodeList(nodeList, ok);
+ nodeList = document.childNodes;
+ secondWindow.wrappedJSObject.tryToUseNodeList(nodeList, ok);
+ SimpleTest.finish();
+ }
+
+ ]]></script>
+
+ <iframe id="one" src="http://mochi.test:8888/tests/dom/tests/mochitest/general/file_moving_nodeList.html"
+ onload="firstWindow = this.contentWindow; iframe_loaded()" />
+ <iframe id="two" src="http://example.org/tests/dom/tests/mochitest/general/file_moving_nodeList.html"
+ onload="secondWindow = this.contentWindow; iframe_loaded()" />
+</window>
diff --git a/dom/tests/mochitest/chrome/test_moving_xhr.xhtml b/dom/tests/mochitest/chrome/test_moving_xhr.xhtml
new file mode 100644
index 0000000000..717a0715cc
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_moving_xhr.xhtml
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=684115
+-->
+<window title="Mozilla Bug 684115"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=654370"
+ target="_blank">Mozilla Bug 684115</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+ SimpleTest.waitForExplicitFinish();
+
+ var firstWindow, secondWindow;
+ function iframe_loaded() {
+ if (!firstWindow || !secondWindow)
+ return;
+ var xhr = firstWindow.wrappedJSObject.createXHR();
+ ok(("expando" in xhr), "should be able to see expandos on the XHR");
+ is(xhr.readyState, XMLHttpRequest.UNSENT, "can access readyState in chrome");
+ secondWindow.wrappedJSObject.tryToUseXHR(xhr, ok);
+ secondWindow.wrappedJSObject.tryToUseXHR(new XMLHttpRequest(), ok);
+ SimpleTest.finish();
+ }
+
+ ]]></script>
+
+ <iframe id="one" src="http://mochi.test:8888/tests/dom/tests/mochitest/general/file_moving_xhr.html"
+ onload="firstWindow = this.contentWindow; iframe_loaded()" />
+ <iframe id="two" src="http://example.org/tests/dom/tests/mochitest/general/file_moving_xhr.html"
+ onload="secondWindow = this.contentWindow; iframe_loaded()" />
+</window>
diff --git a/dom/tests/mochitest/chrome/test_nodesFromPoint.html b/dom/tests/mochitest/chrome/test_nodesFromPoint.html
new file mode 100644
index 0000000000..30675a41dd
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_nodesFromPoint.html
@@ -0,0 +1,119 @@
+<!doctype html>
+<meta charset="utf-8">
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<style>
+ div { text-align: justify; max-height: 100vh; }
+</style>
+<div id="testElement"></div>
+<script>
+
+// TODO(emilio): Upstream to WPT once there's a spec for this and our
+// implementation is not [ChromeOnly].
+
+const testElement = document.getElementById("testElement");
+
+testElement.innerHTML = "X ".repeat(5000);
+
+{
+ const rect = testElement.getBoundingClientRect();
+
+ const node =
+ document.nodeFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
+ is(node, testElement.firstChild, "Should return the text node");
+
+ const nodes =
+ document.nodesFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
+
+ const expected = [testElement.firstChild, testElement, document.body, document.documentElement];
+ is(nodes.length, expected.length, "Not the amount of expected nodes");
+
+ for (let i = 0; i < nodes.length; ++i)
+ is(nodes[i], expected[i]);
+}
+
+// Make the test slotted, and add some fallback that we'll test later as well.
+{
+ // Work around the sanitizer by building the DOM manually....
+ const slot = document.createElement("slot");
+ slot.innerHTML = "Y ".repeat(5000);
+
+ const wrapper = document.createElement("div");
+ wrapper.appendChild(slot);
+
+ testElement.attachShadow({ mode: "open" }).appendChild(wrapper);
+}
+
+{
+ const rect = testElement.getBoundingClientRect();
+
+ const node =
+ document.nodeFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
+ is(node, testElement.firstChild, "Should return the text node");
+
+ const nodes =
+ document.nodesFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
+
+ const expected = [testElement.firstChild, testElement, document.body, document.documentElement];
+ is(nodes.length, expected.length, "Not the amount of expected nodes (returned nodes in the shadow?)");
+
+ for (let i = 0; i < nodes.length; ++i)
+ is(nodes[i], expected[i]);
+}
+
+{
+ const rect = testElement.getBoundingClientRect();
+
+ const node =
+ testElement.shadowRoot.nodeFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
+ is(node, testElement.shadowRoot.firstChild, "Should return the div wrapping the text node");
+
+ const nodes =
+ testElement.shadowRoot.nodesFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
+
+ const expected = [testElement.shadowRoot.firstChild];
+ is(nodes.length, expected.length, "Not the amount of expected nodes (returned nodes outside of the shadow?)");
+
+ for (let i = 0; i < nodes.length; ++i)
+ is(nodes[i], expected[i]);
+}
+
+// Show the fallback.
+testElement.firstChild.remove();
+
+{
+ const rect = testElement.getBoundingClientRect();
+
+ const fallbackText = testElement.shadowRoot.querySelector("slot").firstChild;
+
+ const node =
+ testElement.shadowRoot.nodeFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
+ is(node, fallbackText, "Should return the fallback text");
+
+ const nodes =
+ testElement.shadowRoot.nodesFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
+
+ const expected = [fallbackText, testElement.shadowRoot.firstChild];
+ is(nodes.length, expected.length, "Not the amount of expected nodes (returned nodes outside of the shadow?)");
+
+ for (let i = 0; i < nodes.length; ++i)
+ is(nodes[i], expected[i]);
+}
+
+// Test the fallback from the document.
+{
+ const rect = testElement.getBoundingClientRect();
+
+ const node =
+ document.nodeFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
+ is(node, testElement, "Should return the element, since the fallback text is in the shadow");
+
+ const nodes =
+ document.nodesFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
+
+ const expected = [testElement, document.body, document.documentElement];
+ is(nodes.length, expected.length, "Not the amount of expected nodes (returned nodes inside of the shadow?)");
+
+ for (let i = 0; i < nodes.length; ++i)
+ is(nodes[i], expected[i]);
+}
+</script>
diff --git a/dom/tests/mochitest/chrome/test_nodesFromRect.html b/dom/tests/mochitest/chrome/test_nodesFromRect.html
new file mode 100644
index 0000000000..5f5566c89b
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_nodesFromRect.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>nsIDOMWindowUtils::nodesFromRect test - bug 489127</title>
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+<script type="application/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function done() {
+ testwindow.close();
+ SimpleTest.finish();
+ }
+ var testwindow = window.open("489127.html", '_new', 'width=600,height=400');
+</script>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</body>
+</html>
+
diff --git a/dom/tests/mochitest/chrome/test_parsingMode.html b/dom/tests/mochitest/chrome/test_parsingMode.html
new file mode 100644
index 0000000000..2966b8f79b
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_parsingMode.html
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>CSSStyleSheet parsingMode test - bug 1230491</title>
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+<script type="application/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function sheetText(sheet) {
+ return [...sheet.cssRules].map(r => r.cssText).join();
+ }
+ function run() {
+ const sss = Cc["@mozilla.org/content/style-sheet-service;1"]
+ .getService(Ci.nsIStyleSheetService);
+ const utils = window.windowUtils;
+
+ const userUrl = encodeURI("data:text/css,body { color: seagreen; -moz-window-transform: none }");
+ utils.loadSheetUsingURIString(userUrl, sss.USER_SHEET);
+
+ const agentUrl = encodeURI("data:text/css,body { color: tomato; }");
+ utils.loadSheetUsingURIString(agentUrl, sss.AGENT_SHEET);
+
+ const authorUrl = "chrome://mochikit/content/tests/SimpleTest/test.css";
+
+ let results = [];
+ for (let sheet of InspectorUtils.getAllStyleSheets(document)) {
+ if (sheet.href === agentUrl) {
+ is(sheet.parsingMode, "agent", "agent sheet has expected mode");
+ results[sss.AGENT_SHEET] = 1;
+ } else if (sheet.href === userUrl) {
+ is(sheet.parsingMode, "user", "user sheet has expected mode");
+ is(sheet.cssRules[0].style.length, 2, "Chrome-only properties are parsed in user sheet")
+ results[sss.USER_SHEET] = 1;
+ } else if (sheet.href === authorUrl) {
+ is(sheet.parsingMode, "author", "author sheet has expected mode");
+ results[sss.AUTHOR_SHEET] = 1;
+ } else if (sheet.href === "about:PreferenceStyleSheet") {
+ is(sheet.parsingMode, "agent",
+ "about:PreferenceStyleSheet has agent mode");
+ continue;
+ } else {
+ // Ignore sheets we don't care about.
+ continue;
+ }
+
+ // Check that re-parsing preserves the mode.
+ let mode = sheet.parsingMode;
+ let text = sheetText(sheet);
+ InspectorUtils.parseStyleSheet(sheet, "body { color: chartreuse; }");
+ if (mode == "agent") {
+ is(sheetText(sheet), text,
+ "Reparsing should not have changed a UA sheet");
+ } else {
+ isnot(sheetText(sheet), text,
+ "Reparsing should have changed a non-UA sheet");
+ }
+ is(sheet.parsingMode, mode,
+ "check that re-parsing preserved mode " + mode);
+ }
+
+ ok(results[sss.AGENT_SHEET] && results[sss.USER_SHEET] &&
+ results[sss.AUTHOR_SHEET],
+ "all sheets seen");
+
+ SimpleTest.finish();
+ }
+</script>
+</head>
+<body onload="run()">
+ <div> What? </div>
+</body>
+</html>
diff --git a/dom/tests/mochitest/chrome/test_popup_blocker_chrome.xhtml b/dom/tests/mochitest/chrome/test_popup_blocker_chrome.xhtml
new file mode 100644
index 0000000000..1c00815aa6
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_popup_blocker_chrome.xhtml
@@ -0,0 +1,66 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=662519
+-->
+<window title="Mozilla Bug 662519"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=662519"
+ target="_blank">Mozilla Bug 662519</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+
+ /** Test for Bug 662519 **/
+
+ let w = null;
+
+ let steps = [
+ function() {
+ w = window.open("file_popup_blocker_chrome.html", "", "width=200,height=200");
+ ok(w, "The window object shouldn't be null");
+ // next() is called within file_popup_blocker_chrome.html
+ },
+ function() {
+ w.close();
+ ok(true, "The popup appeared");
+ next();
+ },
+ function() {
+ w = window.open("file_popup_blocker_chrome.html", "_blank", "width=200,height=200");
+ ok(w, "The window object shouldn't be null");
+ // next() is called within file_popup_blocker_chrome.html
+ },
+ function() {
+ w.close();
+ ok(true, "The popup appeared");
+ next();
+ },
+ ];
+
+ function next() {
+ if (!steps.length) {
+ SimpleTest.finish();
+ return;
+ }
+ let step = steps.shift();
+ step();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+
+ // We have to enable dom.disable_open_during_load which is disabled
+ // by the test harness.
+ SpecialPowers.pushPrefEnv({'set': [["dom.disable_open_during_load", true]] }, function() {
+ next();
+ });
+ ]]>
+ </script>
+</window>
diff --git a/dom/tests/mochitest/chrome/test_queryCaretRect.html b/dom/tests/mochitest/chrome/test_queryCaretRect.html
new file mode 100644
index 0000000000..fa1b643d23
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_queryCaretRect.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>nsIDOMWindowUtils::sendQueryContentEvent w/QUERY_CARET_RECT test</title>
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+<script type="application/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function done() {
+ testwindow.close();
+ SimpleTest.finish();
+ }
+ var isWindows = ("@mozilla.org/windows-registry-key;1" in Cc);
+ var testwindow = window.open("queryCaretRect" + (isWindows ? "Win" : "Unix") + ".html",
+ "_new", "width=800,height=800");
+</script>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</body>
+</html>
diff --git a/dom/tests/mochitest/chrome/test_resize_move_windows.xhtml b/dom/tests/mochitest/chrome/test_resize_move_windows.xhtml
new file mode 100644
index 0000000000..bf44523815
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_resize_move_windows.xhtml
@@ -0,0 +1,249 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=565541
+-->
+<window title="Mozilla Bug 565541"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=565541"
+ target="_blank">Mozilla Bug 565541</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+
+ /** Test for Bug 565541 **/
+ var previousX, previousY, previousWidth, previousHeight;
+
+ function backValues()
+ {
+ previousX = window.top.screenX;
+ previousY = window.top.screenY;
+ previousWidth = window.top.outerWidth;
+ previousHeight = window.top.outerHeight;
+ }
+
+ function restoreValues()
+ {
+ window.top.moveTo(previousX, previousY);
+ window.top.resizeTo(previousWidth, previousHeight);
+ }
+
+ function getNewWidth(aWindow)
+ {
+ return (aWindow.innerWidth > (screen.width / 2)) ? 100 : screen.width;
+ }
+
+ function getNewHeight(aWindow)
+ {
+ return (aWindow.innerHeight > (screen.height / 2)) ? 100 : screen.height;
+ }
+
+ function getNewX(aWindow)
+ {
+ return (aWindow.screenX > ((screen.width - aWindow.outerWidth) / 2))
+ ? 0 : screen.width - aWindow.outerWidth;
+ }
+
+ function getNewY(aWindow)
+ {
+ return (aWindow.screenY > ((screen.height - aWindow.outerHeight) / 2))
+ ? 0 : screen.height - aWindow.outerHeight;
+ }
+
+ /**
+ * hitEventLoop is called when we want to check something but we can't rely on
+ * an event or a specific number of event loop hiting.
+ * This method can be called by specifying a condition, a test (using SimpleTest
+ * API), how many times the event loop has to be hitten and what to call next.
+ * If times < 0, the event loop will be hitten as long as the condition isn't
+ * true or the test doesn't time out.
+ */
+ function hitEventLoop(condition, test, times, next) {
+ if (condition() || times == 0) {
+ test();
+ next();
+ return;
+ }
+
+ setTimeout(hitEventLoop, 0, condition, test, times - 1, next);
+ }
+
+ function checkChangeIsEnabled(aWindow, aNext)
+ {
+ // Something should happen. We are not going to go to the next test until
+ // it does.
+ var hits = -1;
+
+ var prevWidth;
+ var prevHeight;
+
+ var prevX;
+ var prevY;
+
+ var oWidth;
+ var oHeight;
+
+ function sizeChangeCondition() {
+ return aWindow.innerWidth != prevWidth && aWindow.innerHeight != prevHeight;
+ }
+
+ function sizeChangeTest() {
+ isnot(aWindow.innerWidth, prevWidth, "Window width should have changed");
+ isnot(aWindow.innerHeight, prevHeight, "Window height should have changed");
+
+ prevWidth = aWindow.innerWidth;
+ prevHeight = aWindow.innerHeight;
+ }
+
+ function posChangeCondition() {
+ // With GTK, sometimes, only one dimension changes.
+ if (navigator.platform.includes('Linux')) {
+ return aWindow.screenX != prevX || aWindow.screenY != prevY;
+ }
+ return aWindow.screenX != prevX && aWindow.screenY != prevY;
+ }
+
+ function posChangeConditionIgnoreLinux() {
+ if (posChangeCondition()) {
+ return true;
+ }
+
+ if (navigator.platform.includes('Linux')) {
+ return true;
+ }
+ }
+
+ function posChangeTest() {
+ // With GTK, sometimes, only one dimension changes.
+ if (navigator.platform.includes('Linux')) {
+ // With GTK, sometimes, aWindow.screenX changes during two calls.
+ // So we call it once and save the returned value.
+ var x = aWindow.screenX;
+ var y = aWindow.screenY;
+ if (x != prevX) {
+ isnot(x, prevX, "Window x position should have changed");
+ }
+ if (y != prevY) {
+ isnot(y, prevY, "Window y position should have changed");
+ }
+ } else {
+ isnot(aWindow.screenX, prevX, "Window x position should have changed");
+ isnot(aWindow.screenY, prevY, "Window y position should have changed");
+ }
+
+ prevX = aWindow.screenX;
+ prevY = aWindow.screenY;
+ }
+
+ function outerChangeCondition() {
+ return aWindow.outerWidth != oWidth && aWindow.outerHeight != oHeight;
+ }
+
+ function outerChangeTest() {
+ isnot(aWindow.outerWidth, oWidth, "Window outerWidth should have changed");
+ isnot(aWindow.outerHeight, oHeight, "Window outerHeight should have changed");
+
+ aWindow.resizeTo(oWidth, oHeight);
+ }
+
+ /**
+ * Size checks.
+ */
+ prevWidth = aWindow.innerWidth;
+ prevHeight = aWindow.innerHeight;
+
+ aWindow.resizeTo(getNewWidth(aWindow), getNewHeight(aWindow));
+ hitEventLoop(sizeChangeCondition, sizeChangeTest, hits, function () {
+ aWindow.resizeBy(getNewWidth(aWindow) - aWindow.innerWidth,
+ getNewHeight(aWindow) - aWindow.innerHeight);
+
+ hitEventLoop(sizeChangeCondition, sizeChangeTest, hits, function () {
+ prevWidth = aWindow.innerWidth;
+ prevHeight = aWindow.innerHeight;
+ aWindow.sizeToContent();
+
+ hitEventLoop(sizeChangeCondition, sizeChangeTest, hits, function () {
+ /**
+ * Position checks.
+ */
+ prevX = aWindow.screenX;
+ prevY = aWindow.screenY;
+
+ aWindow.moveBy(getNewX(aWindow) - aWindow.screenX,
+ getNewY(aWindow) - aWindow.screenY);
+
+ hitEventLoop(posChangeConditionIgnoreLinux, posChangeTest, hits, function () {
+ /**
+ * Outer width/height checks.
+ */
+ oWidth = aWindow.outerWidth;
+ oHeight = aWindow.outerHeight;
+
+ aWindow.resizeTo(oWidth * 2, oHeight* 2);
+
+ hitEventLoop(outerChangeCondition, outerChangeTest, hits, aNext);
+ });
+ });
+ });
+ });
+ }
+
+ SimpleTest.waitForExplicitFinish();
+
+ function test() {
+ SimpleTest.waitForFocus(function() {
+ if (screen.width <= 200 || screen.height <= 200) {
+ todo(false, "The screen is too small to run this test.");
+ SimpleTest.finish();
+ return;
+ }
+
+ backValues();
+
+ // We are in a chrome context, we can change the size and position.
+ checkChangeIsEnabled(window.top, async function() {
+ // We create a window and check that the size and position can be set with
+ // window.open parameters and can be changed by the created window.
+ var w = window.open("file_resize_move_windows_1.html", '',
+ 'width=170,height=170,screenX=25,screenY=25');
+
+ await SimpleTest.promiseWaitForCondition(() => w.document.readyState == "complete");
+ SimpleTest.waitForFocus(function() {
+ w.wrappedJSObject.ok = SimpleTest.ok;
+ w.wrappedJSObject.check();
+ // The current window can change the size and position of the created one.
+ checkChangeIsEnabled(w, async function() {
+ w.close();
+ // If we call window.open with an empty string as a third parameter,
+ // by default, it will create a new tab instead of a new window.
+ // In a chrome context, the size and position can change.
+ w = window.open("file_resize_move_windows_2.html", '', '');
+ await SimpleTest.promiseWaitForCondition(() => w.document.readyState == "complete");
+ SimpleTest.waitForFocus(function() {
+ // The current window can change the size and position of the new tab.
+ // Because we are in a chrome context.
+ checkChangeIsEnabled(w, function() {
+ w.close();
+ restoreValues();
+ SimpleTest.finish();
+ });
+ }, w, false);
+ });
+ }, w, false);
+ });
+ });
+ }
+
+ addLoadEvent(function onLoad() {
+ test();
+ });
+ ]]>
+ </script>
+</window>
diff --git a/dom/tests/mochitest/chrome/test_sandbox_bindings.xhtml b/dom/tests/mochitest/chrome/test_sandbox_bindings.xhtml
new file mode 100644
index 0000000000..e7d80f75af
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_sandbox_bindings.xhtml
@@ -0,0 +1,317 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=741267
+-->
+<window title="Mozilla Bug 741267"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+ <script type="application/javascript">
+
+
+</script>
+ <iframe id="t"></iframe>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=741267"
+ target="_blank">Mozilla Bug 741267</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+
+ /** Test for Bug 741267 **/
+ function isXrayWrapper(x) {
+ return Cu.isXrayWrapper(x);
+ }
+
+ function doTest() {
+ var win = $("t").contentWindow;
+ ok(isXrayWrapper(win),
+ "We want to be testing things with an Xray as sandboxPrototype here");
+
+ var sandbox = Cu.Sandbox(win, { sandboxPrototype: win });
+
+ is(sandbox._content, undefined, "_content does nothing over Xray");
+
+ try {
+ var css = Cu.evalInSandbox("CSSStyleDeclaration", sandbox);
+ is(String(css.prototype), "[object CSSStyleDeclaration]",
+ "'CSSStyleDeclaration.prototype' in a sandbox should return the CSSStyleDeclaration interface prototype object");
+ } catch (e) {
+ ok(false, "'CSSStyleDeclaration' shouldn't throw in a sandbox");
+ }
+ try {
+ var et = Cu.evalInSandbox("EventTarget", sandbox);
+ ok(et, "'EventTarget' in a sandbox should return the EventTarget interface object");
+ ok(isXrayWrapper(et), "Getting an interface object on an Xray wrapper should return an Xray wrapper");
+ } catch (e) {
+ ok(false, "'EventTarget' shouldn't throw in a sandbox");
+ }
+ try {
+ var xhr = Cu.evalInSandbox("XMLHttpRequest.prototype", sandbox);
+ ok(xhr, "'XMLHttpRequest.prototype' in a sandbox should return the XMLHttpRequest interface prototype object");
+ ok(isXrayWrapper(xhr), "Getting an interface prototype object on an Xray wrapper should return an Xray wrapper");
+ ok(isXrayWrapper(xhr.constructor), "Getting the constructor property on an Xray wrapper of an interface prototype object should return an Xray wrapper");
+ isnot(Object.getOwnPropertyDescriptor(xhr, "send"), undefined,
+ "We should claim to have a send() method");
+ isnot(Object.keys(xhr).indexOf("responseType"), -1,
+ "We should claim to have a responseType property");
+ isnot(Object.getOwnPropertyNames(xhr).indexOf("open"), -1,
+ "We should claim to have an open() method");
+ isnot(Object.getOwnPropertyDescriptor(xhr, "constructor"), undefined,
+ "We should claim to have a 'constructor' property");
+ } catch (e) {
+ ok(false, "'XMLHttpRequest.prototype' shouldn't throw in a sandbox");
+ }
+ try {
+ var img = Cu.evalInSandbox("Image.prototype", sandbox);
+ ok(img, "'Image.prototype' in a sandbox should return the interface prototype object");
+ ok(isXrayWrapper(img), "Getting an interface prototype object on an Xray wrapper should return an Xray wrapper");
+ } catch (e) {
+ ok(false, "'Image.prototype' shouldn't throw in a sandbox");
+ }
+ try {
+ var xhr = Cu.evalInSandbox("XMLHttpRequest", sandbox);
+ xhr.prototype = "notok";
+ } finally {
+ isnot(xhr.prototype, "notok", "'XMLHttpRequest.prototype' should be readonly");
+ }
+ var constructorWritable = false;
+ try {
+ var xhr = Cu.evalInSandbox("XMLHttpRequest.prototype", sandbox);
+ xhr.constructor = "ok";
+ is(xhr.constructor, "ok", "'XMLHttpRequest.prototype.constructor' should be writeable");
+ } catch (e) {
+ ok(false, "'XMLHttpRequest.prototype.constructor' should be writeable");
+ }
+ try {
+ var xhr = Cu.evalInSandbox("XMLHttpRequest", sandbox);
+ is(String(xhr), String(XMLHttpRequest), "'XMLHttpRequest' in a sandbox should return the XMLHttpRequest interface object");
+ ok(isXrayWrapper(xhr.prototype), "Getting the prototype property on an Xray wrapper of an interface object should return an Xray wrapper");
+ isnot(Object.getOwnPropertyDescriptor(xhr, "UNSENT"), undefined,
+ "We should claim to have an UNSENT constant");
+ isnot(Object.keys(xhr).indexOf("OPENED"), -1,
+ "We should claim to have an OPENED constant");
+ isnot(Object.getOwnPropertyNames(xhr).indexOf("DONE"), -1,
+ "We should claim to have a DONE constant");
+ isnot(Object.getOwnPropertyDescriptor(xhr, "prototype"), undefined,
+ "We should claim to have 'prototype' property");
+ } catch (e) {
+ ok(false, "'XMLHttpRequest' shouldn't throw in a sandbox");
+ }
+ try {
+ var xhr = Cu.evalInSandbox("new XMLHttpRequest()", sandbox);
+ is("" + xhr, new XMLHttpRequest() + "", "'new XMLHttpRequest()' in a sandbox should create an XMLHttpRequest object");
+ } catch (e) {
+ ok(false, "'new XMLHttpRequest()' shouldn't throw in a sandbox (1)");
+ }
+ try {
+ var xhr = Cu.evalInSandbox("XMLHttpRequest.toString = function () { return 'Failed'; }; XMLHttpRequest;", sandbox);
+ is(xhr.toString(), XMLHttpRequest + "", "XMLHttpRequest.toString in the sandbox should not override the native toString behaviour");
+ } catch (e) {
+ ok(false, "'XMLHttpRequest' shouldn't throw in a sandbox");
+ }
+ try {
+ var xhr = Cu.evalInSandbox("XMLHttpRequest.prototype.toString = function () { return 'Failed'; }; new XMLHttpRequest();", sandbox);
+ is(xhr.toString(), new XMLHttpRequest() + "", "XMLHttpRequest.prototype.toString in the sandbox should not override the native toString behaviour");
+ } catch (e) {
+ ok(false, "'new XMLHttpRequest()' shouldn't throw in a sandbox (2)");
+ }
+
+ try {
+ // have to run this test before document.defaultView.XMLHttpRequest
+ // gets munged in the sandbox.
+ var proto = Cu.evalInSandbox("XMLHttpRequest.prototype", sandbox);
+ props = [];
+ for (var i in proto) {
+ props.push(i);
+ }
+ isnot(props.indexOf("dispatchEvent"), -1,
+ "'dispatchEvent' property should be enumerable on XMLHttpRequest.prototype");
+ props = Object.getOwnPropertyNames(proto);
+ is(props.indexOf("dispatchEvent"), -1,
+ "'dispatchEvent' is not an own property on XMLHttpRequest.prototype; it's on EventTarget.prototype")
+ } catch (e) {
+ ok(false, "XMLHttpRequest.prototype manipulation via an Xray shouldn't throw" + e);
+ }
+ try {
+ Cu.evalInSandbox("XMLHttpRequest.prototype.a = 'expando a'", sandbox);
+ Cu.evalInSandbox("XMLHttpRequest.prototype.b = 'expando b'", sandbox);
+ Cu.evalInSandbox("XMLHttpRequest.prototype", sandbox).b = 'xrayexpando';
+ var xhr = Cu.evalInSandbox("new XMLHttpRequest()", sandbox);
+ is(xhr.a, undefined, "'XMLHttpRequest()' in a sandbox should not have expandos from inside the sandbox");
+ is(xhr.b, "xrayexpando", "'new XMLHttpRequest()' in a sandbox should have Xray expandos");
+ } catch (e) {
+ ok(false, "'new XMLHttpRequest()' shouldn't throw in a sandbox");
+ }
+ try {
+ Cu.evalInSandbox("document.defaultView.XMLHttpRequest = function() {};", sandbox);
+ var win = Cu.evalInSandbox("document.defaultView", sandbox);
+ var xhr = new win.XMLHttpRequest();
+ is("" + xhr, new XMLHttpRequest() + "", "'new XMLHttpRequest()' in a sandbox should create an XMLHttpRequest object");
+ } catch (e) {
+ ok(false, "'new XMLHttpRequest()' shouldn't throw in a sandbox");
+ }
+ try {
+ var canvas = Cu.evalInSandbox("document.createElement('canvas').getContext('2d')", sandbox);
+ is(canvas.DRAWWINDOW_DRAW_CARET, CanvasRenderingContext2D.DRAWWINDOW_DRAW_CARET, "Constants should be defined on DOM objects in a sandbox");
+ } catch (e) {
+ ok(false, "'document.createElement('canvas').getContext('2D')' shouldn't throw in a sandbox");
+ }
+ try {
+ var classList = Cu.evalInSandbox("document.body.className = 'a b'; document.body.classList", sandbox);
+ is(classList.toString(), "a b", "Stringifier should be called");
+ } catch (e) {
+ ok(false, "Stringifying shouldn't throw in a sandbox");
+ }
+ try {
+ var ctx = Cu.evalInSandbox("var ctx = document.createElement('canvas').getContext('2d'); ctx.foopy = 5; ctx", sandbox);
+ ok(!("foopy" in ctx), "We should have an Xray here");
+ var data = ctx.createImageData(1, 1);
+ for (var i = 0; i < data.data.length; ++i) {
+ // Watch out for premultiplied bits... just set all the alphas to 255
+ if (i % 4 == 3) {
+ // Note - We need to waive Xrays here because indexed access on Typed
+ // Arrays is forbidden over Xrays for performance reasons.
+ Cu.waiveXrays(data.data)[i] = 255;
+ } else {
+ Cu.waiveXrays(data.data)[i] = i;
+ }
+ }
+ ctx.putImageData(data, 0, 0);
+ var data2 = ctx.getImageData(0, 0, 1, 1);
+ is(data2.data.length, data.data.length, "Lengths must match");
+ for (i = 0; i < data.data.length; ++i)
+ is(Cu.waiveXrays(data.data)[i], Cu.waiveXrays(data2.data)[i], "Data at " + i + " should match");
+ } catch (e) {
+ ok(false, "Imagedata manipulation via an Xray shouldn't throw " + e);
+ }
+
+ try {
+ var list = Cu.evalInSandbox("document.getElementsByTagName('*')", sandbox);
+ props = [];
+ for (var i in list) {
+ props.push(i);
+ }
+ is(props.indexOf("constructor"), -1,
+ "'constructor' property should not be enumerable on list object");
+ props = Object.getOwnPropertyNames(list);
+ is(props.indexOf("constructor"), -1,
+ "'constructor' property should not be an own property name on list object");
+ } catch (e) {
+ ok(false, "NodeList.prototype manipulation via an Xray shouldn't throw" + e);
+ }
+
+ try {
+ var proto = Cu.evalInSandbox("NodeList.prototype", sandbox);
+ props = [];
+ for (var i in proto) {
+ props.push(i);
+ }
+ is(props.indexOf("constructor"), -1,
+ "'constructor' property should not be enumerable on proto directly");
+ props = Object.getOwnPropertyNames(proto);
+ isnot(props.indexOf("constructor"), -1,
+ "'constructor' property should be an own property name on proto");
+ } catch (e) {
+ ok(false, "NodeList.prototype manipulation via an Xray shouldn't throw" + e);
+ }
+
+ try {
+ var url = Cu.evalInSandbox("URL", sandbox);
+ for (var i in url) {
+ url[i];
+ }
+ isnot(url.createObjectURL, undefined, "Should have a createObjectURL");
+ ok(true, "We didn't crash!");
+ } catch (e) {
+ ok(false, "URL interface object manipulation via an Xray shouldn't throw" + e);
+ }
+
+ try {
+ url.revokeObjectURL("");
+ } catch (e) {
+ // Just testing whether revokeObjectURL crashes us
+ }
+ ok(true, "We didn't crash!");
+
+ // And now tests that don't use a window-associated sandbox
+ sandbox = Cu.Sandbox(win.document.nodePrincipal,
+ { sandboxPrototype: win });
+ try {
+ var ws = Cu.evalInSandbox('var ws = new WebSocket("ws://example.org"); ws', sandbox);
+ // Test that we actually got a WebSocket object, probably
+ ok("bufferedAmount" in ws, "What is this object?");
+ } catch (e) {
+ ok(false, "Should be able to create a WebSocket in a sandbox " + e);
+ }
+ try {
+ var es = Cu.evalInSandbox('var es = new EventSource("about:blank"); es', sandbox);
+ // Test that we actually got a EventSource object, probably
+ is(es.url, "about:blank", "What is this object?");
+ } catch (e) {
+ ok(false, "Should be able to create an EventSource in a sandbox " + e);
+ }
+
+ try {
+ var nodeFilterIface = Cu.evalInSandbox(
+ 'NodeFilter.myExpando = "FAIL"; NodeFilter', sandbox);
+ is(nodeFilterIface.myExpando, undefined,
+ "Should have Xrays for callback interface objects");
+ } catch (e) {
+ ok(false, "Should be able to return NodeFilter from a sandbox " + e);
+ }
+
+ try {
+ var eventCtor = Cu.evalInSandbox("Event", sandbox);
+ var e = new eventCtor("test", { bubbles: true });
+ is(e.bubbles, true, "Dictionary argument should work");
+ } catch (e) {
+ ok(false, "Should be able to construct my event " + e);
+ }
+
+ try {
+ var elem = Cu.evalInSandbox('document.createElement("p")', sandbox);
+ elem.expando = 5;
+ elem.expando = 7;
+ is(elem.expando, 7, "Should be able to set expandos on Xrays for DOM bindings");
+ var doc = Cu.evalInSandbox('document', sandbox);
+ doc.expando = 5;
+ doc.expando = 7;
+ is(doc.expando, 7, "Should be able to set expandos on Xrays for DOM bindings with named properties");
+ } catch (e) {
+ ok(false, "Setting expandos on Xrays shouldn't throw " + e);
+ }
+
+ // Test that binding a bareword window method produces something
+ // which has a .call
+ try {
+ var binary = Cu.evalInSandbox(
+ 'btoa.bind(window).call(null, "foo")', sandbox);
+ is(binary, "Zm9v", "Should get the right result from .call on bound btoa");
+ } catch (e) {
+ ok(false, ".call on bound btoa shouldn't throw " + e);
+ }
+
+ // Test that binding a bareword window method produces something
+ // which has a .apply
+ try {
+ var binary = Cu.evalInSandbox(
+ 'btoa.bind(window).apply(null, ["foo"])', sandbox);
+ is(binary, "Zm9v", "Should get the right result from .apply on bound btoa");
+ } catch (e) {
+ ok(false, ".apply on bound btoa shouldn't throw " + e);
+ }
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(doTest);
+ ]]>
+ </script>
+</window>
diff --git a/dom/tests/mochitest/chrome/test_sandbox_eventhandler.xhtml b/dom/tests/mochitest/chrome/test_sandbox_eventhandler.xhtml
new file mode 100644
index 0000000000..3c870a6f18
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_sandbox_eventhandler.xhtml
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=817284
+-->
+<window title="Mozilla Bug 817284"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=817284"
+ target="_blank">Mozilla Bug 817284</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+
+ /** Test for Bug 817284 **/
+ var sb = Cu.Sandbox("http://example.com", { wantGlobalProperties: ["XMLHttpRequest"] });
+
+ // Test event handler calls
+ var xhr = Cu.evalInSandbox(
+ 'var xhr = new XMLHttpRequest();\
+ var called = false;\
+ xhr.onload = function() { called = true; };\
+ xhr', sb);
+
+ var e = document.createEvent("Events");
+ e.initEvent("load", false, false);
+ xhr.dispatchEvent(e);
+ is(Cu.evalInSandbox('called', sb), true, "Event handler should have been called");
+ ]]>
+ </script>
+</window>
diff --git a/dom/tests/mochitest/chrome/test_sandbox_image.xhtml b/dom/tests/mochitest/chrome/test_sandbox_image.xhtml
new file mode 100644
index 0000000000..a922a7472d
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_sandbox_image.xhtml
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=616397
+-->
+<window title="Mozilla Bug 616397"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+ <iframe id="t"></iframe>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=616397"
+ target="_blank">Mozilla Bug 616397</a>
+ </body>
+
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ /** Test for Bug 616397 **/
+ function doTest() {
+ var win = $("t").contentWindow;
+ var sandbox = Cu.Sandbox(win, { sandboxPrototype: win });
+ var result = Cu.evalInSandbox("new Image()", sandbox);
+ isnot(result, null, "Should have an image");
+ is(result.tagName, "IMG", "Should have the right tag name");
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(doTest);
+ ]]>
+ </script>
+</window>
diff --git a/dom/tests/mochitest/chrome/test_sandbox_postMessage.html b/dom/tests/mochitest/chrome/test_sandbox_postMessage.html
new file mode 100644
index 0000000000..1e2dc4fa5c
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_sandbox_postMessage.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Testing postMessage from sandbox</title>
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+<script type="application/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function doTest() {
+ var sandbox = Cu.Sandbox("http://mochi.test:8888/", { wantXrays: true });
+ var win = window.frames.sameDomain;
+ sandbox.win = win;
+ sandbox.is = is;
+ sandbox.done = SimpleTest.finish;
+
+ result = Cu.evalInSandbox('var data = {some:"data"};'
+ +'win.addEventListener("message", receiveMessage, false);'
+ +'function receiveMessage(event)'
+ +'{'
+ +' is(JSON.stringify(event.data), JSON.stringify(data), "Received the expected message data");'
+ +' done();'
+ +'}'
+ +'win.postMessage(data, "*")'
+ , sandbox);
+ }
+
+ addLoadEvent(doTest);
+</script>
+</head>
+<body>
+<iframe src="http://mochi.test:8888/"
+ id="sameDomain" name="sameDomain">
+</iframe>
+</body>
+</html>
+
diff --git a/dom/tests/mochitest/chrome/test_selectAtPoint.html b/dom/tests/mochitest/chrome/test_selectAtPoint.html
new file mode 100644
index 0000000000..a4865b5125
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_selectAtPoint.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>nsIDOMWindowUtils::selectAtPoint test</title>
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+<script type="application/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function done() {
+ testwindow.close();
+ SimpleTest.finish();
+ }
+ var testwindow = window.open("selectAtPoint.html", '_new', 'width=800,height=800');
+</script>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</body>
+</html>
+
diff --git a/dom/tests/mochitest/chrome/test_sizemode_attribute.xhtml b/dom/tests/mochitest/chrome/test_sizemode_attribute.xhtml
new file mode 100644
index 0000000000..58685531c5
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_sizemode_attribute.xhtml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+<!--
+ Test for the sizemode attribute
+ -->
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ sizemode="fullscreen">
+
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<script>
+SimpleTest.waitForExplicitFinish();
+
+newwindow = window.browsingContext.topChromeWindow.openDialog("sizemode_attribute.xhtml", "_blank","chrome,resizable=yes", window);
+
+function done() {
+ newwindow.close();
+ SimpleTest.finish();
+}
+
+</script>
+<body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px;"/>
+
+</window>
diff --git a/dom/tests/mochitest/chrome/test_subscript_bindings.xhtml b/dom/tests/mochitest/chrome/test_subscript_bindings.xhtml
new file mode 100644
index 0000000000..2bb09c1167
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_subscript_bindings.xhtml
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=741267
+-->
+<window title="Mozilla Bug 741267"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+ <iframe id="t"></iframe>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=741267"
+ target="_blank">Mozilla Bug 741267</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+
+ /** Test for Bug 741267 **/
+ function doTest() {
+ // Resolve XMLHttpRequest on the chrome global
+ new XMLHttpRequest();
+
+ var loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader);
+ var context = { window: $("t").contentWindow };
+ var thrown = false;
+ try {
+ loader.loadSubScript(/.*\//.exec(window.location.href)[0] + "file_subscript_bindings.js", context);
+ } catch (e) {
+ thrown = true;
+ }
+ ok(!thrown, "'new window.XMLHttpRequest()' in a subscript shouldn't throw");
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(doTest);
+ ]]>
+ </script>
+</window>
diff --git a/dom/tests/mochitest/chrome/test_window_getRegionalPrefsLocales.html b/dom/tests/mochitest/chrome/test_window_getRegionalPrefsLocales.html
new file mode 100644
index 0000000000..581169e67b
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_window_getRegionalPrefsLocales.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1337234
+-->
+<head>
+ <title>Test for Bug 1337234</title>
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1337234">Mozilla Bug 1337234</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<script>
+
+const localeService =
+ Cc["@mozilla.org/intl/localeservice;1"].getService(Ci.mozILocaleService);
+
+let rpLocales = localeService.negotiateLanguages(window.getRegionalPrefsLocales(),
+ localeService.availableLocales);
+
+ok(rpLocales.length, "getRegionalPrefsLocales returns at least one locale.");
+is(rpLocales[0], "en-US", "The first regional prefs locale should resolve to en-US.");
+
+</script>
+</body>
+</html>
diff --git a/dom/tests/mochitest/chrome/test_xray_event_constructor.xhtml b/dom/tests/mochitest/chrome/test_xray_event_constructor.xhtml
new file mode 100644
index 0000000000..c26bfa56a6
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_xray_event_constructor.xhtml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=861493
+-->
+<window title="Mozilla Bug 861493"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+ <iframe id="t" type="content"></iframe>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=861493"
+ target="_blank">Mozilla Bug 861493</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ /** Test for Bug 861493 **/
+ SimpleTest.waitForExplicitFinish();
+
+ addLoadEvent(function() {
+ ok(Cu.isXrayWrapper($("t").contentWindow),
+ "Should have xray");
+ var e = new ($("t").contentWindow).Event("test", { bubbles: true });
+ is(e.bubbles, true, "Dictionary should have worked");
+ SimpleTest.finish();
+ })
+
+ ]]>
+ </script>
+</window>
diff --git a/dom/tests/mochitest/chrome/window_activation.xhtml b/dom/tests/mochitest/chrome/window_activation.xhtml
new file mode 100644
index 0000000000..c1cbd4791e
--- /dev/null
+++ b/dom/tests/mochitest/chrome/window_activation.xhtml
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="data:text/css,
+
+%23box {
+ background: blue;
+}
+
+%23box:-moz-window-inactive {
+ background: cyan;
+}
+
+" type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<box id="box" height="100"/>
+
+<script type="application/javascript"><![CDATA[
+
+var ok = window.arguments[0].ok;
+var complete = window.arguments[0].complete;
+var openerDoc = window.arguments[0].document;
+var SimpleTest = window.arguments[0].SimpleTest;
+
+SimpleTest.waitForFocus(function () {
+ ok(getComputedStyle(document.getElementById("box"), "").backgroundColor, "rgb(0, 0, 255)");
+ ok(getComputedStyle(openerDoc.getElementById("box"), "").backgroundColor, "rgb(0, 255, 255)");
+ window.arguments[0].focus();
+ ok(getComputedStyle(document.getElementById("box"), "").backgroundColor, "rgb(0, 255, 255)");
+ ok(getComputedStyle(openerDoc.getElementById("box"), "").backgroundColor, "rgb(0, 0, 255)");
+ complete();
+}, window);
+
+]]></script>
+
+</window>
diff --git a/dom/tests/mochitest/chrome/window_callback_wrapping.xhtml b/dom/tests/mochitest/chrome/window_callback_wrapping.xhtml
new file mode 100644
index 0000000000..6bb8176570
--- /dev/null
+++ b/dom/tests/mochitest/chrome/window_callback_wrapping.xhtml
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <browser type="content"
+ src="data:text/html,&lt;script&gt;var x = new XMLHttpRequest(); x.onreadystatechange = function() {}&lt;/script&gt;"/>
+
+ <script type="application/javascript"><![CDATA[
+ window.onload = function() {
+ var z = new XPCNativeWrapper(window.frames[0].wrappedJSObject.x).onreadystatechange;
+ var t = window.opener.SimpleTest;
+ t.ok(true, "Hey, we didn't crash");
+ window.close();
+ t.finish();
+ }
+ ]]>
+</script>
+
+</window>
diff --git a/dom/tests/mochitest/chrome/window_docshell_swap.xhtml b/dom/tests/mochitest/chrome/window_docshell_swap.xhtml
new file mode 100644
index 0000000000..3b849b64c8
--- /dev/null
+++ b/dom/tests/mochitest/chrome/window_docshell_swap.xhtml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<browser type="content" src="about:blank" id="browser"/>
+
+</window>
diff --git a/dom/tests/mochitest/chrome/window_focus.xhtml b/dom/tests/mochitest/chrome/window_focus.xhtml
new file mode 100644
index 0000000000..a2a1b5a2c3
--- /dev/null
+++ b/dom/tests/mochitest/chrome/window_focus.xhtml
@@ -0,0 +1,1699 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+ This test checks focus in various ways
+-->
+<window id="outer-document" title="Focus Test" width="600" height="550"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+
+<body xmlns="http://www.w3.org/1999/xhtml"/>
+
+ <script type="application/javascript"><![CDATA[
+
+const { BrowserTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/BrowserTestUtils.sys.mjs"
+);
+const { ContentTask } = ChromeUtils.import(
+ "resource://testing-common/ContentTask.jsm"
+);
+
+var fm = Cc["@mozilla.org/focus-manager;1"].
+ getService(Ci.nsIFocusManager);
+
+const kChildDocumentRootIndex = 13;
+const kBeforeTabboxIndex = 34;
+const kTabbableSteps = 38;
+const kFocusSteps = 26;
+const kNoFocusSteps = 7;
+const kOverflowElementIndex = 27;
+
+var gTestStarted = false;
+var gPartialTabbing = false;
+var gMoveToFocusFrame = false;
+var gLastFocus = null;
+var gLastFocusWindow = window;
+var gLastFocusMethod = -1;
+var gEvents = "";
+var gExpectedEvents = "";
+var gEventMatched = true;
+var gShowOutput = false;
+var gChildWindow = null;
+
+var gOldExpectedWindow = null;
+var gNewExpectedWindow = null;
+
+function is(l, r, n) { window.arguments[0].SimpleTest.is(l,r,n); }
+function ok(v, n) { window.arguments[0].SimpleTest.ok(v,n); }
+
+function initEvents(target)
+{
+ target.addEventListener("focus", eventOccured, true);
+ target.addEventListener("blur", eventOccured, true);
+ getTopWindow(target).addEventListener("activate", eventOccured, true);
+ getTopWindow(target).addEventListener("deactivate", eventOccured, true);
+}
+
+function eventOccured(event)
+{
+ // iframes should never receive focus or blur events directly
+ if (Element.isInstance(event.target) && event.target.localName == "iframe")
+ ok(false, "iframe " + event.type + "occured");
+
+ var id;
+ if (gOldExpectedWindow && event.type == "blur") {
+ if (Window.isInstance(event.target))
+ id = "frame-" + gOldExpectedWindow.document.documentElement.id + "-window";
+ else if (Document.isInstance(event.target))
+ id = "frame-" + gOldExpectedWindow.document.documentElement.id + "-document";
+ else
+ id = event.originalTarget.id;
+ }
+ else if (gNewExpectedWindow && event.type == "focus") {
+ if (Window.isInstance(event.target))
+ id = "frame-" + gNewExpectedWindow.document.documentElement.id + "-window";
+ else if (Document.isInstance(event.target))
+ id = "frame-" + gNewExpectedWindow.document.documentElement.id + "-document";
+ else
+ id = event.originalTarget.id;
+ }
+ else if (event.type == "activate" || event.type == "deactivate")
+ id = event.target.document.documentElement.id + "-window";
+ else if (Window.isInstance(event.target))
+ id = (event.target == window) ? "outer-window" : "child-window";
+ else if (Document.isInstance(event.target))
+ id = (event.target == document) ? "outer-document" : "child-document";
+ else
+ id = event.originalTarget.id;
+
+ if (gEvents)
+ gEvents += " ";
+ gEvents += event.type + ": " + id;
+}
+
+function expectFocusShift(callback, expectedWindow, expectedElement, focusChanged, testid)
+{
+ if (expectedWindow == null)
+ expectedWindow = expectedElement ?
+ expectedElement.ownerGlobal :
+ gLastFocusWindow;
+
+ var expectedEvents = "";
+ if (focusChanged) {
+ var id;
+ if (getTopWindow(gLastFocusWindow) != getTopWindow(expectedWindow)) {
+ id = getTopWindow(gLastFocusWindow).document.documentElement.id;
+ expectedEvents += "deactivate: " + id + "-window";
+ }
+
+ if (gLastFocus && gLastFocus.id != "t" + kChildDocumentRootIndex &&
+ (!gOldExpectedWindow || gOldExpectedWindow.document.documentElement != gLastFocus)) {
+ if (expectedEvents)
+ expectedEvents += " ";
+ if (!gOldExpectedWindow)
+ expectedEvents += "commandupdate: cu ";
+ expectedEvents += "blur: " + gLastFocus.id;
+ }
+
+ if (gLastFocusWindow && gLastFocusWindow != expectedWindow) {
+ if (!gMoveToFocusFrame) {
+ if (gOldExpectedWindow)
+ id = "frame-" + gOldExpectedWindow.document.documentElement.id;
+ else
+ id = (gLastFocusWindow == window) ? "outer" : "child";
+ if (expectedEvents)
+ expectedEvents += " ";
+ expectedEvents += "blur: " + id + "-document " +
+ "blur: " + id + "-window";
+ }
+ }
+
+ if (getTopWindow(gLastFocusWindow) != getTopWindow(expectedWindow)) {
+ id = getTopWindow(expectedWindow).document.documentElement.id;
+ if (expectedEvents)
+ expectedEvents += " ";
+ expectedEvents += "activate: " + id + "-window";
+ }
+
+ if (expectedWindow && gLastFocusWindow != expectedWindow) {
+ if (gNewExpectedWindow)
+ id = "frame-" + gNewExpectedWindow.document.documentElement.id;
+ else
+ id = (expectedWindow == window) ? "outer" : "child";
+ if (expectedEvents)
+ expectedEvents += " ";
+ expectedEvents += "focus: " + id + "-document " +
+ "focus: " + id + "-window";
+ }
+
+ // for this test which fires a mouse event on a label, the document will
+ // be focused first and then the label code will focus the related
+ // control. This doesn't result in different focus events, but a command
+ // update will occur for the document and then a second command update will
+ // occur when the control is focused. However, this will only happen on
+ // platforms or controls where mouse clicks cause trigger focus.
+ if (testid == "mouse on html label with content inside" &&
+ mouseWillTriggerFocus(expectedElement)) {
+ expectedEvents += " commandupdate: cu";
+ }
+
+ if (expectedElement &&
+ (!gNewExpectedWindow || gNewExpectedWindow.document.documentElement != expectedElement)) {
+ if (!gNewExpectedWindow) {
+ if (expectedEvents)
+ expectedEvents += " ";
+ expectedEvents += "commandupdate: cu";
+ }
+ if (expectedElement.id != "t" + kChildDocumentRootIndex) {
+ if (expectedEvents)
+ expectedEvents += " ";
+ expectedEvents += "focus: " + expectedElement.id;
+ }
+ }
+ else if (expectedWindow && gLastFocusWindow != expectedWindow &&
+ !expectedElement) {
+ if (expectedEvents)
+ expectedEvents += " ";
+ expectedEvents += "commandupdate: cu";
+ }
+ }
+
+ gLastFocus = expectedElement;
+ gLastFocusWindow = expectedWindow;
+
+ callback();
+
+ compareEvents(expectedEvents, expectedWindow, expectedElement, testid);
+}
+
+function compareEvents(expectedEvents, expectedWindow, expectedElement, testid)
+{
+ if (!gShowOutput) {
+ gEvents = "";
+ return;
+ }
+
+ is(gEvents, expectedEvents, testid + " events");
+ gEvents = "";
+
+ var doc;
+ if (expectedWindow == window)
+ doc = "outer-document";
+ else if (expectedWindow == gChildWindow)
+ doc = "inner-document";
+ else if (gNewExpectedWindow)
+ doc = gNewExpectedWindow.document.body ? gNewExpectedWindow.document.body.id :
+ gNewExpectedWindow.document.documentElement.id;
+ else
+ doc = "other-document";
+
+ var focusedElement = fm.focusedElement;
+ is(focusedElement ? focusedElement.id : "none",
+ expectedElement ? expectedElement.id : "none", testid + " focusedElement");
+ is(fm.focusedWindow, expectedWindow, testid + " focusedWindow");
+ var focusedWindow = {};
+ is(fm.getFocusedElementForWindow(expectedWindow, false, focusedWindow),
+ expectedElement, testid + " getFocusedElementForWindow");
+ is(focusedWindow.value, expectedWindow, testid + " getFocusedElementForWindow frame");
+ is(expectedWindow.document.hasFocus(), true, testid + " hasFocus");
+ is(expectedWindow.document.activeElement ? expectedWindow.document.activeElement.id : "none",
+ expectedElement ? expectedElement.id : doc, testid + " activeElement");
+ var cdwindow = getTopWindow(expectedWindow);
+ if (cdwindow.document.commandDispatcher) {
+ is(cdwindow.document.commandDispatcher.focusedWindow, expectedWindow, testid + " commandDispatcher focusedWindow");
+ is(cdwindow.document.commandDispatcher.focusedElement, focusedElement, testid + " commandDispatcher focusedElement");
+ }
+
+ if (gLastFocusMethod != -1) {
+ is(fm.getLastFocusMethod(null), gLastFocusMethod, testid + " lastFocusMethod null");
+ is(fm.getLastFocusMethod(expectedWindow), gLastFocusMethod, testid + " lastFocusMethod window");
+ }
+
+ // the parent should have the iframe focused
+ if (doc == "inner-document") {
+ is(document.hasFocus(), true, testid + " hasFocus");
+ is(fm.getFocusedElementForWindow(window, false, focusedWindow),
+ $("childframe"), testid + " getFocusedElementForWindow for parent");
+ is(focusedWindow.value, window, testid + " getFocusedElementForWindow for parent frame");
+ is(fm.getFocusedElementForWindow(window, true, focusedWindow),
+ expectedElement, testid + " getFocusedElementForWindow deep for parent");
+ is(focusedWindow.value, gChildWindow, testid + " getFocusedElementForWindow deep for parent frame");
+ is(document.activeElement.id, "childframe", testid + " activeElement for parent");
+ }
+
+ // compare the selection for the child window. Skip mouse tests as the caret
+ // is adjusted by the selection code for mouse clicks, and not the focus code.
+ if (expectedWindow == window) {
+ var selection = window.getSelection();
+ ok(selection.focusNode == null && selection.focusOffset == 0 &&
+ selection.anchorNode == null && selection.anchorOffset == 0, testid + " selection");
+ }
+ else if ((expectedWindow == gChildWindow) && !testid.indexOf("mouse") == -1) {
+ checkSelection(expectedElement, testid);
+ }
+}
+
+function checkSelection(node, testid)
+{
+ var selection = gChildWindow.getSelection();
+
+ var range = gChildWindow.document.createRange();
+ range.selectNodeContents(node);
+ if (!node.firstChild || node.localName == "input" ||
+ node.localName == "select" || node.localName == "button") {
+ range.setStartBefore(node);
+ range.setEndBefore(node);
+ }
+
+ if (node.firstChild)
+ range.setEnd(range.startContainer, range.startOffset);
+
+ is(selection.focusNode, range.startContainer, testid + " selection focusNode");
+ is(selection.focusOffset, range.startOffset, testid + " selection focusOffset");
+ is(selection.anchorNode, range.endContainer, testid + " selection anchorNode");
+ is(selection.anchorOffset, range.endOffset, testid + " selection anchorOffset");
+}
+
+function getTopWindow(win)
+{
+ return win.browsingContext.topChromeWindow;
+}
+
+function mouseWillTriggerFocus(element)
+{
+ if (!element) {
+ return false;
+ }
+
+ if (SpecialPowers.getIntPref("accessibility.mouse_focuses_formcontrol") == 1) {
+ // This is a chrome document, so we'll only trigger focus with the mouse if the value of the pref is 1.
+ return true;
+ }
+
+ if (element.namespaceURI == "http://www.w3.org/1999/xhtml") {
+ // links are special. They can be focused but show no focus ring
+ if (element.localName == "a" || element.localName == "div" ||
+ element.localName == "select" ||
+ element.localName == "input" && (element.type == "text" ||
+ element.type == "password")) {
+ return true;
+ }
+ } else if (element.localName == "richlistbox") {
+ return true;
+ }
+
+ return false;
+}
+
+function mouseOnElement(element, expectedElement, focusChanged, testid)
+{
+ var expectedWindow = (element.ownerGlobal == gChildWindow) ? gChildWindow : window;
+ // on Mac, form elements are not focused when clicking, except for lists and inputs.
+ var noFocusOnMouse = !mouseWillTriggerFocus(element)
+
+ if (noFocusOnMouse) {
+ // no focus so the last focus method will be 0
+ gLastFocusMethod = 0;
+ expectFocusShift(() => synthesizeMouse(element, 4, 4, { }, element.ownerGlobal),
+ expectedWindow, null, true, testid);
+ gLastFocusMethod = fm.FLAG_BYMOUSE;
+ }
+ else {
+ expectFocusShift(() => synthesizeMouse(element, 4, 4, { }, element.ownerGlobal),
+ element.ownerGlobal,
+ expectedElement, focusChanged, testid);
+ }
+}
+
+function done()
+{
+ var opener = window.arguments[0];
+ window.close();
+ window.arguments[0].SimpleTest.finish();
+}
+
+var pressTab = () => synthesizeKey("KEY_Tab");
+
+function setFocusTo(id, fwindow)
+{
+ gLastFocus = getById(id);
+ gLastFocusWindow = fwindow;
+ if (gLastFocus)
+ gLastFocus.focus();
+ else
+ fm.clearFocus(fwindow);
+ gEvents = "";
+}
+
+function getById(id)
+{
+ if (gNewExpectedWindow)
+ return gNewExpectedWindow.document.getElementById(id);
+ var element = $(id);
+ if (!element)
+ element = $("childframe").contentDocument.getElementById(id);
+ return element;
+}
+
+function startTest()
+{
+ if (gTestStarted)
+ return;
+ gTestStarted = true;
+
+ gChildWindow = $("childframe").contentWindow;
+ gShowOutput = true;
+
+ // synthesize a mousemove over the image to ensure that the imagemap data is
+ // created. Otherwise, the special imagemap frames might not exist, and
+ // won't be focusable.
+ synthesizeMouse(getById("image"), 4, 4, { type: "mousemove" }, gChildWindow);
+
+ initEvents(window);
+
+ is(fm.activeWindow, window, "activeWindow");
+ is(gChildWindow.document.hasFocus(), false, " child document hasFocus");
+
+ // test to see if the Mac Full Keyboard Access setting is set. If t3 is
+ // focused after tab is pressed, then it is set to inputs and lists only.
+ // Otherwise, all elements are in the tab order.
+ pressTab();
+
+ if (fm.focusedElement.id == "t3")
+ gPartialTabbing = true;
+ else
+ is(fm.focusedElement.id, "t1", "initial tab key");
+
+ is(fm.getLastFocusMethod(null), fm.FLAG_BYKEY, "last focus method null start");
+ is(fm.getLastFocusMethod(window), fm.FLAG_BYKEY, "last focus method window start");
+
+ fm.clearFocus(window);
+ gEvents = "";
+
+ gLastFocusMethod = fm.FLAG_BYKEY;
+ if (gPartialTabbing) {
+ var partialTabList = ["t3", "t5", "t9", "t10", "t11", "t12", "t13", "t14", "t15",
+ "t16", "t19", "t20", "t21", "t22", "t26", "t27", "t28", "t29", "t30"];
+ for (var idx = 0; idx < partialTabList.length; idx++) {
+ expectFocusShift(pressTab, null, getById(partialTabList[idx]), true, "partial tab key " + partialTabList[idx]);
+ }
+ setFocusTo("last", window);
+ expectFocusShift(pressTab, null, getById(partialTabList[0]), true, "partial tab key wrap to start");
+ expectFocusShift(() => synthesizeKey("KEY_Tab", {shiftKey: true}),
+ null, getById("last"), true, "partial shift tab key wrap to end");
+ for (var idx = partialTabList.length - 1; idx >= 0; idx--) {
+ expectFocusShift(() => synthesizeKey("KEY_Tab", {shiftKey: true}),
+ null, getById(partialTabList[idx]), true, "partial tab key " + partialTabList[idx]);
+ }
+ }
+ else {
+ // TAB key
+ for (var idx = 1; idx <= kTabbableSteps; idx++) {
+ expectFocusShift(pressTab, null, getById("t" + idx), true, "tab key t" + idx);
+ }
+
+ // wrapping around at end with TAB key
+ setFocusTo("last", window);
+ expectFocusShift(pressTab, null, getById("t1"), true, "tab key wrap to start");
+ expectFocusShift(() => synthesizeKey("KEY_Tab", {shiftKey: true}),
+ null, getById("last"), true, "shift tab key wrap to end");
+
+ // Shift+TAB key
+ setFocusTo("o5", window);
+ for (idx = kTabbableSteps; idx > 0; idx--) {
+ expectFocusShift(() => synthesizeKey("KEY_Tab", {shiftKey: true}),
+ null, getById("t" + idx), true, "shift tab key t" + idx);
+ }
+ }
+
+ var t19 = getById("t19");
+ is(t19.selectionStart, 0, "input focused from tab key selectionStart");
+ is(t19.selectionEnd, 5, "input focused from tab key selectionEnd");
+ t19.setSelectionRange(0, 0);
+
+ gLastFocusMethod = 0;
+ var selectFired = false;
+ function selectListener() { selectFired = true; }
+ t19.addEventListener("select", selectListener, false);
+ expectFocusShift(() => t19.select(),
+ null, getById("t" + 19), true, "input.select()");
+ t19.removeEventListener("select", selectListener, false);
+ ok(!selectFired, "select event does not fire asynchronously for input");
+
+ // mouse clicking
+ gLastFocusMethod = fm.FLAG_BYMOUSE;
+ for (idx = kTabbableSteps; idx >= 1; idx--) {
+ // skip the document root and the overflow element
+ if (idx == kChildDocumentRootIndex || idx == kOverflowElementIndex)
+ continue;
+ if ((navigator.platform.indexOf("Mac") == 0) && (idx == kBeforeTabboxIndex + 1))
+ continue;
+
+ var element = getById("t" + idx);
+ // skip area elements, as getBoundingClientRect doesn't return their actual coordinates
+ if (element.localName == "area")
+ continue;
+
+ mouseOnElement(element, element, true, "mouse on element t" + idx);
+ var expectedWindow = (element.ownerGlobal == gChildWindow) ? gChildWindow : window;
+ if (element.localName == "richlistbox" && expectedWindow == window &&
+ navigator.platform.indexOf("Mac") == 0) {
+ // after focusing a listbox on Mac, clear the focus before continuing.
+ setFocusTo(null, window);
+ }
+ }
+
+ ok(t19.selectionStart == t19.selectionEnd, "input focused from mouse selection");
+
+ // mouse clicking on elements that are not tabbable
+ for (idx = 1; idx <= kFocusSteps; idx++) {
+ var element = getById("o" + (idx % 2 ? idx : idx - 1));
+
+ mouseOnElement(element, element, idx % 2,
+ "mouse on non-tabbable element o" + idx);
+ }
+
+ // mouse clicking on elements that are not tabbable and have user-focus: none
+ // or are not focusable for other reasons (for instance, being disabled)
+ // These elements will clear the focus when clicked.
+ for (idx = 1; idx <= kNoFocusSteps; idx++) {
+ var element = getById("n" + idx);
+ gLastFocusMethod = idx % 2 ? 0 : fm.FLAG_BYMOUSE;
+
+ mouseOnElement(element, idx % 2 ? null: element, true, "mouse on unfocusable element n" + idx);
+ }
+
+ if (idx == kOverflowElementIndex) {
+ gLastFocusMethod = fm.FLAG_BYMOUSE;
+ var element = getById("t" + idx);
+ expectFocusShift(() => synthesizeMouse(element, 4, 4, { }, element.ownerGlobal),
+ window, null, true, "mouse on scrollable element");
+ }
+
+ // focus() method
+ gLastFocusMethod = fm.FLAG_BYJS;
+ for (idx = kTabbableSteps; idx >= 1; idx--) {
+ if ((navigator.platform.indexOf("Mac") == 0) && (idx == kBeforeTabboxIndex + 1))
+ continue;
+ expectFocusShift(() => getById("t" + idx).focus(),
+ null, getById("t" + idx), true, "focus method on element t" + idx);
+ }
+
+ $("t1").focus();
+ ok(gEvents === "", "focusing element that is already focused");
+
+ $("t2").blur();
+ $("t7").blur();
+ ok(gEvents === "", "blurring element that is not focused");
+ is(document.activeElement, $("t1"), "old element still focused after blur() on another element");
+
+ // focus() method on elements that are not tabbable
+ for (idx = 1; idx <= kFocusSteps; idx++) {
+ var expected = getById("o" + (idx % 2 ? idx : idx - 1));
+ expectFocusShift(() => getById("o" + idx).focus(),
+ expected.ownerGlobal,
+ expected, idx % 2, "focus method on non-tabbable element o" + idx);
+ }
+
+ // focus() method on elements that are not tabbable and have user-focus: none
+ // or are not focusable for other reasons (for instance, being disabled)
+ for (idx = 1; idx <= kNoFocusSteps; idx++) {
+ var expected = getById("o" + (idx % 2 ? idx : idx - 1));
+ expectFocusShift(() => getById("o" + idx).focus(),
+ expected.ownerGlobal,
+ expected, idx % 2, "focus method on unfocusable element n" + idx);
+ }
+
+ // the focus() method on the legend element should focus the legend if it is
+ // focusable, or the first element after the legend if it is not focusable.
+ if (!gPartialTabbing) {
+ gLastFocusMethod = fm.FLAG_BYJS;
+ var legend = getById("legend");
+ expectFocusShift(() => legend.focus(),
+ null, getById("t28"), true, "focus method on unfocusable legend");
+ legend.tabIndex = "0";
+ expectFocusShift(() => legend.focus(),
+ null, getById("legend"), true, "focus method on focusable legend");
+ legend.tabIndex = "-1";
+ }
+
+ var accessKeyDetails = (navigator.platform.includes("Mac")) ?
+ { ctrlKey : true } : { altKey : true };
+
+ // test accesskeys
+ var keys = ["t26", "t19", "t22", "t29", "t15", "t17", "n6",
+ "t4", "o1", "o9", "n4"];
+ for (var k = 0; k < keys.length; k++) {
+ var key = String.fromCharCode(65 + k);
+
+ // accesskeys D and G are for labels so get redirected
+ gLastFocusMethod = (key == "D" || key == "G") ? fm.FLAG_BYMOVEFOCUS : fm.FLAG_BYKEY;
+
+ // on Windows and Linux, the shift key must be pressed for content area access keys
+ // and on Mac, the alt key must be pressed for content area access keys
+ var isContent = (getById(keys[k]).ownerGlobal == gChildWindow);
+ if (!navigator.platform.includes("Mac")) {
+ accessKeyDetails.shiftKey = isContent;
+ } else {
+ accessKeyDetails.altKey = isContent;
+ }
+
+ expectFocusShift(() => synthesizeKey(key, accessKeyDetails),
+ null, getById(keys[k]), true, "accesskey " + key);
+ }
+
+ // clicking on the labels
+ gLastFocusMethod = fm.FLAG_BYMOVEFOCUS | fm.FLAG_BYMOUSE;
+ mouseOnElement(getById("ad"), getById("t29"), true, "mouse on html label with content inside");
+ mouseOnElement(getById("ag"), getById("n6"), true, "mouse on html label with for attribute");
+ gLastFocusMethod = fm.FLAG_BYJS;
+ expectFocusShift(() => synthesizeMouse(getById("aj"), 2, 2, { }),
+ null, getById("o9"), true, "mouse on xul label with content inside");
+ expectFocusShift(() => synthesizeMouse(getById("ak"), 2, 2, { }),
+ null, getById("n4"), true, "mouse on xul label with control attribute");
+
+ // test accesskeys that shouldn't work
+ k = "o".charCodeAt(0);
+ gLastFocusMethod = fm.FLAG_BYJS;
+ while (k++ < "v".charCodeAt(0)) {
+ var key = String.fromCharCode(k);
+ expectFocusShift(() => synthesizeKey(key, accessKeyDetails),
+ window, getById("n4"), false, "non accesskey " + key);
+ }
+ gLastFocusMethod = -1;
+
+ // should focus the for element when using the focus method on a label as well
+ expectFocusShift(() => getById("ad").focus(),
+ null, getById("t29"), true, "mouse on html label using focus method");
+
+ // make sure that the text is selected when clicking a label associated with an input
+ getById("ag").htmlFor = "t19";
+ expectFocusShift(() => synthesizeMouse(getById("ag"), 2, 2, { }, gChildWindow),
+ null, getById("t19"), true, "mouse on html label with for attribute changed");
+ is(t19.selectionStart, 0, "input focused from label, selectionStart");
+ is(t19.selectionEnd, 5, "input focused from label, selectionEnd");
+
+ // switch to another panel in a tabbox and ensure that tabbing moves between
+ // elements on the new panel.
+ $("tabbox").selectedIndex = 1;
+ expectFocusShift(() => getById("t" + kBeforeTabboxIndex).focus(),
+ null, getById("t" + kBeforeTabboxIndex), true, "focus method on element before tabbox");
+
+ if (!gPartialTabbing) {
+ expectFocusShift(pressTab, null, getById("tab2"), true, "focus method on tab");
+ expectFocusShift(pressTab, null, getById("htab1"), true, "tab key switch tabpanel 1");
+ expectFocusShift(pressTab, null, getById("htab2"), true, "tab key switch tabpanel 2");
+ expectFocusShift(pressTab, null, getById("t" + (kBeforeTabboxIndex + 4)), true, "tab key switch tabpanel 3");
+ }
+ $("tabbox").selectedIndex = 0;
+
+ // ---- the following checks when the focus changes during a blur or focus event ----
+
+ var o5 = $("o5");
+ var o9 = $("o9");
+ var t3 = $("t3");
+ var t17 = getById("t17");
+ var t19 = getById("t19");
+ var shiftFocusParentDocument = () => o9.focus();
+ var shiftFocusChildDocument = () => t17.focus();
+
+ var trapBlur = function (element, eventListener, blurFunction)
+ {
+ element.focus();
+ gEvents = "";
+ element.addEventListener("blur", eventListener, false);
+ blurFunction();
+ element.removeEventListener("blur", eventListener, false);
+ }
+
+ var functions = [
+ element => element.focus(),
+ element => synthesizeMouse(element, 4, 4, { }, element.ownerGlobal)
+ ];
+
+ // first, check cases where the focus is adjusted during the blur event. Iterate twice,
+ // once with the focus method and then focusing by mouse clicking
+ for (var l = 0; l < 2; l++) {
+ var adjustFocus = functions[l];
+ var mod = (l == 1) ? " with mouse" : "";
+
+ // an attempt is made to switch the focus from one element (o5) to another
+ // element (t3) within the same document, yet the focus is shifted to a
+ // third element (o9) in the same document during the blur event for the
+ // first element.
+ trapBlur(o5, shiftFocusParentDocument, () => adjustFocus(t3));
+ compareEvents("commandupdate: cu blur: o5 commandupdate: cu focus: o9",
+ window, o9, "change focus to sibling during element blur, attempted sibling" + mod);
+
+ // similar, but the third element (t17) is in a child document
+ trapBlur(o9, shiftFocusChildDocument, () => adjustFocus(t3));
+ compareEvents("commandupdate: cu blur: o9 blur: outer-document blur: outer-window " +
+ "focus: child-document focus: child-window commandupdate: cu focus: t17",
+ gChildWindow, t17, "change focus to child document during element blur, attempted sibling" + mod);
+
+ // similar, but an attempt to switch focus within the same document, but the
+ // third element (t17) is in a parent document
+ trapBlur(t17, shiftFocusParentDocument, () => adjustFocus(t19));
+ compareEvents("commandupdate: cu blur: t17 blur: child-document blur: child-window " +
+ "focus: outer-document focus: outer-window commandupdate: cu focus: o9",
+ window, o9, "change focus to parent document during element blur, attempted sibling" + mod);
+
+ // similar, but blur is called instead of switching focus
+ trapBlur(t3, shiftFocusParentDocument, () => t3.blur());
+ compareEvents("commandupdate: cu blur: t3 commandupdate: cu focus: o9",
+ window, o9, "change focus to same document during clear focus" + mod);
+
+ // check when an element in the same document is focused during the
+ // element's blur event, but an attempt was made to focus an element in the
+ // child document. In this case, the focus in the parent document should be
+ // what was set during the blur event, but the actual focus should still
+ // move to the child document.
+ trapBlur(t3, shiftFocusParentDocument, () => adjustFocus(t17));
+ compareEvents("commandupdate: cu blur: t3 commandupdate: cu focus: o9 " +
+ "blur: outer-document blur: outer-window " +
+ "focus: child-document focus: child-window commandupdate: cu focus: t17",
+ gChildWindow, t17, "change focus to sibling during element blur, attempted child" + mod);
+ is(fm.getFocusedElementForWindow(window, false, {}), $("childframe"),
+ "change focus to sibling during element blur, attempted child, focused in parent" + mod);
+
+ // similar, but with a parent
+ trapBlur(t19, shiftFocusChildDocument, () => adjustFocus(t3));
+ compareEvents("commandupdate: cu blur: t19 commandupdate: cu focus: t17 " +
+ "blur: child-document blur: child-window " +
+ "focus: outer-document focus: outer-window commandupdate: cu focus: t3",
+ window, t3, "change focus to sibling during element blur, attempted parent" + mod);
+ is(fm.getFocusedElementForWindow(gChildWindow, false, {}), t17,
+ "change focus to sibling during element blur, attempted child, focused in child" + mod);
+
+ // similar, with a child, but the blur event focuses a child element also
+ trapBlur(t3, shiftFocusChildDocument, () => adjustFocus(t19));
+ compareEvents("commandupdate: cu blur: t3 blur: outer-document blur: outer-window " +
+ "focus: child-document focus: child-window commandupdate: cu focus: t17",
+ gChildWindow, t17, "change focus to child during element blur, attempted child" + mod);
+
+ // similar, with a parent, where the blur event focuses a parent element also
+ trapBlur(t17, shiftFocusParentDocument, () => adjustFocus(t3));
+ compareEvents("commandupdate: cu blur: t17 blur: child-document blur: child-window " +
+ "focus: outer-document focus: outer-window commandupdate: cu focus: o9",
+ window, o9, "change focus to parent during element blur, attempted parent" + mod);
+ }
+
+ var trapFocus = function (element, eventListener)
+ {
+ element.addEventListener("focus", eventListener, false);
+ element.focus();
+ element.removeEventListener("focus", eventListener, false);
+ }
+
+ fm.clearFocus(window);
+ gEvents = "";
+
+ // next, check cases where the focus is adjusted during the focus event
+
+ // switch focus to an element in the same document
+ trapFocus(o5, shiftFocusParentDocument);
+ compareEvents("commandupdate: cu focus: o5 commandupdate: cu blur: o5 commandupdate: cu focus: o9",
+ window, o9, "change focus to sibling during element focus");
+
+ // similar, but the new element (t17) is in a child document
+ trapFocus(o5, shiftFocusChildDocument);
+ compareEvents("commandupdate: cu blur: o9 " +
+ "commandupdate: cu focus: o5 commandupdate: cu blur: o5 " +
+ "blur: outer-document blur: outer-window " +
+ "focus: child-document focus: child-window commandupdate: cu focus: t17",
+ gChildWindow, t17, "change focus to child document during element focus");
+
+ // similar, but the new element (o9) is in a parent document.
+ trapFocus(t19, shiftFocusParentDocument);
+ compareEvents("commandupdate: cu blur: t17 " +
+ "commandupdate: cu focus: t19 commandupdate: cu blur: t19 " +
+ "blur: child-document blur: child-window " +
+ "focus: outer-document focus: outer-window commandupdate: cu focus: o9",
+ window, o9, "change focus to parent document during element focus");
+
+ // clear the focus during the focus event
+ trapFocus(t3, () => fm.clearFocus(window));
+ compareEvents("commandupdate: cu blur: o9 commandupdate: cu focus: t3 commandupdate: cu blur: t3",
+ window, null, "clear focus during focus event");
+
+ if (!gPartialTabbing)
+ doCommandDispatcherTests();
+
+ testMoveFocus();
+
+ doRemoveTests();
+
+ // tests various focus manager apis for null checks
+ var exh = false;
+ try {
+ fm.clearFocus(null);
+ }
+ catch (ex) { exh = true; }
+ is(exh, true, "clearFocus with null window causes exception");
+
+ var exh = false;
+ try {
+ fm.getFocusedElementForWindow(null, false, focusedWindow);
+ }
+ catch (ex) { exh = true; }
+ is(exh, true, "getFocusedElementForWindow with null window causes exception");
+
+ // just make sure that this doesn't crash
+ fm.moveCaretToFocus(null);
+
+ // ---- tests for the FLAG_NOSWITCHFRAME flag
+ getById("o5").focus();
+ gLastFocusMethod = fm.FLAG_BYJS;
+ gEvents = "";
+ // focus is being shifted in a child, so the focus should not change
+ expectFocusShift(() => fm.setFocus(getById("t20"), fm.FLAG_NOSWITCHFRAME),
+ window, getById("o5"), false, "no switch frame focus to child");
+ setFocusTo("t20", gChildWindow);
+
+ gLastFocusMethod = 0;
+
+ // here, however, focus is being shifted in a parent, which will have to blur
+ // the child, so the focus will always change
+ expectFocusShift(() => fm.setFocus(getById("o5"), fm.FLAG_NOSWITCHFRAME),
+ window, getById("o5"), true, "no switch frame focus to parent");
+
+ expectFocusShift(() => fm.setFocus(getById("t1"), fm.FLAG_NOSWITCHFRAME),
+ window, getById("t1"), true, "no switch frame focus to same window");
+
+ // ---- tests for focus and scrolling into view ----
+ var inscroll = getById("inscroll");
+ inscroll.tabIndex = 0;
+ is(inscroll.parentNode.scrollTop, 0, "scroll position before focus");
+ inscroll.focus();
+ ok(inscroll.parentNode.scrollTop > 5, "scroll position after focus");
+ inscroll.parentNode.scrollTop = 0;
+ fm.setFocus(inscroll, fm.FLAG_NOSCROLL);
+ is(inscroll.parentNode.scrollTop, 0, "scroll position after noscroll focus");
+
+ getById("t9").focus();
+ getById("inpopup1").focus();
+ is(fm.focusedElement, getById("t9"), "focus in closed popup");
+
+ // ---- tests to check if tabbing out of a input works
+
+ setFocusTo("t1", window);
+
+ var input1 = document.createElement("input");
+ $("innerbox").appendChild(input1);
+
+ var input2 = document.createElement("input");
+ $("innerbox").appendChild(input2);
+
+ gLastFocusMethod = fm.FLAG_BYJS;
+ expectFocusShift(() => input2.focus(),
+ null, input2, true, "focus on input");
+ gLastFocusMethod = fm.FLAG_BYKEY;
+ expectFocusShift(() => synthesizeKey("KEY_Tab", {shiftKey: true}),
+ null, input1, true, "shift+tab on input");
+
+ input1.tabIndex = 2;
+ input2.tabIndex = 2;
+ gLastFocusMethod = fm.FLAG_BYJS;
+ expectFocusShift(() => input2.focus(),
+ null, input2, true, "focus on input with tabindex set");
+ gLastFocusMethod = fm.FLAG_BYKEY;
+ expectFocusShift(() => synthesizeKey("KEY_Tab", {shiftKey: true}),
+ null, input1, true, "shift+tab on input with tabindex set");
+
+ // ---- test to check that refocusing an element during a blur event doesn't succeed
+
+ var t1 = getById("t1");
+ t1.addEventListener("blur", () => t1.focus(), true);
+ t1.focus();
+ var t3 = getById("t3");
+ synthesizeMouse(t3, 2, 2, { });
+ is(fm.focusedElement, t3, "focus during blur");
+
+ setFocusTo("t9", window);
+ gLastFocusMethod = -1;
+ window.openDialog("focus_window2.xhtml", "_blank", "chrome", otherWindowFocused);
+}
+
+function doCommandDispatcherTests()
+{
+ var t19 = getById("t19");
+ t19.focus();
+ gLastFocusWindow = gChildWindow;
+ gLastFocus = t19;
+ gEvents = "";
+
+ expectFocusShift(() => document.commandDispatcher.focusedElement = getById("o9"),
+ null, getById("o9"), true, "command dispatcher set focusedElement");
+ expectFocusShift(() => document.commandDispatcher.advanceFocus(),
+ null, getById("o13"), true, "command dispatcher advanceFocus");
+ expectFocusShift(() => document.commandDispatcher.rewindFocus(),
+ null, getById("o9"), true, "command dispatcher rewindFocus");
+ expectFocusShift(() => document.commandDispatcher.focusedElement = null,
+ null, null, true, "command dispatcher set focusedElement to null");
+ expectFocusShift(() => document.commandDispatcher.focusedWindow = gChildWindow,
+ null, getById("t19"), true, "command dispatcher set focusedElement to null");
+ expectFocusShift(() => document.commandDispatcher.focusedElement = null,
+ gChildWindow, null, true, "command dispatcher set focusedElement to null in child");
+ expectFocusShift(() => document.commandDispatcher.advanceFocusIntoSubtree(getById("t19")),
+ null, getById("t20"), true, "command dispatcher advanceFocusIntoSubtree child");
+ expectFocusShift(() => document.commandDispatcher.advanceFocusIntoSubtree(null),
+ null, getById("t21"), true, "command dispatcher advanceFocusIntoSubtree null child");
+ expectFocusShift(() => document.commandDispatcher.advanceFocusIntoSubtree(getById("o9").parentNode),
+ null, getById("o9"), true, "command dispatcher advanceFocusIntoSubtree parent");
+}
+
+function doRemoveTests()
+{
+ // next, some tests which remove elements
+ var t19 = getById("t19");
+ t19.focus();
+ t19.remove();
+
+ is(fm.focusedElement, null, "removed element focusedElement");
+ is(fm.focusedWindow, gChildWindow, "removed element focusedWindow");
+ is(gChildWindow.document.hasFocus(), true, "removed element hasFocus");
+ is(gChildWindow.document.activeElement, getById("inner-document"), "removed element activeElement");
+
+ getById("t15").focus();
+ var abs = getById("abs");
+ abs.remove();
+
+ is(fm.focusedElement, null, "removed ancestor focusedElement");
+ is(fm.focusedWindow, gChildWindow, "removed ancestor focusedWindow");
+ is(gChildWindow.document.hasFocus(), true, "removed ancestor hasFocus");
+ is(gChildWindow.document.activeElement, getById("inner-document"), "removed ancestor activeElement");
+}
+
+// tests for the FocusManager moveFocus method
+function testMoveFocus()
+{
+ setFocusTo("t6", window);
+
+ // moving focus while an element is already focused
+ var newFocus;
+ gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
+ var expectedFirst = getById(gPartialTabbing ? "t3" : "t1");
+ expectFocusShift(() => newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FIRST, 0),
+ window, expectedFirst, true, "moveFocus to first null window null content");
+ is(newFocus, fm.focusedElement, "moveFocus to first null window null content return value");
+
+ expectFocusShift(() => newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_LAST, 0),
+ window, getById("last"), true, "moveFocus to last null window null content");
+ is(newFocus, fm.focusedElement, "moveFocus to last null window null content return value");
+
+ gLastFocusMethod = 0;
+ newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_ROOT, 0);
+ is(newFocus, null, "moveFocus to root null window null content return value");
+ is(fm.focusedWindow, window, "moveFocus to root null window null content focusedWindow");
+ is(fm.focusedElement, null, "moveFocus to root null window null content focusedElement");
+
+ // moving focus while no element is focused
+ fm.clearFocus(window);
+ gEvents = "";
+ gLastFocus = null;
+ gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
+ expectFocusShift(() => newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FIRST, 0),
+ window, expectedFirst, true, "moveFocus to first null window null content no focus");
+ is(newFocus, fm.focusedElement, "moveFocus to first null window null content no focus return value");
+ fm.clearFocus(window);
+ gEvents = "";
+ gLastFocus = null;
+ expectFocusShift(() => newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_LAST, 0),
+ window, getById("last"), true, "moveFocus to last null window null content no focus");
+ is(newFocus, fm.focusedElement, "moveFocus to last null window null content no focus return value");
+ fm.clearFocus(window);
+ gEvents = "";
+ gLastFocusMethod = 0;
+ newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_ROOT, 0);
+ is(newFocus, null, "moveFocus to root null window null content no focus return value");
+ is(fm.focusedWindow, window, "moveFocus to root null window null content no focus focusedWindow");
+ is(fm.focusedElement, null, "moveFocus to root null window null content no focus focusedElement");
+
+ // moving focus from a specified element
+ setFocusTo("t6", window);
+ gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
+ expectFocusShift(() => newFocus = fm.moveFocus(null, getById("specialroot"), fm.MOVEFOCUS_FIRST, 0),
+ window, getById("t3"), true, "moveFocus to first null window with content");
+// XXXndeakin P3 this doesn't work
+// expectFocusShift(() => newFocus = fm.moveFocus(null, getById("specialroot"), fm.MOVEFOCUS_LAST, 0),
+// window, getById("o3"), true, "moveFocus to last null window with content");
+
+ // move focus to first in child window
+ expectFocusShift(() => newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_FIRST, 0),
+ gChildWindow, getById("t" + (kChildDocumentRootIndex + 1)), true,
+ "moveFocus to first child window null content");
+ is(newFocus, getById("t" + (kChildDocumentRootIndex + 1)),
+ "moveFocus to first child window null content return value");
+
+ // move focus to last in child window
+ setFocusTo("t6", window);
+ var expectedLast = getById(gPartialTabbing ? "t30" : "t" + (kBeforeTabboxIndex - 1));
+ expectFocusShift(() => newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_LAST, 0),
+ gChildWindow, expectedLast, true,
+ "moveFocus to last child window null content");
+ is(newFocus, getById(expectedLast),
+ "moveFocus to last child window null content return value");
+
+ // move focus to root in child window
+ setFocusTo("t6", window);
+ var childroot = getById("t" + kChildDocumentRootIndex);
+ gLastFocusMethod = 0;
+ newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_ROOT, 0),
+ is(newFocus, childroot, "moveFocus to root child window null content return value");
+ is(fm.focusedWindow, gChildWindow, "moveFocus to root child window null content focusedWindow");
+ is(fm.focusedElement, childroot, "moveFocus to root child window null content focusedElement");
+
+ // MOVEFOCUS_CARET tests
+ getById("t20").focus();
+ gEvents = "";
+
+ var selection = gChildWindow.getSelection();
+ selection.removeAllRanges();
+
+ newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_CARET, 0);
+ is(newFocus, null, "move caret when at document root");
+ is(fm.focusedElement, null, "move caret when at document root");
+
+ var node = getById("t16").firstChild;
+ var range = gChildWindow.document.createRange();
+ range.setStart(node, 3);
+ range.setEnd(node, 3);
+ selection.addRange(range);
+
+ newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_CARET, 0);
+ is(newFocus, null, "move caret to non-link return value");
+ is(fm.focusedElement, null, "move caret to non-link");
+
+ var t25 = getById("t25");
+ var node = t25.firstChild;
+ range.setStart(node, 1);
+ range.setEnd(node, 1);
+ newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_CARET, 0);
+
+ is(newFocus, t25, "move caret to link return value");
+ is(fm.focusedElement, t25, "move caret to link focusedElement");
+
+ // enable caret browsing temporarily to test caret movement
+ var prefs = Cc["@mozilla.org/preferences-service;1"].
+ getService(Ci.nsIPrefBranch);
+ prefs.setBoolPref("accessibility.browsewithcaret", true);
+
+ synthesizeKey("KEY_ArrowLeft", {}, gChildWindow);
+ synthesizeKey("KEY_ArrowLeft", {}, gChildWindow);
+ is(fm.focusedElement, null, "move caret away from link");
+
+ synthesizeKey("KEY_ArrowLeft", {}, gChildWindow);
+ is(fm.focusedElement, getById("t24"), "move caret away onto link");
+
+ prefs.setBoolPref("accessibility.browsewithcaret", false);
+
+ // cases where focus in on a content node with no frame
+
+ if (!gPartialTabbing) {
+ getById("t24").blur();
+ gEvents = "";
+ gLastFocus = null;
+ gLastFocusWindow = gChildWindow;
+ gLastFocusMethod = fm.FLAG_BYKEY;
+
+ selection.selectAllChildren(getById("hiddenspan"));
+ expectFocusShift(() => synthesizeKey("KEY_Tab"),
+ gChildWindow, getById("t26"), true, "tab with selection on hidden content");
+
+ setFocusTo($("o15"), window);
+ $("o15").hidden = true;
+ document.documentElement.getBoundingClientRect(); // flush after hiding
+ expectFocusShift(() => synthesizeKey("KEY_Tab"),
+ window, $("o17"), true, "tab with focus on hidden content");
+
+ $("o17").hidden = true;
+ document.documentElement.getBoundingClientRect();
+ expectFocusShift(() => synthesizeKey("KEY_Tab", {shiftKey: true}),
+ window, $("o13"), true, "shift+tab with focus on hidden content");
+ }
+
+ // cases with selection in an <input>
+
+ var t19 = getById("t19");
+ t19.setSelectionRange(0, 0);
+ setFocusTo("t18", gChildWindow);
+
+ gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
+ expectFocusShift(() => newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FORWARD, 0),
+ gChildWindow, t19, true, "moveFocus to next input");
+ is(t19.selectionStart, 0, "input focused after moveFocus selectionStart");
+ is(t19.selectionEnd, 5, "input focused after moveFocus selectionEnd");
+
+ t19.setSelectionRange(0, 0);
+ setFocusTo("t18", gChildWindow);
+ gLastFocusMethod = fm.FLAG_BYKEY;
+ expectFocusShift(() => newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FORWARD, fm.FLAG_BYKEY),
+ gChildWindow, t19, true, "moveFocus to next input by key");
+ is(t19.selectionStart, 0, "input focused after moveFocus by key selectionStart");
+ is(t19.selectionEnd, 5, "input focused after moveFocus by key selectionEnd");
+}
+
+function otherWindowFocused(otherWindow)
+{
+ var expectedElement = getById("t9");
+
+ is(fm.activeWindow, otherWindow, "other activeWindow");
+ is(fm.focusedWindow, otherWindow, "other focusedWindow");
+ is(window.document.hasFocus(), false, "when lowered document hasFocus");
+ var focusedWindow = {};
+ is(fm.getFocusedElementForWindow(window, false, focusedWindow),
+ expectedElement, "when lowered getFocusedElementForWindow");
+ is(focusedWindow.value, window, "when lowered getFocusedElementForWindow frame");
+ is(document.activeElement.id, expectedElement.id, "when lowered activeElement");
+ is(window.document.commandDispatcher.focusedWindow, window, " commandDispatcher in other window focusedWindow");
+ is(window.document.commandDispatcher.focusedElement, expectedElement, " commandDispatcher in other window focusedElement");
+
+ compareEvents("deactivate: outer-document-window blur: t9 blur: outer-document blur: outer-window",
+ otherWindow, null, "other window opened");
+
+ otherWindow.document.getElementById("other").focus();
+
+ for (var idx = kTabbableSteps; idx >= 1; idx--) {
+ expectedElement = getById("t" + idx);
+ if (!expectedElement) // skip elements that were removed in doRemoveTests()
+ continue;
+ if ((navigator.platform.indexOf("Mac") == 0) && (idx == kBeforeTabboxIndex + 1))
+ continue;
+
+ expectedElement.focus();
+
+ is(fm.focusedElement.id, "other", "when lowered focusedElement t" + idx);
+ is(fm.focusedWindow, otherWindow, "when lowered focusedWindow t" + idx);
+
+ var checkWindow = expectedElement.ownerGlobal;
+ is(fm.getFocusedElementForWindow(checkWindow, false, {}).id, expectedElement.id,
+ "when lowered getFocusedElementForWindow t" + idx);
+ is(checkWindow.document.activeElement.id, expectedElement.id, "when lowered activeElement t" + idx);
+ if (checkWindow != window) {
+ is(fm.getFocusedElementForWindow(window, false, {}), $("childframe"),
+ "when lowered parent getFocusedElementForWindow t" + idx);
+ is(document.activeElement.id, "childframe",
+ "when lowered parent activeElement t" + idx);
+ }
+ }
+
+ gEvents = gEvents.replace(/commandupdate: cu\s?/g, "");
+ is(gEvents, "", "when lowered no events fired");
+
+ var other = otherWindow.document.getElementById("other");
+ other.focus();
+ is(fm.focusedElement, other, "focus method in second window");
+
+ otherWindow.close();
+
+ getById("n2").focus();
+
+ // next, check modal dialogs
+ // XXXndeakin Bug 621399 - the modal dialog test as well as later tests sometime fail
+ // on Windows 8 so just end the test here.
+ if (navigator.userAgent.includes("Windows NT 6.2")) {
+ done();
+ }
+ else {
+ window.openDialog("focus_window2.xhtml", "_blank", "chrome,modal", modalWindowOpened);
+ }
+}
+
+function modalWindowOpened(modalWindow)
+{
+ var elem = modalWindow.document.getElementById("other");
+ if (gPartialTabbing)
+ elem.focus();
+ else
+ synthesizeKey("KEY_Tab", {}, modalWindow);
+ is(fm.activeWindow, modalWindow, "modal activeWindow");
+ is(fm.focusedElement, elem, "modal focusedElement");
+
+ modalWindow.close();
+ SimpleTest.waitForFocus(modalWindowClosed);
+}
+
+function modalWindowClosed()
+{
+ is(fm.activeWindow, window, "modal window closed activeWindow");
+ is(fm.focusedElement, getById("n2"), "modal window closed focusedElement");
+
+ window.arguments[0].framesetWindowLoaded = framesetWindowLoaded;
+ window.arguments[0].open("focus_frameset.html", "_blank", "width=400,height=400,toolbar=no");
+}
+
+function framesetWindowLoaded(framesetWindow)
+{
+ gLastFocus = null;
+ gLastFocusWindow = framesetWindow;
+ gEvents = "";
+
+ is(fm.activeWindow, getTopWindow(framesetWindow), "frameset window active");
+ gOldExpectedWindow = getTopWindow(framesetWindow);
+
+ gMoveToFocusFrame = true;
+ for (var idx = 1; idx <= 8; idx++) {
+ gNewExpectedWindow = framesetWindow.frames[(idx - 1) >> 1];
+ if (idx % 2)
+ initEvents(gNewExpectedWindow);
+ expectFocusShift(() => synthesizeKey("KEY_Tab", {}, framesetWindow),
+ gNewExpectedWindow, getById("f" + idx), true, "frameset tab key f" + idx);
+ gMoveToFocusFrame = false;
+ gOldExpectedWindow = gNewExpectedWindow;
+ }
+
+ gNewExpectedWindow = framesetWindow.frames[0];
+ expectFocusShift(() => synthesizeKey("KEY_Tab", {}, framesetWindow),
+ gNewExpectedWindow, getById("f1"), true, "frameset tab key wrap to start");
+ gOldExpectedWindow = gNewExpectedWindow;
+ gNewExpectedWindow = framesetWindow.frames[3];
+ expectFocusShift(() => synthesizeKey("KEY_Tab", {shiftKey: true}, framesetWindow),
+ gNewExpectedWindow, getById("f8"), true, "frameset shift tab key wrap to end");
+
+ for (idx = 7; idx >= 1; idx--) {
+ gOldExpectedWindow = gNewExpectedWindow;
+ gNewExpectedWindow = framesetWindow.frames[(idx - 1) >> 1];
+ expectFocusShift(() => synthesizeKey("KEY_Tab", {shiftKey: true}, framesetWindow),
+ gNewExpectedWindow, getById("f" + idx), true, "frameset shift tab key f" + idx);
+ }
+
+ // document shifting
+ // XXXndeakin P3 ctrl+tab doesn't seem to be testable currently for some reason
+ gNewExpectedWindow = framesetWindow.frames[1];
+ expectFocusShift(() => synthesizeKey("KEY_F6", {ctrlKey: true}, framesetWindow),
+ gNewExpectedWindow, getById("f3"), true, "switch document forward with f6");
+ gOldExpectedWindow = gNewExpectedWindow;
+ gNewExpectedWindow = framesetWindow.frames[2];
+ expectFocusShift(() => synthesizeKey("KEY_F6", {}, framesetWindow),
+ gNewExpectedWindow, getById("f5"), true, "switch document forward with ctrl+tab");
+ gOldExpectedWindow = gNewExpectedWindow;
+ gNewExpectedWindow = framesetWindow.frames[3];
+ expectFocusShift(() => synthesizeKey("KEY_F6", {ctrlKey: true}, framesetWindow),
+ gNewExpectedWindow, getById("f7"), true, "switch document forward with ctrl+f6");
+ gOldExpectedWindow = gNewExpectedWindow;
+ gNewExpectedWindow = framesetWindow.frames[0];
+ expectFocusShift(() => synthesizeKey("KEY_F6", {ctrlKey: true}, framesetWindow),
+ gNewExpectedWindow, getById("f1"), true, "switch document forward and wrap");
+
+// going backwards by document and wrapping doesn't currently work, but didn't work
+// before the focus reworking either
+
+/*
+ gOldExpectedWindow = gNewExpectedWindow;
+ gNewExpectedWindow = framesetWindow.frames[3];
+ expectFocusShift(() => synthesizeKey("KEY_F6", { ctrlKey: true, shiftKey: true }, framesetWindow),
+ gNewExpectedWindow, getById("f7"), true, "switch document backward and wrap");
+ */
+
+ fm.moveFocus(framesetWindow.frames[3], null, fm.MOVEFOCUS_ROOT, 0);
+ gEvents = "";
+
+ gOldExpectedWindow = gNewExpectedWindow;
+ gNewExpectedWindow = framesetWindow.frames[2];
+ expectFocusShift(() => synthesizeKey("KEY_F6", {ctrlKey: true, shiftKey: true}, framesetWindow),
+ gNewExpectedWindow, getById("f5"), true, "switch document backward with f6");
+ gOldExpectedWindow = gNewExpectedWindow;
+ gNewExpectedWindow = framesetWindow.frames[1];
+ expectFocusShift(() => synthesizeKey("KEY_F6", {ctrlKey: true, shiftKey: true}, framesetWindow),
+ gNewExpectedWindow, getById("f3"), true, "switch document backward with ctrl+tab");
+ gOldExpectedWindow = gNewExpectedWindow;
+ gNewExpectedWindow = framesetWindow.frames[0];
+ expectFocusShift(() => synthesizeKey("KEY_F6", {ctrlKey: true, shiftKey: true}, framesetWindow),
+ gNewExpectedWindow, getById("f1"), true, "switch document backward with ctrl+f6");
+
+ // skip the window switching tests for now on Linux, as raising and lowering
+ // a window is asynchronous there
+ if (!navigator.platform.includes("Linux")) {
+ window.openDialog("focus_window2.xhtml", "_blank", "chrome", switchWindowTest, framesetWindow);
+ }
+ else {
+ gOldExpectedWindow = null;
+ gNewExpectedWindow = null;
+ framesetWindow.close();
+ SimpleTest.waitForFocus(doWindowNoRootTest);
+ }
+}
+
+// test switching between two windows
+function switchWindowTest(otherWindow, framesetWindow)
+{
+ initEvents(otherWindow);
+ var otherElement = otherWindow.document.getElementById("other");
+ otherElement.focus();
+
+ framesetWindow.frames[1].document.getElementById("f4").focus();
+
+ is(fm.focusedElement, otherElement, "focus after inactive window focus");
+
+ gLastFocus = otherElement;
+ gLastFocusWindow = otherWindow;
+ gEvents = "";
+ gOldExpectedWindow = otherWindow;
+ gNewExpectedWindow = framesetWindow.frames[1];
+
+ expectFocusShift(() => gNewExpectedWindow.focus(),
+ gNewExpectedWindow, getById("f4"), true, "switch to frame in another window");
+ is(fm.getFocusedElementForWindow(otherWindow, false, {}).id, "other", "inactive window has focused element");
+
+ gOldExpectedWindow = framesetWindow.frames[1];
+ gNewExpectedWindow = otherWindow;
+ expectFocusShift(() => otherWindow.focus(),
+ gNewExpectedWindow, getById("other"), true, "switch to another window");
+
+ var topWindow = getTopWindow(framesetWindow);
+
+ ok(topWindow.document.commandDispatcher.getControllerForCommand("cmd_copy"),
+ "getControllerForCommand for focused window set");
+ ok(otherWindow.document.commandDispatcher.getControllerForCommand("cmd_copy"),
+ "getControllerForCommand for non-focused window set");
+ ok(topWindow.document.commandDispatcher.getControllerForCommand("cmd_copy") !=
+ otherWindow.document.commandDispatcher.getControllerForCommand("cmd_copy"),
+ "getControllerForCommand for two windows different");
+ ok(topWindow.document.commandDispatcher.getControllers() !=
+ otherWindow.document.commandDispatcher.getControllers(),
+ "getControllers for two windows different");
+
+ gOldExpectedWindow = otherWindow;
+ gNewExpectedWindow = framesetWindow.frames[1];
+ expectFocusShift(() => topWindow.focus(),
+ gNewExpectedWindow, getById("f4"), true, "switch to frame activeWindow");
+
+ fm.clearFocus(otherWindow);
+ gOldExpectedWindow = gNewExpectedWindow;
+ gNewExpectedWindow = otherWindow;
+ expectFocusShift(() => fm.setFocus(otherElement, fm.FLAG_RAISE),
+ gNewExpectedWindow, getById("other"), true, "switch to window with raise");
+
+ getTopWindow(framesetWindow).document.commandDispatcher.focusedWindow = gOldExpectedWindow;
+ is(fm.activeWindow, gNewExpectedWindow, "setting commandDispatcher focusedWindow doesn't raise window");
+
+ fm.moveFocus(otherWindow, null, fm.MOVEFOCUS_FORWARD, 0);
+ var otherInput = otherWindow.document.getElementById("other-input");
+ otherInput.setSelectionRange(2, 3);
+ topWindow.focus();
+ otherWindow.focus();
+ is(otherInput.selectionStart, 2, "selectionStart after input focus and window raise");
+ is(otherInput.selectionEnd, 3, "selectionEnd after input focus and window raise");
+ is(fm.getLastFocusMethod(null), fm.FLAG_BYMOVEFOCUS, "last focus method after input focus and window raise");
+
+ fm.clearFocus(otherWindow);
+
+ // test to ensure that a synthetic event won't move focus
+ var synevent = new FocusEvent("focus", {});
+ otherInput.dispatchEvent(synevent);
+ is(synevent.type, "focus", "event.type after synthetic focus event");
+ is(synevent.target, otherInput, "event.target after synthetic focus event");
+ is(fm.focusedElement, null, "focusedElement after synthetic focus event");
+ is(otherWindow.document.activeElement, otherWindow.document.documentElement,
+ "document.activeElement after synthetic focus event");
+
+ // check accessing a focus event after the event has finishing firing
+ function continueTest(event) {
+ is(event.type, "focus", "event.type after accessing focus event in timeout");
+ is(event.target, otherInput, "event.target after accessing focus event in timeout");
+
+ gOldExpectedWindow = null;
+ gNewExpectedWindow = null;
+ otherWindow.close();
+ framesetWindow.close();
+
+ SimpleTest.waitForFocus(doWindowNoRootTest);
+ }
+
+ function inputFocused(event) {
+ otherInput.removeEventListener("focus", inputFocused, true);
+ setTimeout(continueTest, 0, event);
+ }
+
+ otherInput.addEventListener("focus", inputFocused, true);
+ otherInput.focus();
+}
+
+// open a window with no root element
+var noRootWindow = null;
+function doWindowNoRootTest()
+{
+ addEventListener("focus", doFrameSwitchingTests, true);
+ noRootWindow = window.open("window_focus_inner.xhtml", "_blank", "chrome,width=100,height=100");
+}
+
+// these tests check when focus is moved between a tree of frames to ensure
+// that the focus is in the right place at each event step.
+function doFrameSwitchingTests()
+{
+ removeEventListener("focus", doFrameSwitchingTests, true);
+ noRootWindow.close();
+
+ var framea = document.getElementById("ifa");
+ var frameb = document.getElementById("ifb");
+ framea.style.MozUserFocus = "";
+ frameb.style.MozUserFocus = "";
+
+ window.removeEventListener("focus", eventOccured, true);
+ window.removeEventListener("blur", eventOccured, true);
+
+ var inputa = framea.contentDocument.body.firstChild;
+ inputa.focus();
+
+ addFrameSwitchingListeners(framea);
+ addFrameSwitchingListeners(frameb);
+ var framec = framea.contentDocument.body.lastChild;
+ addFrameSwitchingListeners(framec);
+
+ var framed = framec.contentDocument.body.lastChild;
+ addFrameSwitchingListeners(framed);
+
+ var inputc = framec.contentDocument.body.firstChild;
+
+ var expectedMainWindowFocus = framea;
+
+ // An element in the immediate parent frame is focused. Focus an element in
+ // the child. The child should be focused and the parent's current focus should
+ // be the child iframe.
+ gEventMatched = true;
+ is(fm.getFocusedElementForWindow(window, false, {}), expectedMainWindowFocus,
+ "parent of framea has iframe focused");
+ gExpectedEvents = [[inputa, "blur", null, framea.contentWindow, window, framea],
+ [framea.contentDocument, "blur", null, null, window, framea],
+ [framea.contentWindow, "blur", null, null, window, framea],
+ [framec.contentDocument, "focus", null, framec.contentWindow, window, framea],
+ [framec.contentWindow, "focus", null, framec.contentWindow, window, framea],
+ [inputc, "focus", inputc, framec.contentWindow, window, framea]];
+ inputc.focus();
+ ok(gEventMatched && !gExpectedEvents.length, "frame switch from parent input to child input" + gExpectedEvents);
+
+ // An element in a child is focused. Focus an element in the immediate
+ // parent.
+ gEventMatched = true;
+ gExpectedEvents = [[inputc, "blur", null, framec.contentWindow, window, framea],
+ [framec.contentDocument, "blur", null, null, window, framea],
+ [framec.contentWindow, "blur", null, null, window, framea],
+ [framea.contentDocument, "focus", null, framea.contentWindow, window, framea],
+ [framea.contentWindow, "focus", null, framea.contentWindow, window, framea],
+ [inputa, "focus", inputa, framea.contentWindow, window, framea]];
+ inputa.focus();
+ ok(gEventMatched && !gExpectedEvents.length, "frame switch from child input to parent input");
+
+ // An element in a frame is focused. Focus an element in a sibling frame.
+ // The common ancestor of the two frames should have its focused node
+ // cleared after the element is blurred.
+ var inputb = frameb.contentDocument.body.firstChild;
+
+ gEventMatched = true;
+ gExpectedEvents = [[inputa, "blur", null, framea.contentWindow, window, framea],
+ [framea.contentDocument, "blur", null, null, window, null],
+ [framea.contentWindow, "blur", null, null, window, null],
+ [frameb.contentDocument, "focus", null, frameb.contentWindow, window, frameb],
+ [frameb.contentWindow, "focus", null, frameb.contentWindow, window, frameb],
+ [inputb, "focus", inputb, frameb.contentWindow, window, frameb]];
+ inputb.focus();
+ ok(gEventMatched && !gExpectedEvents.length, "frame switch from input to sibling frame");
+ is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), inputa,
+ "blurred frame still has input as focus");
+
+ // focus a descendant in a sibling
+ var inputd = framed.contentDocument.body.firstChild;
+ gEventMatched = true;
+ gExpectedEvents = [[inputb, "blur", null, frameb.contentWindow, window, frameb],
+ [frameb.contentDocument, "blur", null, null, window, null],
+ [frameb.contentWindow, "blur", null, null, window, null],
+ [framed.contentDocument, "focus", null, framed.contentWindow, window, framea],
+ [framed.contentWindow, "focus", null, framed.contentWindow, window, framea],
+ [inputd, "focus", inputd, framed.contentWindow, window, framea]];
+ inputd.focus();
+ ok(gEventMatched && !gExpectedEvents.length, "frame switch from input to sibling descendant");
+ is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), framec,
+ "sibling parent focus has shifted to frame");
+
+ // focus an ancestor
+ gEventMatched = true;
+ gExpectedEvents = [[inputd, "blur", null, framed.contentWindow, window, framea],
+ [framed.contentDocument, "blur", null, null, window, framea],
+ [framed.contentWindow, "blur", null, null, window, framea],
+ [framea.contentDocument, "focus", null, framea.contentWindow, window, framea],
+ [framea.contentWindow, "focus", null, framea.contentWindow, window, framea],
+ [inputa, "focus", inputa, framea.contentWindow, window, framea]];
+ inputa.focus();
+ ok(gEventMatched && !gExpectedEvents.length, "frame switch from child input to ancestor");
+
+ // focus a descendant
+ gEventMatched = true;
+ gExpectedEvents = [[inputa, "blur", null, framea.contentWindow, window, framea],
+ [framea.contentDocument, "blur", null, null, window, framea],
+ [framea.contentWindow, "blur", null, null, window, framea],
+ [framed.contentDocument, "focus", null, framed.contentWindow, window, framea],
+ [framed.contentWindow, "focus", null, framed.contentWindow, window, framea],
+ [inputd, "focus", inputd, framed.contentWindow, window, framea]];
+ inputd.focus();
+ ok(gEventMatched && !gExpectedEvents.length, "frame switch from child input to ancestor");
+ is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), framec,
+ "parent focus has shifted to frame");
+
+ // focus a sibling frame by setting focusedWindow
+ gEventMatched = true;
+ gExpectedEvents = [[inputd, "blur", null, framed.contentWindow, window, framea],
+ [framed.contentDocument, "blur", null, null, window, null],
+ [framed.contentWindow, "blur", null, null, window, null],
+ [frameb.contentDocument, "focus", null, frameb.contentWindow, window, frameb],
+ [frameb.contentWindow, "focus", null, frameb.contentWindow, window, frameb]];
+ fm.focusedWindow = frameb.contentWindow;
+ ok(gEventMatched && !gExpectedEvents.length, "frame switch using focusedWindow");
+
+ // clear the focus in an unfocused frame
+ gEventMatched = true;
+ gExpectedEvents = [];
+ fm.clearFocus(framec.contentWindow);
+ ok(gEventMatched && !gExpectedEvents.length, "clearFocus in unfocused frame");
+
+ // focus a sibling frame by setting focusedWindow when no element is focused in that frame
+ gEventMatched = true;
+ gExpectedEvents = [[frameb.contentDocument, "blur", null, null, window, null],
+ [frameb.contentWindow, "blur", null, null, window, null],
+ [framec.contentDocument, "focus", null, framec.contentWindow, window, framea],
+ [framec.contentWindow, "focus", null, framec.contentWindow, window, framea]];
+ fm.focusedWindow = framec.contentWindow;
+ ok(gEventMatched && !gExpectedEvents.length, "frame switch using focusedWindow with no element focused");
+ is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), framec,
+ "parent focus has shifted to frame using focusedWindow");
+
+ // focus the parent frame by setting focusedWindow. This should have no effect.
+ gEventMatched = true;
+ gExpectedEvents = [];
+ fm.focusedWindow = framea.contentWindow;
+ ok(gEventMatched && !gExpectedEvents.length, "frame switch to parent using focusedWindow");
+
+ // clear the focus in the parent frame
+ gEventMatched = true;
+ gExpectedEvents = [[framec.contentDocument, "blur", null, null, window, framea],
+ [framec.contentWindow, "blur", null, null, window, framea],
+ [framea.contentDocument, "focus", null, framea.contentWindow, window, framea],
+ [framea.contentWindow, "focus", null, framea.contentWindow, window, framea]];
+ fm.clearFocus(framea.contentWindow);
+ ok(gEventMatched && !gExpectedEvents.length, "clearFocus in parent frame");
+
+ // clear the focus in an unfocused child frame
+ gEventMatched = true;
+ gExpectedEvents = [];
+ fm.clearFocus(framed.contentWindow);
+ ok(gEventMatched && !gExpectedEvents.length, "clearFocus in unfocused child frame");
+
+ var exh = false;
+ try {
+ fm.focusedWindow = null;
+ }
+ catch (ex) { exh = true; }
+ is(exh, true, "focusedWindow set to null");
+ is(fm.focusedWindow, framea.contentWindow, "window not changed when focusedWindow set to null");
+
+ doFrameHistoryTests()
+}
+
+function doFrameHistoryTests()
+{
+ let frame = $("childframe");
+ frame.setAttribute("maychangeremoteness", "true");
+ let loaded = BrowserTestUtils.browserLoaded(frame, true);
+ let firstLocation = "https://example.org/chrome/dom/tests/mochitest/chrome/child_focus_frame.html";
+ frame.src = firstLocation;
+ loaded.then(() => {
+ return ContentTask.spawn(frame, {}, () => {
+ let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
+ let t20 = content.document.getElementById("t20");
+ t20.focus();
+ let goneBack = new Promise(resolve => {
+ content.addEventListener("pageshow", ({ persisted }) => {
+ resolve({ location: content.location.href, persisted });
+ }, { once: true });
+ });
+ // make sure that loading a new page and then going back maintains the focus
+ content.location = "data:text/html,<script>window.onload=function() {setTimeout(function () { history.back() }, 0);}</script>";
+ return goneBack;
+ });
+ }).then(({ location, persisted }) => {
+ is(location, firstLocation, "should go back to the right page");
+ ok(persisted, "test relies on BFCache");
+ return ContentTask.spawn(frame, {}, () => {
+ let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
+ let t20 = content.document.getElementById("t20");
+ return fm.focusedElement === t20;
+ });
+ }).then((focusCorrect) => {
+ if (SpecialPowers.Services.appinfo.sessionHistoryInParent) {
+ todo(focusCorrect, "focus restored after history back");
+ } else {
+ ok(focusCorrect, "focus restored after history back");
+ }
+ done();
+ });
+}
+
+function addFrameSwitchingListeners(frame)
+{
+ frame.contentWindow.addEventListener("focus", frameSwitchingEventOccured, false);
+ frame.contentWindow.addEventListener("blur", frameSwitchingEventOccured, false);
+ frame.contentDocument.addEventListener("focus", frameSwitchingEventOccured, false);
+ frame.contentDocument.addEventListener("blur", frameSwitchingEventOccured, false);
+
+ var node = frame.contentDocument.body.firstChild;
+ node.addEventListener("focus", frameSwitchingEventOccured, false);
+ node.addEventListener("blur", frameSwitchingEventOccured, false);
+}
+
+function frameSwitchingEventOccured(event)
+{
+ if (!gExpectedEvents.length) {
+ gEventMatched = false;
+ return;
+ }
+
+ try {
+ var events = gExpectedEvents.shift();
+ is(event.target, events[0], "event target");
+ is(event.type, events[1], "event type");
+ is(fm.focusedElement, events[2], "focused element");
+ is(fm.focusedWindow, events[3], "focused frame");
+ if (events[4])
+ is(fm.getFocusedElementForWindow(events[4], false, {}), events[5], "focused element in frame");
+
+ if (gEventMatched && event.target == events[0] && event.type == events[1] &&
+ fm.focusedElement == events[2] && fm.focusedWindow == events[3]) {
+ if (!events[4] || fm.getFocusedElementForWindow(events[4], false, {}) == events[5])
+ return;
+ }
+ } catch (ex) { ok(ex, "exception"); }
+
+ gEventMatched = false;
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(startTest);
+
+]]>
+</script>
+
+<commandset id="cu"
+ commandupdater="true"
+ events="focus"
+ oncommandupdate="eventOccured(event)"/>
+
+<!--
+ The elements with ids starting with t are focusable and in the taborder.
+ The elements with ids starting with o are:
+ odd numbered ids - focusable but not part of the tab order
+ even numbered ids - not focusable with -moz-user-focus: ignore or disabled
+ The elements with ids starting with n are:
+ odd numbered ids - not focusable with -moz-user-focus: none
+ even numbered ids - focusable but not part of the tab order
+ -->
+<vbox id="buttonbox">
+<hbox id="innerbox">
+ <button id="t4" accesskey="h" label="no tabindex"/>
+ <button id="o1" accesskey="i" label="tabindex = -1" tabindex="-1"/>
+ <richlistbox id="t5" label="tabindex = 0" tabindex="0" style="width: 50px">
+ <richlistitem height="10"/>
+ </richlistbox>
+ <button id="t1" label="tabindex = 2" tabindex="2"/>
+</hbox>
+<hbox>
+ <button id="o2" accesskey="o" style="-moz-user-focus: ignore;" label="no tabindex"/>
+ <button id="o4" style="-moz-user-focus: ignore;" label="no tabindex"/>
+ <button id="t6" style="-moz-user-focus: ignore;" label="tabindex = 0" tabindex="0"/>
+ <button id="t2" style="-moz-user-focus: ignore;" label="tabindex = 2" tabindex="2"/>
+</hbox>
+<hbox id="specialroot">
+ <button id="t7" style="-moz-user-focus: normal;" label="no tabindex"/>
+ <button id="o3" style="-moz-user-focus: normal;" label="tabindex = -1" tabindex="-1"/>
+ <button id="t8" style="-moz-user-focus: normal;" label="tabindex = 0" tabindex="0"/>
+ <richlistbox id="t3" style="-moz-user-focus: normal; width: 50px" label="tabindex = 2" tabindex="2">
+ <richlistitem style="height: 10px"/>
+ </richlistbox>
+</hbox>
+<hbox>
+ <button accesskey="p" style="display: none;"/> <button accesskey="q" style="visibility: collapse;"/>
+ <button style="display: none;" tabindex="2"/> <button style="visibility: collapse;" tabindex="2"/>
+</hbox>
+<hbox>
+ <button id="o20" accesskey="s" label="no tabindex" disabled="true"/>
+ <button id="o22" label="tabindex = -1" tabindex="-1" disabled="true"/>
+ <button id="o24" label="tabindex = 0" tabindex="0" disabled="true"/>
+ <button id="o26" label="tabindex = 2" tabindex="2" disabled="true"/>
+</hbox>
+</vbox>
+<vbox>
+<hbox>
+ <dropmarker id="o6" value="no tabindex"/>
+ <dropmarker id="o8" value="no tabindex"/>
+ <dropmarker id="o10" value="no tabindx"/>
+ <dropmarker id="o12" value="no tabindex"/>
+ <dropmarker id="t9" accesskey="r" style="-moz-user-focus: normal;" value="no tabindex" />
+ <dropmarker id="t10" style="-moz-user-focus: normal;" value="no tabindex"/>
+ <dropmarker id="t11" style="-moz-user-focus: normal;" value="tabindex = 0" tabindex="0" />
+ <dropmarker id="t12" style="-moz-user-focus: normal;" value="no tabindex"/>
+ <dropmarker id="o14" style="-moz-user-focus: ignore;" value="no tabindex"/>
+ <dropmarker id="o16" style="-moz-user-focus: ignore;" value="no tabindex"/>
+ <dropmarker id="n1" style="-moz-user-focus: none;" value="no tabindex"/>
+ <dropmarker id="n3" style="-moz-user-focus: none;" value="no tabindex"/>
+</hbox>
+</vbox>
+<browser id="childframe" type="content" src="child_focus_frame.html" style="height: 195px"/>
+<button id="t34"/>
+<tabbox id="tabbox">
+ <tabs><tab id="t35" label="One"/><tab id="tab2" label="Two"/></tabs>
+ <tabpanels>
+ <tabpanel>
+ <checkbox id="t36"/>
+ <button id="t37"/>
+ </tabpanel>
+ <tabpanel>
+ <checkbox id="htab1"/>
+ <button id="nohtab2" tabindex="7"/>
+ <checkbox id="htab2" tabindex="0"/>
+ </tabpanel>
+ </tabpanels>
+</tabbox>
+<hbox>
+<panel>
+ <button id="inpopup1" label="One"/>
+ <input xmlns="http://www.w3.org/1999/xhtml" label="Two"/>
+</panel>
+<description label="o" accesskey="v"/>
+<button id="t38"/>
+<!-- The 't' element tests end here so it doesn't matter that these elements are tabbable -->
+<label id="aj" value="j" accesskey="j" control="o9"/>
+<label id="ak" accesskey="k" control="n4">k</label>
+<checkbox id="o5"/><checkbox id="o7"/><hbox><checkbox id="o9"/></hbox>
+<checkbox id="o13"/><checkbox id="o15"/><checkbox id="o17"/><checkbox id="o19"/><checkbox id="o21"/><checkbox id="o23"/><checkbox id="o25"/>
+<checkbox id="n2"/><checkbox id="n4"/>
+<richlistbox id="last" style="width: 20px; height: 20px"/>
+
+<iframe id="ifa" style="-moz-user-focus: ignore; width: 40px; height: 60px" type="content"
+ src="data:text/html,&lt;input id=fra size='2'&gt;&lt;input id='fra-b' size='2'&gt;
+ &lt;iframe src='data:text/html,&lt;input id=frc&gt;&lt;iframe src=&quot;data:text/html,&lt;input id=frd&gt;&quot;&gt;&lt;/iframe&gt;'&gt;&lt;/iframe&gt;"/>
+<iframe id="ifb" style="-moz-user-focus: ignore; width: 20px; height: 20px"
+ src="data:text/html,&lt;input id=frd&gt;&lt;/iframe&gt;"/>
+
+</hbox>
+</window>
diff --git a/dom/tests/mochitest/chrome/window_focus_docnav.xhtml b/dom/tests/mochitest/chrome/window_focus_docnav.xhtml
new file mode 100644
index 0000000000..33bff7ec0a
--- /dev/null
+++ b/dom/tests/mochitest/chrome/window_focus_docnav.xhtml
@@ -0,0 +1,124 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window onload="start()"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
+
+<input xmlns="http://www.w3.org/1999/xhtml" id="textbox1"/>
+<input xmlns="http://www.w3.org/1999/xhtml" id="textbox2"/>
+
+<panel id="panel" onpopupshown="runTests(this, 1);"
+ onpopuphidden="noChildrenTest()">
+ <input xmlns="http://www.w3.org/1999/xhtml" id="p1textbox" value="Popup1"/>
+</panel>
+<panel id="panel2" onpopupshown="runTests(this, 2);" onpopuphidden="document.getElementById('panel').hidePopup()">
+ <input xmlns="http://www.w3.org/1999/xhtml" id="p2textbox" value="Popup2"/>
+</panel>
+
+<browser id="browser" type="content" src="focus_frameset.html" style="width: 500px; height: 400px"/>
+
+<script type="application/javascript">
+<![CDATA[
+
+var fm = Cc["@mozilla.org/focus-manager;1"].
+ getService(Ci.nsIFocusManager);
+
+function is(l, r, n) { window.arguments[0].SimpleTest.is(l,r,n); }
+function ok(v, n) { window.arguments[0].SimpleTest.ok(v,n); }
+
+function noChildrenTest()
+{
+ // Remove the browser element and test navigation when there are no other documents.
+ // The focus should move or stay on the first focusable element.
+ let browser = document.getElementById("browser");
+ browser.remove();
+
+ let textbox1 = document.getElementById("textbox1");
+ let textbox2 = document.getElementById("textbox2");
+
+ textbox2.focus();
+ next(window, textbox1, "Focus forward when no child documents");
+ next(window, textbox1, "Focus forward again when no child documents");
+
+ textbox2.focus();
+ previous(window, textbox1, "Focus backward when no child documents");
+ previous(window, textbox1, "Focus backward again when no child documents");
+
+ done();
+}
+
+function done()
+{
+ window.close();
+ window.arguments[0].SimpleTest.finish();
+}
+
+function previous(expectedWindow, expectedElement, desc)
+{
+ synthesizeKey("KEY_F6", {shiftKey: true});
+ is(fm.focusedWindow, expectedWindow, desc);
+ is(fm.focusedElement, expectedElement, desc + " element");
+}
+
+function next(expectedWindow, expectedElement, desc)
+{
+ synthesizeKey("KEY_F6");
+ is(fm.focusedWindow, expectedWindow, desc);
+ is(fm.focusedElement, expectedElement, desc + " element" + "::" + (fm.focusedElement ? fm.focusedElement.parentNode.id : "<none>"));
+}
+
+// This test runs through three cases. Document navigation forward and
+// backward using the F6 key when no popups are open, with one popup open and
+// with two popups open.
+function runTests(panel, popupCount)
+{
+ if (!popupCount || popupCount > 2)
+ popupCount = 0;
+
+ fm.clearFocus(window);
+
+ var childwin = document.getElementById("browser").contentWindow;
+
+ if (popupCount) {
+ next(window, document.getElementById("p1textbox"), "First into popup 1 with " + popupCount);
+
+ if (popupCount == 2) {
+ next(window, document.getElementById("p2textbox"), "First into popup 2 with " + popupCount);
+ }
+ }
+
+ next(childwin.frames[0], childwin.frames[0].document.documentElement, "First with " + popupCount);
+ next(childwin.frames[1], childwin.frames[1].document.documentElement, "Second with " + popupCount);
+ previous(childwin.frames[0], childwin.frames[0].document.documentElement, "Second back with " + popupCount);
+
+ if (popupCount) {
+ if (popupCount == 2) {
+ previous(window, document.getElementById("p2textbox"), "First back from popup 2 with " + popupCount);
+ }
+
+ previous(window, document.getElementById("p1textbox"), "First back from popup 1 with " + popupCount);
+ }
+
+ previous(window, document.getElementById("textbox1"), "First back with " + popupCount);
+
+ if (panel == document.getElementById("panel"))
+ document.getElementById("panel2").openPopup(null, "after_start", 100, 20);
+ else if (panel == document.getElementById("panel2"))
+ panel.hidePopup();
+ else
+ document.getElementById("panel").openPopup(null, "after_start");
+}
+
+function start()
+{
+ window.arguments[0].SimpleTest.waitForExplicitFinish();
+ window.arguments[0].SimpleTest.waitForFocus(
+ function() { runTests(null, 0); },
+ document.getElementById("browser").contentWindow);
+}
+
+]]></script>
+
+</window>
diff --git a/dom/tests/mochitest/chrome/window_focus_inner.xhtml b/dom/tests/mochitest/chrome/window_focus_inner.xhtml
new file mode 100644
index 0000000000..6887555fa7
--- /dev/null
+++ b/dom/tests/mochitest/chrome/window_focus_inner.xhtml
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<window onfocus='dostuff()' xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' style='-moz-user-focus: normal;'>
+<script>
+ function dostuff() {
+ setTimeout(function() {
+ document.documentElement.focus();
+ document.removeChild(document.documentElement);
+ window.opener.focus();
+ }, 100);
+ }
+</script>
+</window>