Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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/. */
5 /**
6 * Checks that restoring the last browser window in session is actually
7 * working:
8 * 1.1) Open a new browser window
9 * 1.2) Add some tabs
10 * 1.3) Close that window
11 * 1.4) Opening another window
12 * --> State is restored
13 *
14 * 2.1) Open a new browser window
15 * 2.2) Add some tabs
16 * 2.3) Enter private browsing mode
17 * 2.4) Close the window while still in private browsing mode
18 * 2.5) Opening a new window
19 * --> State is not restored, because private browsing mode is still active
20 * 2.6) Leaving private browsing mode
21 * 2.7) Open another window
22 * --> State (that was before entering PBM) is restored
23 *
24 * 3.1) Open a new browser window
25 * 3.2) Add some tabs
26 * 3.4) Open some popups
27 * 3.5) Add another tab to one popup (so that it gets stored) and close it again
28 * 3.5) Close the browser window
29 * 3.6) Open another browser window
30 * --> State of the closed browser window, but not of the popup, is restored
31 *
32 * 4.1) Open a popup
33 * 4.2) Add another tab to the popup (so that it gets stored) and close it again
34 * 4.3) Open a window
35 * --> Nothing at all should be restored
36 *
37 * 5.1) Open two browser windows and close them again
38 * 5.2) undoCloseWindow() one
39 * 5.3) Open another browser window
40 * --> Nothing at all should be restored
41 *
42 * Checks the new notifications are correctly posted and processed, that is
43 * for each successful -requested a -granted is received, but omitted if
44 * -requested was cnceled
45 * Said notifications are:
46 * - browser-lastwindow-close-requested
47 * - browser-lastwindow-close-granted
48 * Tests are:
49 * 6) Cancel closing when first observe a -requested
50 * --> Window is kept open
51 * 7) Count the number of notifications
52 * --> count(-requested) == count(-granted) + 1
53 * --> (The first -requested was canceled, so off-by-one)
54 * 8) (Mac only) Mac version of Test 5 additionally preparing Test 6
55 *
56 * @see https://bugzilla.mozilla.org/show_bug.cgi?id=354894
57 * @note It is implicitly tested that restoring the last window works when
58 * non-browser windows are around. The "Run Tests" window as well as the main
59 * browser window (wherein the test code gets executed) won't be considered
60 * browser windows. To achiveve this said main browser window has it's windowtype
61 * attribute modified so that it's not considered a browser window any longer.
62 * This is crucial, because otherwise there would be two browser windows around,
63 * said main test window and the one opened by the tests, and hence the new
64 * logic wouldn't be executed at all.
65 * @note Mac only tests the new notifications, as restoring the last window is
66 * not enabled on that platform (platform shim; the application is kept running
67 * although there are no windows left)
68 * @note There is a difference when closing a browser window with
69 * BrowserTryToCloseWindow() as opposed to close(). The former will make
70 * nsSessionStore restore a window next time it gets a chance and will post
71 * notifications. The latter won't.
72 */
74 function browserWindowsCount(expected, msg) {
75 if (typeof expected == "number")
76 expected = [expected, expected];
77 let count = 0;
78 let e = Services.wm.getEnumerator("navigator:browser");
79 while (e.hasMoreElements()) {
80 if (!e.getNext().closed)
81 ++count;
82 }
83 is(count, expected[0], msg + " (nsIWindowMediator)");
84 let state = ss.getBrowserState();
85 is(JSON.parse(state).windows.length, expected[1], msg + " (getBrowserState)");
86 }
88 function test() {
89 browserWindowsCount(1, "Only one browser window should be open initially");
91 waitForExplicitFinish();
92 // This test takes some time to run, and it could timeout randomly.
93 // So we require a longer timeout. See bug 528219.
94 requestLongerTimeout(2);
96 // Some urls that might be opened in tabs and/or popups
97 // Do not use about:blank:
98 // That one is reserved for special purposes in the tests
99 const TEST_URLS = ["about:mozilla", "about:buildconfig"];
101 // Number of -request notifications to except
102 // remember to adjust when adding new tests
103 const NOTIFICATIONS_EXPECTED = 6;
105 // Window features of popup windows
106 const POPUP_FEATURES = "toolbar=no,resizable=no,status=no";
108 // Window features of browser windows
109 const CHROME_FEATURES = "chrome,all,dialog=no";
111 // Store the old window type for cleanup
112 let oldWinType = "";
113 // Store the old tabs.warnOnClose pref so that we may reset it during
114 // cleanup
115 let oldWarnTabsOnClose = gPrefService.getBoolPref("browser.tabs.warnOnClose");
117 // Observe these, and also use to count the number of hits
118 let observing = {
119 "browser-lastwindow-close-requested": 0,
120 "browser-lastwindow-close-granted": 0
121 };
123 /**
124 * Helper: Will observe and handle the notifications for us
125 */
126 let hitCount = 0;
127 function observer(aCancel, aTopic, aData) {
128 // count so that we later may compare
129 observing[aTopic]++;
131 // handle some tests
132 if (++hitCount == 1) {
133 // Test 6
134 aCancel.QueryInterface(Ci.nsISupportsPRBool).data = true;
135 }
136 }
138 /**
139 * Helper: Sets prefs as the testsuite requires
140 * @note Will be reset in cleanTestSuite just before finishing the tests
141 */
142 function setPrefs() {
143 gPrefService.setIntPref("browser.startup.page", 3);
144 gPrefService.setBoolPref(
145 "browser.privatebrowsing.keep_current_session",
146 true
147 );
148 gPrefService.setBoolPref("browser.tabs.warnOnClose", false);
149 }
151 /**
152 * Helper: Sets up this testsuite
153 */
154 function setupTestsuite(testFn) {
155 // Register our observers
156 for (let o in observing)
157 Services.obs.addObserver(observer, o, false);
159 // Make the main test window not count as a browser window any longer
160 oldWinType = document.documentElement.getAttribute("windowtype");
161 document.documentElement.setAttribute("windowtype", "navigator:testrunner");
162 }
164 /**
165 * Helper: Cleans up behind the testsuite
166 */
167 function cleanupTestsuite(callback) {
168 // Finally remove observers again
169 for (let o in observing)
170 Services.obs.removeObserver(observer, o);
172 // Reset the prefs we touched
173 [
174 "browser.startup.page",
175 "browser.privatebrowsing.keep_current_session"
176 ].forEach(function (pref) {
177 if (gPrefService.prefHasUserValue(pref))
178 gPrefService.clearUserPref(pref);
179 });
180 gPrefService.setBoolPref("browser.tabs.warnOnClose", oldWarnTabsOnClose);
182 // Reset the window type
183 document.documentElement.setAttribute("windowtype", oldWinType);
184 }
186 /**
187 * Helper: sets the prefs and a new window with our test tabs
188 */
189 function setupTestAndRun(aIsPrivateWindow, testFn) {
190 // Prepare the prefs
191 setPrefs();
193 // Prepare a window; open it and add more tabs
194 let options = {};
195 if (aIsPrivateWindow) {
196 options = {private: true};
197 }
199 whenNewWindowLoaded(options, function (newWin) {
200 TEST_URLS.forEach(function (url) {
201 newWin.gBrowser.addTab(url);
202 });
204 executeSoon(() => testFn(newWin));
205 });
206 }
208 /**
209 * Test 1: Normal in-session restore
210 * @note: Non-Mac only
211 */
212 function testOpenCloseNormal(nextFn) {
213 setupTestAndRun(false, function(newWin) {
214 // Close the window
215 // window.close doesn't push any close events,
216 // so use BrowserTryToCloseWindow
217 newWin.BrowserTryToCloseWindow();
219 // The first request to close is denied by our observer (Test 6)
220 ok(!newWin.closed, "First close request was denied");
221 if (!newWin.closed) {
222 newWin.BrowserTryToCloseWindow();
223 ok(newWin.closed, "Second close request was granted");
224 }
226 // Open a new window
227 // The previously closed window should be restored
228 whenNewWindowLoaded({}, function (newWin) {
229 is(newWin.gBrowser.browsers.length, TEST_URLS.length + 1,
230 "Restored window in-session with otherpopup windows around");
232 // Cleanup
233 newWin.close();
235 // Next please
236 executeSoon(nextFn);
237 });
238 });
239 }
241 /**
242 * Test 2: PrivateBrowsing in-session restore
243 * @note: Non-Mac only
244 */
245 function testOpenClosePrivateBrowsing(nextFn) {
246 setupTestAndRun(false, function(newWin) {
247 // Close the window
248 newWin.BrowserTryToCloseWindow();
250 // Enter private browsing mode
251 // Open a new window.
252 // The previously closed window should NOT be restored
253 whenNewWindowLoaded({private: true}, function (newWin) {
254 is(newWin.gBrowser.browsers.length, 1,
255 "Did not restore in private browing mode");
257 // Cleanup
258 newWin.BrowserTryToCloseWindow();
260 // Exit private browsing mode again
261 whenNewWindowLoaded({}, function (newWin) {
262 is(newWin.gBrowser.browsers.length, TEST_URLS.length + 1,
263 "Restored after leaving private browsing again");
265 newWin.close();
267 // Next please
268 executeSoon(nextFn);
269 });
270 });
271 });
272 }
274 /**
275 * Test 3: Open some popup windows to check those aren't restored, but
276 * the browser window is
277 * @note: Non-Mac only
278 */
279 function testOpenCloseWindowAndPopup(nextFn) {
280 setupTestAndRun(false, function(newWin) {
281 // open some popups
282 let popup = openDialog(location, "popup", POPUP_FEATURES, TEST_URLS[0]);
283 let popup2 = openDialog(location, "popup2", POPUP_FEATURES, TEST_URLS[1]);
284 popup2.addEventListener("load", function() {
285 popup2.removeEventListener("load", arguments.callee, false);
286 popup2.gBrowser.addEventListener("load", function() {
287 popup2.gBrowser.removeEventListener("load", arguments.callee, true);
288 popup2.gBrowser.addTab(TEST_URLS[0]);
289 // close the window
290 newWin.BrowserTryToCloseWindow();
292 // Close the popup window
293 // The test is successful when not this popup window is restored
294 // but instead newWin
295 popup2.close();
297 // open a new window the previously closed window should be restored to
298 whenNewWindowLoaded({}, function (newWin) {
299 is(newWin.gBrowser.browsers.length, TEST_URLS.length + 1,
300 "Restored window and associated tabs in session");
302 // Cleanup
303 newWin.close();
304 popup.close();
306 // Next please
307 executeSoon(nextFn);
308 });
309 }, true);
310 }, false);
311 });
312 }
314 /**
315 * Test 4: Open some popup window to check it isn't restored.
316 * Instead nothing at all should be restored
317 * @note: Non-Mac only
318 */
319 function testOpenCloseOnlyPopup(nextFn) {
320 // prepare the prefs
321 setPrefs();
323 // This will cause nsSessionStore to restore a window the next time it
324 // gets a chance.
325 let popup = openDialog(location, "popup", POPUP_FEATURES, TEST_URLS[1]);
326 popup.addEventListener("load", function() {
327 this.removeEventListener("load", arguments.callee, true);
328 is(popup.gBrowser.browsers.length, 1,
329 "Did not restore the popup window (1)");
330 popup.BrowserTryToCloseWindow();
332 // Real tests
333 popup = openDialog(location, "popup", POPUP_FEATURES, TEST_URLS[1]);
334 popup.addEventListener("load", function() {
335 popup.removeEventListener("load", arguments.callee, false);
336 popup.gBrowser.addEventListener("load", function() {
337 popup.gBrowser.removeEventListener("load", arguments.callee, true);
338 popup.gBrowser.addTab(TEST_URLS[0]);
340 is(popup.gBrowser.browsers.length, 2,
341 "Did not restore to the popup window (2)");
343 // Close the popup window
344 // The test is successful when not this popup window is restored
345 // but instead a new window is opened without restoring anything
346 popup.close();
348 whenNewWindowLoaded({}, function (newWin) {
349 isnot(newWin.gBrowser.browsers.length, 2,
350 "Did not restore the popup window");
351 is(TEST_URLS.indexOf(newWin.gBrowser.browsers[0].currentURI.spec), -1,
352 "Did not restore the popup window (2)");
354 // Cleanup
355 newWin.close();
357 // Next please
358 executeSoon(nextFn);
359 });
360 }, true);
361 }, false);
362 }, true);
363 }
365 /**
366 * Test 5: Open some windows and do undoCloseWindow. This should prevent any
367 * restoring later in the test
368 * @note: Non-Mac only
369 */
370 function testOpenCloseRestoreFromPopup(nextFn) {
371 setupTestAndRun(false, function(newWin) {
372 setupTestAndRun(false, function(newWin2) {
373 newWin.BrowserTryToCloseWindow();
374 newWin2.BrowserTryToCloseWindow();
376 browserWindowsCount([0, 1], "browser windows while running testOpenCloseRestoreFromPopup");
378 newWin = undoCloseWindow(0);
380 whenNewWindowLoaded({}, function (newWin2) {
381 is(newWin2.gBrowser.browsers.length, 1,
382 "Did not restore, as undoCloseWindow() was last called");
383 is(TEST_URLS.indexOf(newWin2.gBrowser.browsers[0].currentURI.spec), -1,
384 "Did not restore, as undoCloseWindow() was last called (2)");
386 browserWindowsCount([2, 3], "browser windows while running testOpenCloseRestoreFromPopup");
388 // Cleanup
389 newWin.close();
390 newWin2.close();
392 browserWindowsCount([0, 1], "browser windows while running testOpenCloseRestoreFromPopup");
394 // Next please
395 executeSoon(nextFn);
396 });
397 });
398 });
399 }
401 /**
402 * Test 7: Check whether the right number of notifications was received during
403 * the tests
404 */
405 function testNotificationCount(nextFn) {
406 is(observing["browser-lastwindow-close-requested"], NOTIFICATIONS_EXPECTED,
407 "browser-lastwindow-close-requested notifications observed");
409 // -request must be one more as we cancel the first one we hit,
410 // and hence won't produce a corresponding -grant
411 // @see observer.observe
412 is(observing["browser-lastwindow-close-requested"],
413 observing["browser-lastwindow-close-granted"] + 1,
414 "Notification count for -request and -grant matches");
416 executeSoon(nextFn);
417 }
419 /**
420 * Test 8: Test if closing can be denied on Mac
421 * Futhermore prepares the testNotificationCount test (Test 7)
422 * @note: Mac only
423 */
424 function testMacNotifications(nextFn, iteration) {
425 iteration = iteration || 1;
426 setupTestAndRun(false, function(newWin) {
427 // close the window
428 // window.close doesn't push any close events,
429 // so use BrowserTryToCloseWindow
430 newWin.BrowserTryToCloseWindow();
431 if (iteration == 1) {
432 ok(!newWin.closed, "First close attempt denied");
433 if (!newWin.closed) {
434 newWin.BrowserTryToCloseWindow();
435 ok(newWin.closed, "Second close attempt granted");
436 }
437 }
439 if (iteration < NOTIFICATIONS_EXPECTED - 1) {
440 executeSoon(function() testMacNotifications(nextFn, ++iteration));
441 }
442 else {
443 executeSoon(nextFn);
444 }
445 });
446 }
448 // Execution starts here
450 setupTestsuite();
451 if (navigator.platform.match(/Mac/)) {
452 // Mac tests
453 testMacNotifications(function () {
454 testNotificationCount(function () {
455 cleanupTestsuite();
456 browserWindowsCount(1, "Only one browser window should be open eventually");
457 finish();
458 });
459 });
460 }
461 else {
462 // Non-Mac Tests
463 testOpenCloseNormal(function () {
464 browserWindowsCount([0, 1], "browser windows after testOpenCloseNormal");
465 testOpenClosePrivateBrowsing(function () {
466 browserWindowsCount([0, 1], "browser windows after testOpenClosePrivateBrowsing");
467 testOpenCloseWindowAndPopup(function () {
468 browserWindowsCount([0, 1], "browser windows after testOpenCloseWindowAndPopup");
469 testOpenCloseOnlyPopup(function () {
470 browserWindowsCount([0, 1], "browser windows after testOpenCloseOnlyPopup");
471 testOpenCloseRestoreFromPopup(function () {
472 browserWindowsCount([0, 1], "browser windows after testOpenCloseRestoreFromPopup");
473 testNotificationCount(function () {
474 cleanupTestsuite();
475 browserWindowsCount(1, "browser windows after testNotificationCount");
476 finish();
477 });
478 });
479 });
480 });
481 });
482 });
483 }
484 }