CLOSED TREE: TraceMonkey merge head. (a=blockers)
[mozilla-central.git] / docshell / test / navigation / browser_bug343515.js
blobfb405841c9402086b60bf7dbf4a9e2353073a756
1 // Test for bug 343515 - Need API for tabbrowsers to tell docshells they're visible/hidden
3 // Globals
4 var testPath = "http://mochi.test:8888/browser/docshell/test/navigation/";
5 var Ci = Components.interfaces;
6 var Cc = Components.classes;
7 var ctx = {};
9 // Helper function to check if a window is active
10 function isActive(aWindow) {
11 var docshell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
12 .getInterface(Ci.nsIWebNavigation)
13 .QueryInterface(Ci.nsIDocShell);
14 return docshell.isActive;
17 // Returns a closure that will remove itself as a listener from
18 // aElem and then call aCallback. aCallback is executed asynchronously,
19 // which is handy because load events fire before mIsDocumentLoaded is actually
20 // set to true. :(
21 function autoRemovedListener(aElem, aType, aCallback) {
23 var elem = aElem;
24 var type = aType;
25 var callback = aCallback;
27 function remover() {
28 elem.removeEventListener(type, remover, true);
29 executeSoon(callback);
32 return remover;
35 // Returns a closure that iteratively (BFS) waits for all
36 // of the descendant frames of aInitialWindow to finish loading,
37 // then calls aFinalCallback.
38 function frameLoadWaiter(aInitialWindow, aFinalCallback) {
40 // The window we're currently waiting on
41 var curr = aInitialWindow;
43 // The windows we need to wait for
44 var waitQueue = [];
46 // The callback to call when we're all done
47 var finalCallback = aFinalCallback;
49 function frameLoadCallback() {
51 // Push any subframes of what we just got
52 for (var i = 0; i < curr.frames.length; ++i)
53 waitQueue.push(curr.frames[i]);
55 // Handle the next window in the queue
56 if (waitQueue.length >= 1) {
57 curr = waitQueue.shift();
58 if (curr.document.readyState == "complete")
59 frameLoadCallback();
60 else
61 curr.addEventListener("load", autoRemovedListener(curr, "load", frameLoadCallback), true);
62 return;
65 // Otherwise, we're all done. Call the final callback
66 finalCallback();
69 return frameLoadCallback;
72 // Entry point from Mochikit
73 function test() {
75 // Lots of callbacks going on here
76 waitForExplicitFinish();
78 // Begin the test
79 step1();
82 function step1() {
84 // Get a handle on the initial tab
85 ctx.tab0 = gBrowser.selectedTab;
86 ctx.tab0Browser = gBrowser.getBrowserForTab(ctx.tab0);
87 ctx.tab0Window = ctx.tab0Browser.contentWindow;
89 // Our current tab should be active
90 ok(isActive(ctx.tab0Window), "Tab 0 should be active at test start");
92 // Open a New Tab
93 ctx.tab1 = gBrowser.addTab(testPath + "bug343515_pg1.html");
94 ctx.tab1Browser = gBrowser.getBrowserForTab(ctx.tab1);
95 ctx.tab1Window = ctx.tab1Browser.contentWindow;
96 ctx.tab1Browser.addEventListener("load",
97 autoRemovedListener(ctx.tab1Browser, "load", step2),
98 true);
101 function step2() {
103 // Our current tab should still be active
104 ok(isActive(ctx.tab0Window), "Tab 0 should still be active");
105 ok(!isActive(ctx.tab1Window), "Tab 1 should not be active");
107 // Switch to tab 1
108 gBrowser.selectedTab = ctx.tab1;
110 // Tab 1 should now be active
111 ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
112 ok(isActive(ctx.tab1Window), "Tab 1 should be active");
114 // Open another tab
115 ctx.tab2 = gBrowser.addTab(testPath + "bug343515_pg2.html");
116 ctx.tab2Browser = gBrowser.getBrowserForTab(ctx.tab2);
117 ctx.tab2Window = ctx.tab2Browser.contentWindow;
118 ctx.tab2Browser.addEventListener("load",
119 autoRemovedListener(ctx.tab2Browser, "load",
120 frameLoadWaiter(ctx.tab2Window, step3)),
121 true);
124 function step3() {
126 // Tab 0 should be inactive, Tab 1 should be active
127 ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
128 ok(isActive(ctx.tab1Window), "Tab 1 should be active");
130 // Tab 2's window _and_ its iframes should be inactive
131 ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive");
132 is(ctx.tab2Window.frames.length, 2, "Tab 2 should have 2 iframes");
133 ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive");
134 ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive");
136 // Navigate tab 2 to a different page
137 ctx.tab2Window.location = testPath + "bug343515_pg3.html";
138 ctx.tab2Browser.addEventListener("load",
139 autoRemovedListener(ctx.tab2Browser, "load",
140 frameLoadWaiter(ctx.tab2Window, step4)),
141 true);
144 function step4() {
146 // Tab 0 should be inactive, Tab 1 should be active
147 ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
148 ok(isActive(ctx.tab1Window), "Tab 1 should be active");
150 // Tab2 and all descendants should be inactive
151 ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive");
152 is(ctx.tab2Window.frames.length, 2, "Tab 2 should have 2 iframes");
153 is(ctx.tab2Window.frames[0].frames.length, 1, "Tab 2 iframe 0 should have 1 iframes");
154 ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive");
155 ok(!isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be inactive");
156 ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive");
158 // Switch to Tab 2
159 gBrowser.selectedTab = ctx.tab2;
161 // Check everything
162 ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
163 ok(!isActive(ctx.tab1Window), "Tab 1 should be inactive");
164 ok(isActive(ctx.tab2Window), "Tab 2 should be active");
165 ok(isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be active");
166 ok(isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be active");
167 ok(isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be active");
169 // Go back
170 ctx.tab2Browser.addEventListener("pageshow",
171 autoRemovedListener(ctx.tab2Browser, "pageshow",
172 frameLoadWaiter(ctx.tab2Window, step5)),
173 true);
174 ctx.tab2Browser.goBack();
178 function step5() {
180 // Check everything
181 ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
182 ok(!isActive(ctx.tab1Window), "Tab 1 should be inactive");
183 ok(isActive(ctx.tab2Window), "Tab 2 should be active");
184 ok(isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be active");
185 ok(isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be active");
187 // Switch to tab 1
188 gBrowser.selectedTab = ctx.tab1;
190 // Navigate to page 3
191 ctx.tab1Window.location = testPath + "bug343515_pg3.html";
192 ctx.tab1Browser.addEventListener("load",
193 autoRemovedListener(ctx.tab1Browser, "load",
194 frameLoadWaiter(ctx.tab1Window, step6)),
195 true);
198 function step6() {
200 // Check everything
201 ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
202 ok(isActive(ctx.tab1Window), "Tab 1 should be active");
203 ok(isActive(ctx.tab1Window.frames[0]), "Tab1 iframe 0 should be active");
204 ok(isActive(ctx.tab1Window.frames[0].frames[0]), "Tab1 iframe 0 subiframe 0 should be active");
205 ok(isActive(ctx.tab1Window.frames[1]), "Tab1 iframe 1 should be active");
206 ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive");
207 ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive");
208 ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive");
210 // Go forward on tab 2
211 ctx.tab2Browser.addEventListener("pageshow",
212 autoRemovedListener(ctx.tab2Browser, "pageshow",
213 frameLoadWaiter(ctx.tab2Window, step7)),
214 true);
215 var tab2docshell = ctx.tab2Window.QueryInterface(Ci.nsIInterfaceRequestor)
216 .getInterface(Ci.nsIWebNavigation);
217 tab2docshell.goForward();
220 function step7() {
222 ctx.tab2Window = ctx.tab2Browser.contentWindow;
224 // Check everything
225 ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
226 ok(isActive(ctx.tab1Window), "Tab 1 should be active");
227 ok(isActive(ctx.tab1Window.frames[0]), "Tab1 iframe 0 should be active");
228 ok(isActive(ctx.tab1Window.frames[0].frames[0]), "Tab1 iframe 0 subiframe 0 should be active");
229 ok(isActive(ctx.tab1Window.frames[1]), "Tab1 iframe 1 should be active");
230 ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive");
231 ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive");
232 ok(!isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be inactive");
233 ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive");
235 // That's probably enough
236 allDone();
239 function allDone() {
241 // Close the tabs we made
242 gBrowser.removeCurrentTab();
243 gBrowser.tabContainer.advanceSelectedTab(1, true);
244 gBrowser.removeCurrentTab();
246 // Tell the framework we're done
247 finish();