summaryrefslogtreecommitdiffstats
path: root/layout/base/tests/chrome/test_css_visibility_propagation.xhtml
blob: f11db96a898f2b509065315249ff2467ee763375 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
<?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 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>
<![CDATA[
const baseURL = "chrome://mochitests/content/chrome/layout/base/tests/chrome/";

function checkHiddenEmbeddederState(window1, window2, expected1, expected2)
{
  ok(!window1.browsingContext.isUnderHiddenEmbedderElement, "window1 visible state");
  ok(!window2.browsingContext.isUnderHiddenEmbedderElement, "window2 visible state");
  is(window1.document.querySelector("browser").contentWindow.browsingContext.isUnderHiddenEmbedderElement, !expected1,
     "window1 child visible state");
  is(window2.document.querySelector("browser").contentWindow.browsingContext.isUnderHiddenEmbedderElement, !expected2,
     "window2 child visible state");
}

// Tests that browser visibility is updated when it's swapped.
add_task(async () => {
  // Open two new windows to swap iframes.
  const window1 = window.browsingContext.topChromeWindow.open(
      baseURL + "window_css_visibility_propagation-1.xhtml",
      "_blank", "chrome");
  const window2 = window.browsingContext.topChromeWindow.open(
      baseURL + "window_css_visibility_propagation-2.xhtml",
      "_blank", "chrome");

  const loadWindow1 =
      new Promise(resolve => window1.addEventListener("load", resolve));
  const loadWindow2 =
      new Promise(resolve => window2.addEventListener("load", resolve));

  await Promise.all([ loadWindow1, loadWindow2 ]);

  checkHiddenEmbeddederState(window1, window2, false, true);

  // Hide the parent of browser2.
  let parent = window2.document.getElementById("parent");
  parent.style.visibility = "hidden";
  parent.getBoundingClientRect();

  checkHiddenEmbeddederState(window1, window2, false, false);

  const browser2 = window2.document.querySelector("browser");
  let target = browser2.contentDocument.getElementById("button");
  target.focus();

  // browser2 is now in a visibility:hidden element in window2,
  // so that Element.focus() shouldn't work.
  isnot(browser2.contentDocument.activeElement, target,
        "Element.focus() shouldn't work in invisible browser");

  // Make the parent visible.
  parent.style.visibility = "";
  parent.getBoundingClientRect();

  checkHiddenEmbeddederState(window1, window2, false, true);

  target.focus();

  // browser2 is visible now, so focus() should work.
  is(browser2.contentDocument.activeElement, target,
     "Element.focus() should work in visible browser");

  target.blur();
  isnot(browser2.contentDocument.activeElement, target,
        "The target element shouldn't be activeElement");

  // Swap the content in browser1 for the content in browser2.
  const browser1 = window1.document.querySelector("browser");
  browser1.swapFrameLoaders(browser2);
  await new Promise(resolve => setTimeout(resolve, 0));

  target = browser1.contentDocument.getElementById("button");
  target.focus();

  // browser1 is in a visibility:hidden element in window1,
  // so that Element.focus() shouldn't work.
  isnot(browser1.contentDocument.activeElement, target,
        "Element.focus() shouldn't work in invisible browser");

  checkHiddenEmbeddederState(window1, window2, false, true);

  parent = window1.document.getElementById("parent");
  parent.style.visibility = "visible";
  parent.getBoundingClientRect();

  checkHiddenEmbeddederState(window1, window2, true, true);

  target.focus();

  // Now browser1 is in a visibility:visible element, so that
  // Element.focus() should just work.
  is(browser1.contentDocument.activeElement, target,
     "Element.focus() should work in visible browser");

  window1.close();
  window2.close();
});

// Tests that ancestor's visibility change doesn't clobber child
// iframe's visibility if the child iframe is hidden by an
// element in the ancestor document.
add_task(async () => {
  const tabReady = new Promise(resolve => {
    window.addEventListener("message", event => {
      if (event.data == "ready") {
        resolve();
      }
    }, { once: true });
  });
  const tabWindow =
      window.open(baseURL + "window_css_visibility_propagation-3.html");
  await tabReady;

  const childIFrame = tabWindow.document.querySelector("iframe");

  const grandChildBrowser =
      childIFrame.contentDocument.querySelector("browser");
  let target = grandChildBrowser.contentDocument.getElementById("button");
  target.focus();

  ok(!tabWindow.browsingContext.isUnderHiddenEmbedderElement, "tab window is visible");
  ok(!childIFrame.browsingContext.isUnderHiddenEmbedderElement, "iframe is visible");
  ok(!grandChildBrowser.browsingContext.isUnderHiddenEmbedderElement, "grandchild is visible");

  is(grandChildBrowser.contentDocument.activeElement, target,
     "Element.focus() should work in visible browser");
  target.blur();

  // Hide the parent element of the grand child browser.
  let parent = childIFrame.contentDocument.getElementById("parent");
  parent.style.visibility = "hidden";
  parent.getBoundingClientRect();

  ok(!tabWindow.browsingContext.isUnderHiddenEmbedderElement, "tab window is visible");
  ok(!childIFrame.browsingContext.isUnderHiddenEmbedderElement, "iframe is visible");
  ok(grandChildBrowser.browsingContext.isUnderHiddenEmbedderElement, "grandchild is not visible");

  target.focus();

  isnot(grandChildBrowser.contentDocument.activeElement, target,
        "Element.focus() shouldn't work in invisible browser");

  // Hide the parent element of the child iframe.
  parent = tabWindow.document.getElementById("parent");
  parent.style.visibility = "hidden";
  parent.getBoundingClientRect();

  target.focus();

  ok(!tabWindow.browsingContext.isUnderHiddenEmbedderElement, "tab window is visible");
  ok(childIFrame.browsingContext.isUnderHiddenEmbedderElement, "iframe is not visible");
  ok(grandChildBrowser.browsingContext.isUnderHiddenEmbedderElement, "grandchild is not visible");

  isnot(grandChildBrowser.contentDocument.activeElement, target,
        "Element.focus() shouldn't work in invisible iframe");

  // Make the parent element of the child iframe visible.
  parent.style.visibility = "visible";
  parent.getBoundingClientRect();

  ok(!tabWindow.browsingContext.isUnderHiddenEmbedderElement, "tab window is visible");
  ok(!childIFrame.browsingContext.isUnderHiddenEmbedderElement, "iframe is visible");
  ok(grandChildBrowser.browsingContext.isUnderHiddenEmbedderElement, "grandchild is not visible");

  target.focus();

  // Even if the child iframe is visible, but still the grand child is
  // hidden by the parent element of the grand child browser so that
  // we can't focus to the element in the grand child browser.
  isnot(grandChildBrowser.contentDocument.activeElement, target,
        "Element.focus() shouldn't work in invisible browser");

  tabWindow.close();
});

// Tests that an iframe is initially hidden by a visibility:hidden element in
// the parent document.
add_task(async () => {
  const tabReady = new Promise(resolve => {
    window.addEventListener("message", event => {
      if (event.data == "ready") {
        resolve();
      }
    }, { once: true });
  });
  const tabWindow =
      window.open(baseURL + "window_css_visibility_propagation-4.html");
  await tabReady;

  const iframe = tabWindow.document.querySelector("iframe");
  let target = iframe.contentDocument.getElementById("button");
  target.focus();

  ok(!tabWindow.browsingContext.isUnderHiddenEmbedderElement, "tab window is visible");
  ok(iframe.browsingContext.isUnderHiddenEmbedderElement, "iframe is not visible");

  isnot(iframe.contentDocument.activeElement, target,
        "Element.focus() shouldn't work in invisible iframe");

  tabWindow.close();
});
]]>
</script>
</window>