1 // Test for bug 343515 - Need API for tabbrowsers to tell docshells they're visible/hidden
4 var testPath
= "http://mochi.test:8888/browser/docshell/test/navigation/";
5 var Ci
= Components
.interfaces
;
6 var Cc
= Components
.classes
;
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
21 function autoRemovedListener(aElem
, aType
, aCallback
) {
25 var callback
= aCallback
;
28 elem
.removeEventListener(type
, remover
, true);
29 executeSoon(callback
);
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
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")
61 curr
.addEventListener("load", autoRemovedListener(curr
, "load", frameLoadCallback
), true);
65 // Otherwise, we're all done. Call the final callback
69 return frameLoadCallback
;
72 // Entry point from Mochikit
75 // Lots of callbacks going on here
76 waitForExplicitFinish();
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");
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
),
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");
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");
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
)),
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
)),
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");
159 gBrowser
.selectedTab
= ctx
.tab2
;
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");
170 ctx
.tab2Browser
.addEventListener("pageshow",
171 autoRemovedListener(ctx
.tab2Browser
, "pageshow",
172 frameLoadWaiter(ctx
.tab2Window
, step5
)),
174 ctx
.tab2Browser
.goBack();
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");
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
)),
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
)),
215 var tab2docshell
= ctx
.tab2Window
.QueryInterface(Ci
.nsIInterfaceRequestor
)
216 .getInterface(Ci
.nsIWebNavigation
);
217 tab2docshell
.goForward();
222 ctx
.tab2Window
= ctx
.tab2Browser
.contentWindow
;
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
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