|
1 // Test for bug 343515 - Need API for tabbrowsers to tell docshells they're visible/hidden |
|
2 |
|
3 // Globals |
|
4 var testPath = "http://mochi.test:8888/browser/docshell/test/navigation/"; |
|
5 var ctx = {}; |
|
6 |
|
7 // Helper function to check if a window is active |
|
8 function isActive(aWindow) { |
|
9 var docshell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor) |
|
10 .getInterface(Ci.nsIWebNavigation) |
|
11 .QueryInterface(Ci.nsIDocShell); |
|
12 return docshell.isActive; |
|
13 } |
|
14 |
|
15 // We need to wait until the page from each testcase is fully loaded, |
|
16 // including all of its descendant iframes. To do that we manually count |
|
17 // how many load events should happen on that page (one for the toplevel doc |
|
18 // and one for each subframe) and wait until we receive the expected number |
|
19 // of events. |
|
20 function nShotsListener(aElem, aType, aCallback, aCount) { |
|
21 let count = aCount; |
|
22 aElem.addEventListener(aType, function listenerCallback() { |
|
23 if (--count == 0) { |
|
24 aElem.removeEventListener(aType, listenerCallback, true); |
|
25 |
|
26 // aCallback is executed asynchronously, which is handy because load |
|
27 // events fire before mIsDocumentLoaded is actually set to true. :( |
|
28 executeSoon(aCallback); |
|
29 } |
|
30 }, true); |
|
31 } |
|
32 |
|
33 function oneShotListener(aElem, aType, aCallback) { |
|
34 nShotsListener(aElem, aType, aCallback, 1); |
|
35 } |
|
36 |
|
37 // Entry point from Mochikit |
|
38 function test() { |
|
39 |
|
40 // Lots of callbacks going on here |
|
41 waitForExplicitFinish(); |
|
42 |
|
43 // Begin the test |
|
44 step1(); |
|
45 } |
|
46 |
|
47 function step1() { |
|
48 |
|
49 // Get a handle on the initial tab |
|
50 ctx.tab0 = gBrowser.selectedTab; |
|
51 ctx.tab0Browser = gBrowser.getBrowserForTab(ctx.tab0); |
|
52 ctx.tab0Window = ctx.tab0Browser.contentWindow; |
|
53 |
|
54 // Our current tab should be active |
|
55 ok(isActive(ctx.tab0Window), "Tab 0 should be active at test start"); |
|
56 |
|
57 // Open a New Tab |
|
58 ctx.tab1 = gBrowser.addTab(testPath + "bug343515_pg1.html"); |
|
59 ctx.tab1Browser = gBrowser.getBrowserForTab(ctx.tab1); |
|
60 ctx.tab1Window = ctx.tab1Browser.contentWindow; |
|
61 oneShotListener(ctx.tab1Browser, "load", step2); |
|
62 } |
|
63 |
|
64 function step2() { |
|
65 is(testPath + "bug343515_pg1.html", ctx.tab1Browser.currentURI.spec, |
|
66 "Got expected tab 1 url in step 2"); |
|
67 |
|
68 // Our current tab should still be active |
|
69 ok(isActive(ctx.tab0Window), "Tab 0 should still be active"); |
|
70 ok(!isActive(ctx.tab1Window), "Tab 1 should not be active"); |
|
71 |
|
72 // Switch to tab 1 |
|
73 gBrowser.selectedTab = ctx.tab1; |
|
74 |
|
75 // Tab 1 should now be active |
|
76 ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive"); |
|
77 ok(isActive(ctx.tab1Window), "Tab 1 should be active"); |
|
78 |
|
79 // Open another tab |
|
80 ctx.tab2 = gBrowser.addTab(testPath + "bug343515_pg2.html"); |
|
81 ctx.tab2Browser = gBrowser.getBrowserForTab(ctx.tab2); |
|
82 ctx.tab2Window = ctx.tab2Browser.contentWindow; |
|
83 |
|
84 // bug343515_pg2.html consists of a page with two iframes, |
|
85 // which will therefore generate 3 load events. |
|
86 nShotsListener(ctx.tab2Browser, "load", step3, 3); |
|
87 } |
|
88 |
|
89 function step3() { |
|
90 is(testPath + "bug343515_pg2.html", ctx.tab2Browser.currentURI.spec, |
|
91 "Got expected tab 2 url in step 3"); |
|
92 |
|
93 // Tab 0 should be inactive, Tab 1 should be active |
|
94 ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive"); |
|
95 ok(isActive(ctx.tab1Window), "Tab 1 should be active"); |
|
96 |
|
97 // Tab 2's window _and_ its iframes should be inactive |
|
98 ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive"); |
|
99 is(ctx.tab2Window.frames.length, 2, "Tab 2 should have 2 iframes"); |
|
100 for (var i = 0; i < ctx.tab2Window.frames.length; i++) |
|
101 info("step 3, frame " + i + " info: " + ctx.tab2Window.frames[i].location); |
|
102 ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive"); |
|
103 ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive"); |
|
104 |
|
105 // Navigate tab 2 to a different page |
|
106 ctx.tab2Window.location = testPath + "bug343515_pg3.html"; |
|
107 |
|
108 // bug343515_pg3.html consists of a page with two iframes, one of which |
|
109 // contains another iframe, so there'll be a total of 4 load events |
|
110 nShotsListener(ctx.tab2Browser, "load", step4, 4); |
|
111 } |
|
112 |
|
113 function step4() { |
|
114 is(testPath + "bug343515_pg3.html", ctx.tab2Browser.currentURI.spec, |
|
115 "Got expected tab 2 url in step 4"); |
|
116 |
|
117 // Tab 0 should be inactive, Tab 1 should be active |
|
118 ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive"); |
|
119 ok(isActive(ctx.tab1Window), "Tab 1 should be active"); |
|
120 |
|
121 // Tab2 and all descendants should be inactive |
|
122 ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive"); |
|
123 is(ctx.tab2Window.frames.length, 2, "Tab 2 should have 2 iframes"); |
|
124 for (var i = 0; i < ctx.tab2Window.frames.length; i++) |
|
125 info("step 4, frame " + i + " info: " + ctx.tab2Window.frames[i].location); |
|
126 is(ctx.tab2Window.frames[0].frames.length, 1, "Tab 2 iframe 0 should have 1 iframes"); |
|
127 ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive"); |
|
128 ok(!isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be inactive"); |
|
129 ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive"); |
|
130 |
|
131 // Switch to Tab 2 |
|
132 gBrowser.selectedTab = ctx.tab2; |
|
133 |
|
134 // Check everything |
|
135 ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive"); |
|
136 ok(!isActive(ctx.tab1Window), "Tab 1 should be inactive"); |
|
137 ok(isActive(ctx.tab2Window), "Tab 2 should be active"); |
|
138 ok(isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be active"); |
|
139 ok(isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be active"); |
|
140 ok(isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be active"); |
|
141 |
|
142 // Go back |
|
143 oneShotListener(ctx.tab2Browser, "pageshow", step5); |
|
144 ctx.tab2Browser.goBack(); |
|
145 |
|
146 } |
|
147 |
|
148 function step5() { |
|
149 // Check everything |
|
150 ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive"); |
|
151 ok(!isActive(ctx.tab1Window), "Tab 1 should be inactive"); |
|
152 ok(isActive(ctx.tab2Window), "Tab 2 should be active"); |
|
153 ok(isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be active"); |
|
154 ok(isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be active"); |
|
155 |
|
156 // Switch to tab 1 |
|
157 gBrowser.selectedTab = ctx.tab1; |
|
158 |
|
159 // Navigate to page 3 |
|
160 ctx.tab1Window.location = testPath + "bug343515_pg3.html"; |
|
161 |
|
162 // bug343515_pg3.html consists of a page with two iframes, one of which |
|
163 // contains another iframe, so there'll be a total of 4 load events |
|
164 nShotsListener(ctx.tab1Browser, "load", step6, 4); |
|
165 } |
|
166 |
|
167 function step6() { |
|
168 |
|
169 // Check everything |
|
170 ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive"); |
|
171 ok(isActive(ctx.tab1Window), "Tab 1 should be active"); |
|
172 ok(isActive(ctx.tab1Window.frames[0]), "Tab1 iframe 0 should be active"); |
|
173 ok(isActive(ctx.tab1Window.frames[0].frames[0]), "Tab1 iframe 0 subiframe 0 should be active"); |
|
174 ok(isActive(ctx.tab1Window.frames[1]), "Tab1 iframe 1 should be active"); |
|
175 ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive"); |
|
176 ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive"); |
|
177 ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive"); |
|
178 |
|
179 // Go forward on tab 2 |
|
180 oneShotListener(ctx.tab2Browser, "pageshow", step7); |
|
181 var tab2docshell = ctx.tab2Window.QueryInterface(Ci.nsIInterfaceRequestor) |
|
182 .getInterface(Ci.nsIWebNavigation); |
|
183 tab2docshell.goForward(); |
|
184 } |
|
185 |
|
186 function step7() { |
|
187 |
|
188 ctx.tab2Window = ctx.tab2Browser.contentWindow; |
|
189 |
|
190 // Check everything |
|
191 ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive"); |
|
192 ok(isActive(ctx.tab1Window), "Tab 1 should be active"); |
|
193 ok(isActive(ctx.tab1Window.frames[0]), "Tab1 iframe 0 should be active"); |
|
194 ok(isActive(ctx.tab1Window.frames[0].frames[0]), "Tab1 iframe 0 subiframe 0 should be active"); |
|
195 ok(isActive(ctx.tab1Window.frames[1]), "Tab1 iframe 1 should be active"); |
|
196 ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive"); |
|
197 ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive"); |
|
198 ok(!isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be inactive"); |
|
199 ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive"); |
|
200 |
|
201 // That's probably enough |
|
202 allDone(); |
|
203 } |
|
204 |
|
205 function allDone() { |
|
206 |
|
207 // Close the tabs we made |
|
208 gBrowser.removeTab(ctx.tab1); |
|
209 gBrowser.removeTab(ctx.tab2); |
|
210 |
|
211 // Tell the framework we're done |
|
212 finish(); |
|
213 } |