|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 const stateBackup = JSON.parse(ss.getBrowserState()); |
|
6 const testState = { |
|
7 windows: [{ |
|
8 tabs: [ |
|
9 { entries: [{ url: "about:blank" }] }, |
|
10 { entries: [{ url: "about:rights" }] } |
|
11 ] |
|
12 }] |
|
13 }; |
|
14 const lameMultiWindowState = { windows: [ |
|
15 { |
|
16 tabs: [ |
|
17 { entries: [{ url: "http://example.org#1" }], extData: { "uniq": r() } }, |
|
18 { entries: [{ url: "http://example.org#2" }], extData: { "uniq": r() } }, |
|
19 { entries: [{ url: "http://example.org#3" }], extData: { "uniq": r() } }, |
|
20 { entries: [{ url: "http://example.org#4" }], extData: { "uniq": r() } } |
|
21 ], |
|
22 selected: 1 |
|
23 }, |
|
24 { |
|
25 tabs: [ |
|
26 { entries: [{ url: "http://example.com#1" }], extData: { "uniq": r() } }, |
|
27 { entries: [{ url: "http://example.com#2" }], extData: { "uniq": r() } }, |
|
28 { entries: [{ url: "http://example.com#3" }], extData: { "uniq": r() } }, |
|
29 { entries: [{ url: "http://example.com#4" }], extData: { "uniq": r() } }, |
|
30 ], |
|
31 selected: 3 |
|
32 } |
|
33 ] }; |
|
34 |
|
35 |
|
36 function getOuterWindowID(aWindow) { |
|
37 return aWindow.QueryInterface(Ci.nsIInterfaceRequestor). |
|
38 getInterface(Ci.nsIDOMWindowUtils).outerWindowID; |
|
39 } |
|
40 |
|
41 function test() { |
|
42 /** Test for Bug 615394 - Session Restore should notify when it is beginning and ending a restore **/ |
|
43 waitForExplicitFinish(); |
|
44 // Preemptively extend the timeout to prevent [orange] |
|
45 requestLongerTimeout(2); |
|
46 runNextTest(); |
|
47 } |
|
48 |
|
49 |
|
50 let tests = [ |
|
51 test_setTabState, |
|
52 test_duplicateTab, |
|
53 test_undoCloseTab, |
|
54 test_setWindowState, |
|
55 test_setBrowserState, |
|
56 test_undoCloseWindow |
|
57 ]; |
|
58 function runNextTest() { |
|
59 // set an empty state & run the next test, or finish |
|
60 if (tests.length) { |
|
61 // Enumerate windows and close everything but our primary window. We can't |
|
62 // use waitForFocus() because apparently it's buggy. See bug 599253. |
|
63 var windowsEnum = Services.wm.getEnumerator("navigator:browser"); |
|
64 while (windowsEnum.hasMoreElements()) { |
|
65 var currentWindow = windowsEnum.getNext(); |
|
66 if (currentWindow != window) { |
|
67 currentWindow.close(); |
|
68 } |
|
69 } |
|
70 |
|
71 // If we closed a window, give it time to close |
|
72 executeSoon(function() { |
|
73 let currentTest = tests.shift(); |
|
74 info("prepping for " + currentTest.name); |
|
75 waitForBrowserState(testState, currentTest); |
|
76 }); |
|
77 } |
|
78 else { |
|
79 waitForBrowserState(stateBackup, finish); |
|
80 } |
|
81 } |
|
82 |
|
83 /** ACTUAL TESTS **/ |
|
84 |
|
85 function test_setTabState() { |
|
86 let tab = gBrowser.tabs[1]; |
|
87 let newTabState = JSON.stringify({ entries: [{ url: "http://example.org" }], extData: { foo: "bar" } }); |
|
88 let busyEventCount = 0; |
|
89 let readyEventCount = 0; |
|
90 |
|
91 function onSSWindowStateBusy(aEvent) { |
|
92 busyEventCount++; |
|
93 } |
|
94 |
|
95 function onSSWindowStateReady(aEvent) { |
|
96 readyEventCount++; |
|
97 is(ss.getTabValue(tab, "foo"), "bar"); |
|
98 ss.setTabValue(tab, "baz", "qux"); |
|
99 } |
|
100 |
|
101 function onSSTabRestored(aEvent) { |
|
102 is(busyEventCount, 1); |
|
103 is(readyEventCount, 1); |
|
104 is(ss.getTabValue(tab, "baz"), "qux"); |
|
105 is(tab.linkedBrowser.currentURI.spec, "http://example.org/"); |
|
106 |
|
107 window.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); |
|
108 window.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false); |
|
109 gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored, false); |
|
110 |
|
111 runNextTest(); |
|
112 } |
|
113 |
|
114 window.addEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); |
|
115 window.addEventListener("SSWindowStateReady", onSSWindowStateReady, false); |
|
116 gBrowser.tabContainer.addEventListener("SSTabRestored", onSSTabRestored, false); |
|
117 ss.setTabState(tab, newTabState); |
|
118 } |
|
119 |
|
120 |
|
121 function test_duplicateTab() { |
|
122 let tab = gBrowser.tabs[1]; |
|
123 let busyEventCount = 0; |
|
124 let readyEventCount = 0; |
|
125 let newTab; |
|
126 |
|
127 // We'll look to make sure this value is on the duplicated tab |
|
128 ss.setTabValue(tab, "foo", "bar"); |
|
129 |
|
130 function onSSWindowStateBusy(aEvent) { |
|
131 busyEventCount++; |
|
132 } |
|
133 |
|
134 function onSSWindowStateReady(aEvent) { |
|
135 newTab = gBrowser.tabs[2]; |
|
136 readyEventCount++; |
|
137 is(ss.getTabValue(newTab, "foo"), "bar"); |
|
138 ss.setTabValue(newTab, "baz", "qux"); |
|
139 } |
|
140 |
|
141 function onSSTabRestored(aEvent) { |
|
142 is(busyEventCount, 1); |
|
143 is(readyEventCount, 1); |
|
144 is(ss.getTabValue(newTab, "baz"), "qux"); |
|
145 is(newTab.linkedBrowser.currentURI.spec, "about:rights"); |
|
146 |
|
147 window.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); |
|
148 window.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false); |
|
149 gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored, false); |
|
150 |
|
151 runNextTest(); |
|
152 } |
|
153 |
|
154 window.addEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); |
|
155 window.addEventListener("SSWindowStateReady", onSSWindowStateReady, false); |
|
156 gBrowser.tabContainer.addEventListener("SSTabRestored", onSSTabRestored, false); |
|
157 |
|
158 newTab = ss.duplicateTab(window, tab); |
|
159 } |
|
160 |
|
161 |
|
162 function test_undoCloseTab() { |
|
163 let tab = gBrowser.tabs[1], |
|
164 busyEventCount = 0, |
|
165 readyEventCount = 0, |
|
166 reopenedTab; |
|
167 |
|
168 ss.setTabValue(tab, "foo", "bar"); |
|
169 |
|
170 function onSSWindowStateBusy(aEvent) { |
|
171 busyEventCount++; |
|
172 } |
|
173 |
|
174 function onSSWindowStateReady(aEvent) { |
|
175 reopenedTab = gBrowser.tabs[1]; |
|
176 readyEventCount++; |
|
177 is(ss.getTabValue(reopenedTab, "foo"), "bar"); |
|
178 ss.setTabValue(reopenedTab, "baz", "qux"); |
|
179 } |
|
180 |
|
181 function onSSTabRestored(aEvent) { |
|
182 is(busyEventCount, 1); |
|
183 is(readyEventCount, 1); |
|
184 is(ss.getTabValue(reopenedTab, "baz"), "qux"); |
|
185 is(reopenedTab.linkedBrowser.currentURI.spec, "about:rights"); |
|
186 |
|
187 window.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); |
|
188 window.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false); |
|
189 gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored, false); |
|
190 |
|
191 runNextTest(); |
|
192 } |
|
193 |
|
194 window.addEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); |
|
195 window.addEventListener("SSWindowStateReady", onSSWindowStateReady, false); |
|
196 gBrowser.tabContainer.addEventListener("SSTabRestored", onSSTabRestored, false); |
|
197 |
|
198 gBrowser.removeTab(tab); |
|
199 reopenedTab = ss.undoCloseTab(window, 0); |
|
200 } |
|
201 |
|
202 |
|
203 function test_setWindowState() { |
|
204 let testState = { |
|
205 windows: [{ |
|
206 tabs: [ |
|
207 { entries: [{ url: "about:mozilla" }], extData: { "foo": "bar" } }, |
|
208 { entries: [{ url: "http://example.org" }], extData: { "baz": "qux" } } |
|
209 ] |
|
210 }] |
|
211 }; |
|
212 |
|
213 let busyEventCount = 0, |
|
214 readyEventCount = 0, |
|
215 tabRestoredCount = 0; |
|
216 |
|
217 function onSSWindowStateBusy(aEvent) { |
|
218 busyEventCount++; |
|
219 } |
|
220 |
|
221 function onSSWindowStateReady(aEvent) { |
|
222 readyEventCount++; |
|
223 is(ss.getTabValue(gBrowser.tabs[0], "foo"), "bar"); |
|
224 is(ss.getTabValue(gBrowser.tabs[1], "baz"), "qux"); |
|
225 } |
|
226 |
|
227 function onSSTabRestored(aEvent) { |
|
228 if (++tabRestoredCount < 2) |
|
229 return; |
|
230 |
|
231 is(busyEventCount, 1); |
|
232 is(readyEventCount, 1); |
|
233 is(gBrowser.tabs[0].linkedBrowser.currentURI.spec, "about:mozilla"); |
|
234 is(gBrowser.tabs[1].linkedBrowser.currentURI.spec, "http://example.org/"); |
|
235 |
|
236 window.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); |
|
237 window.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false); |
|
238 gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored, false); |
|
239 |
|
240 runNextTest(); |
|
241 } |
|
242 |
|
243 window.addEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); |
|
244 window.addEventListener("SSWindowStateReady", onSSWindowStateReady, false); |
|
245 gBrowser.tabContainer.addEventListener("SSTabRestored", onSSTabRestored, false); |
|
246 |
|
247 ss.setWindowState(window, JSON.stringify(testState), true); |
|
248 } |
|
249 |
|
250 |
|
251 function test_setBrowserState() { |
|
252 // We'll track events per window so we are sure that they are each happening once |
|
253 // pre window. |
|
254 let windowEvents = {}; |
|
255 windowEvents[getOuterWindowID(window)] = { busyEventCount: 0, readyEventCount: 0 }; |
|
256 |
|
257 // waitForBrowserState does it's own observing for windows, but doesn't attach |
|
258 // the listeners we want here, so do it ourselves. |
|
259 let newWindow; |
|
260 function windowObserver(aSubject, aTopic, aData) { |
|
261 if (aTopic == "domwindowopened") { |
|
262 newWindow = aSubject.QueryInterface(Ci.nsIDOMWindow); |
|
263 newWindow.addEventListener("load", function() { |
|
264 newWindow.removeEventListener("load", arguments.callee, false); |
|
265 |
|
266 Services.ww.unregisterNotification(windowObserver); |
|
267 |
|
268 windowEvents[getOuterWindowID(newWindow)] = { busyEventCount: 0, readyEventCount: 0 }; |
|
269 |
|
270 newWindow.addEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); |
|
271 newWindow.addEventListener("SSWindowStateReady", onSSWindowStateReady, false); |
|
272 }, false); |
|
273 } |
|
274 } |
|
275 |
|
276 function onSSWindowStateBusy(aEvent) { |
|
277 windowEvents[getOuterWindowID(aEvent.originalTarget)].busyEventCount++; |
|
278 } |
|
279 |
|
280 function onSSWindowStateReady(aEvent) { |
|
281 windowEvents[getOuterWindowID(aEvent.originalTarget)].readyEventCount++; |
|
282 } |
|
283 |
|
284 window.addEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); |
|
285 window.addEventListener("SSWindowStateReady", onSSWindowStateReady, false); |
|
286 Services.ww.registerNotification(windowObserver); |
|
287 |
|
288 waitForBrowserState(lameMultiWindowState, function() { |
|
289 let checkedWindows = 0; |
|
290 for (let id of Object.keys(windowEvents)) { |
|
291 let winEvents = windowEvents[id]; |
|
292 is(winEvents.busyEventCount, 1, |
|
293 "[test_setBrowserState] window" + id + " busy event count correct"); |
|
294 is(winEvents.readyEventCount, 1, |
|
295 "[test_setBrowserState] window" + id + " ready event count correct"); |
|
296 checkedWindows++; |
|
297 } |
|
298 is(checkedWindows, 2, |
|
299 "[test_setBrowserState] checked 2 windows"); |
|
300 window.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); |
|
301 window.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false); |
|
302 newWindow.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); |
|
303 newWindow.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false); |
|
304 runNextTest(); |
|
305 }); |
|
306 } |
|
307 |
|
308 |
|
309 function test_undoCloseWindow() { |
|
310 let newWindow, reopenedWindow; |
|
311 |
|
312 function firstWindowObserver(aSubject, aTopic, aData) { |
|
313 if (aTopic == "domwindowopened") { |
|
314 newWindow = aSubject.QueryInterface(Ci.nsIDOMWindow); |
|
315 Services.ww.unregisterNotification(firstWindowObserver); |
|
316 } |
|
317 } |
|
318 Services.ww.registerNotification(firstWindowObserver); |
|
319 |
|
320 waitForBrowserState(lameMultiWindowState, function() { |
|
321 // Close the window which isn't window |
|
322 newWindow.close(); |
|
323 // Now give it time to close |
|
324 executeSoon(function() { |
|
325 reopenedWindow = ss.undoCloseWindow(0); |
|
326 reopenedWindow.addEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); |
|
327 reopenedWindow.addEventListener("SSWindowStateReady", onSSWindowStateReady, false); |
|
328 |
|
329 reopenedWindow.addEventListener("load", function() { |
|
330 reopenedWindow.removeEventListener("load", arguments.callee, false); |
|
331 |
|
332 reopenedWindow.gBrowser.tabContainer.addEventListener("SSTabRestored", onSSTabRestored, false); |
|
333 }, false); |
|
334 }); |
|
335 }); |
|
336 |
|
337 let busyEventCount = 0, |
|
338 readyEventCount = 0, |
|
339 tabRestoredCount = 0; |
|
340 // These will listen to the reopened closed window... |
|
341 function onSSWindowStateBusy(aEvent) { |
|
342 busyEventCount++; |
|
343 } |
|
344 |
|
345 function onSSWindowStateReady(aEvent) { |
|
346 readyEventCount++; |
|
347 } |
|
348 |
|
349 function onSSTabRestored(aEvent) { |
|
350 if (++tabRestoredCount < 4) |
|
351 return; |
|
352 |
|
353 is(busyEventCount, 1); |
|
354 is(readyEventCount, 1); |
|
355 |
|
356 reopenedWindow.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); |
|
357 reopenedWindow.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false); |
|
358 reopenedWindow.gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored, false); |
|
359 |
|
360 reopenedWindow.close(); |
|
361 |
|
362 // Give it time to close |
|
363 executeSoon(runNextTest); |
|
364 } |
|
365 } |