forked from mirrors/gecko-dev
		
	 bf9d434a13
			
		
	
	
		bf9d434a13
		
	
	
	
	
		
			
			MozReview-Commit-ID: 8spvIOus9ai --HG-- rename : browser/components/sessionstore/nsSessionStore.manifest => browser/components/sessionstore/nsSessionStartup.manifest extra : rebase_source : fc353af87bd620b7039d3e6241cc60c3788e3da6
		
			
				
	
	
		
			230 lines
		
	
	
	
		
			7.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			230 lines
		
	
	
	
		
			7.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| // Mirrors WINDOW_ATTRIBUTES IN SessionStore.jsm
 | |
| const WINDOW_ATTRIBUTES = ["width", "height", "screenX", "screenY", "sizemode"];
 | |
| 
 | |
| var stateBackup = ss.getBrowserState();
 | |
| 
 | |
| var originalWarnOnClose = Services.prefs.getBoolPref("browser.tabs.warnOnClose");
 | |
| var originalStartupPage = Services.prefs.getIntPref("browser.startup.page");
 | |
| var originalWindowType = document.documentElement.getAttribute("windowtype");
 | |
| 
 | |
| var gotLastWindowClosedTopic = false;
 | |
| var shouldPinTab = false;
 | |
| var shouldOpenTabs = false;
 | |
| var shouldCloseTab = false;
 | |
| var testNum = 0;
 | |
| var afterTestCallback;
 | |
| 
 | |
| // Set state so we know the closed windows content
 | |
| var testState = {
 | |
|   windows: [
 | |
|     { tabs: [{ entries: [{ url: "http://example.org" }] }] }
 | |
|   ],
 | |
|   _closedWindows: []
 | |
| };
 | |
| 
 | |
| // We'll push a set of conditions and callbacks into this array
 | |
| // Ideally we would also test win/linux under a complete set of conditions, but
 | |
| // the tests for osx mirror the other set of conditions possible on win/linux.
 | |
| var tests = [];
 | |
| 
 | |
| // the third & fourth test share a condition check, keep it DRY
 | |
| function checkOSX34Generator(num) {
 | |
|   return function(aPreviousState, aCurState) {
 | |
|     // In here, we should have restored the pinned tab, so only the unpinned tab
 | |
|     // should be in aCurState. So let's shape our expectations.
 | |
|     let expectedState = JSON.parse(aPreviousState);
 | |
|     expectedState[0].tabs.shift();
 | |
|     // size attributes are stripped out in _prepDataForDeferredRestore in SessionStore.jsm.
 | |
|     // This isn't the best approach, but neither is comparing JSON strings
 | |
|     WINDOW_ATTRIBUTES.forEach(attr => delete expectedState[0][attr]);
 | |
| 
 | |
|     is(aCurState, JSON.stringify(expectedState),
 | |
|        "test #" + num + ": closedWindowState is as expected");
 | |
|   };
 | |
| }
 | |
| function checkNoWindowsGenerator(num) {
 | |
|   return function(aPreviousState, aCurState) {
 | |
|     is(aCurState, "[]", "test #" + num + ": there should be no closedWindowsLeft");
 | |
|   };
 | |
| }
 | |
| 
 | |
| // The first test has 0 pinned tabs and 1 unpinned tab
 | |
| tests.push({
 | |
|   pinned: false,
 | |
|   extra: false,
 | |
|   close: false,
 | |
|   checkWinLin: checkNoWindowsGenerator(1),
 | |
|   checkOSX(aPreviousState, aCurState) {
 | |
|     is(aCurState, aPreviousState, "test #1: closed window state is unchanged");
 | |
|   }
 | |
| });
 | |
| 
 | |
| // The second test has 1 pinned tab and 0 unpinned tabs.
 | |
| tests.push({
 | |
|   pinned: true,
 | |
|   extra: false,
 | |
|   close: false,
 | |
|   checkWinLin: checkNoWindowsGenerator(2),
 | |
|   checkOSX: checkNoWindowsGenerator(2)
 | |
| });
 | |
| 
 | |
| // The third test has 1 pinned tab and 2 unpinned tabs.
 | |
| tests.push({
 | |
|   pinned: true,
 | |
|   extra: true,
 | |
|   close: false,
 | |
|   checkWinLin: checkNoWindowsGenerator(3),
 | |
|   checkOSX: checkOSX34Generator(3)
 | |
| });
 | |
| 
 | |
| // The fourth test has 1 pinned tab, 2 unpinned tabs, and closes one unpinned tab.
 | |
| tests.push({
 | |
|   pinned: true,
 | |
|   extra: true,
 | |
|   close: "one",
 | |
|   checkWinLin: checkNoWindowsGenerator(4),
 | |
|   checkOSX: checkOSX34Generator(4)
 | |
| });
 | |
| 
 | |
| // The fifth test has 1 pinned tab, 2 unpinned tabs, and closes both unpinned tabs.
 | |
| tests.push({
 | |
|   pinned: true,
 | |
|   extra: true,
 | |
|   close: "both",
 | |
|   checkWinLin: checkNoWindowsGenerator(5),
 | |
|   checkOSX: checkNoWindowsGenerator(5)
 | |
| });
 | |
| 
 | |
| 
 | |
| function test() {
 | |
|   /** Test for Bug 589246 - Closed window state getting corrupted when closing
 | |
|       and reopening last browser window without exiting browser **/
 | |
|   waitForExplicitFinish();
 | |
|   // windows opening & closing, so extending the timeout
 | |
|   requestLongerTimeout(2);
 | |
| 
 | |
|   // We don't want the quit dialog pref
 | |
|   Services.prefs.setBoolPref("browser.tabs.warnOnClose", false);
 | |
|   // Ensure that we would restore the session (important for Windows)
 | |
|   Services.prefs.setIntPref("browser.startup.page", 3);
 | |
| 
 | |
|   runNextTestOrFinish();
 | |
| }
 | |
| 
 | |
| function runNextTestOrFinish() {
 | |
|   if (tests.length) {
 | |
|     setupForTest(tests.shift());
 | |
|   } else {
 | |
|     // some state is cleaned up at the end of each test, but not all
 | |
|     ["browser.tabs.warnOnClose", "browser.startup.page"].forEach(function(p) {
 | |
|       if (Services.prefs.prefHasUserValue(p))
 | |
|         Services.prefs.clearUserPref(p);
 | |
|     });
 | |
| 
 | |
|     ss.setBrowserState(stateBackup);
 | |
|     executeSoon(finish);
 | |
|   }
 | |
| }
 | |
| 
 | |
| function setupForTest(aConditions) {
 | |
|   // reset some checks
 | |
|   gotLastWindowClosedTopic = false;
 | |
|   shouldPinTab = aConditions.pinned;
 | |
|   shouldOpenTabs = aConditions.extra;
 | |
|   shouldCloseTab = aConditions.close;
 | |
|   testNum++;
 | |
| 
 | |
|   // set our test callback
 | |
|   afterTestCallback = /Mac/.test(navigator.platform) ? aConditions.checkOSX
 | |
|                                                      : aConditions.checkWinLin;
 | |
| 
 | |
|   // Add observers
 | |
|   Services.obs.addObserver(onLastWindowClosed, "browser-lastwindow-close-granted");
 | |
| 
 | |
|   // Set the state
 | |
|   Services.obs.addObserver(onStateRestored, "sessionstore-browser-state-restored");
 | |
|   ss.setBrowserState(JSON.stringify(testState));
 | |
| }
 | |
| 
 | |
| function onStateRestored(aSubject, aTopic, aData) {
 | |
|   info("test #" + testNum + ": onStateRestored");
 | |
|   Services.obs.removeObserver(onStateRestored, "sessionstore-browser-state-restored");
 | |
| 
 | |
|   // change this window's windowtype so that closing a new window will trigger
 | |
|   // browser-lastwindow-close-granted.
 | |
|   document.documentElement.setAttribute("windowtype", "navigator:testrunner");
 | |
| 
 | |
|   let newWin = openDialog(location, "_blank", "chrome,all,dialog=no", "http://example.com");
 | |
|   newWin.addEventListener("load", function(aEvent) {
 | |
|     promiseBrowserLoaded(newWin.gBrowser.selectedBrowser).then(() => {
 | |
|       // pin this tab
 | |
|       if (shouldPinTab)
 | |
|         newWin.gBrowser.pinTab(newWin.gBrowser.selectedTab);
 | |
| 
 | |
|       newWin.addEventListener("unload", function() {
 | |
|         onWindowUnloaded();
 | |
|       }, {once: true});
 | |
|       // Open a new tab as well. On Windows/Linux this will be restored when the
 | |
|       // new window is opened below (in onWindowUnloaded). On OS X we'll just
 | |
|       // restore the pinned tabs, leaving the unpinned tab in the closedWindowsData.
 | |
|       if (shouldOpenTabs) {
 | |
|         let newTab = newWin.gBrowser.addTab("about:config");
 | |
|         let newTab2 = newWin.gBrowser.addTab("about:buildconfig");
 | |
| 
 | |
|         newTab.linkedBrowser.addEventListener("load", function() {
 | |
|           if (shouldCloseTab == "one") {
 | |
|             newWin.gBrowser.removeTab(newTab2);
 | |
|           } else if (shouldCloseTab == "both") {
 | |
|             newWin.gBrowser.removeTab(newTab);
 | |
|             newWin.gBrowser.removeTab(newTab2);
 | |
|           }
 | |
|           newWin.BrowserTryToCloseWindow();
 | |
|         }, {capture: true, once: true});
 | |
|       } else {
 | |
|         newWin.BrowserTryToCloseWindow();
 | |
|       }
 | |
|     });
 | |
|   }, {once: true});
 | |
| }
 | |
| 
 | |
| // This will be called before the window is actually closed
 | |
| function onLastWindowClosed(aSubject, aTopic, aData) {
 | |
|   info("test #" + testNum + ": onLastWindowClosed");
 | |
|   Services.obs.removeObserver(onLastWindowClosed, "browser-lastwindow-close-granted");
 | |
|   gotLastWindowClosedTopic = true;
 | |
| }
 | |
| 
 | |
| // This is the unload event listener on the new window (from onStateRestored).
 | |
| // Unload is fired after the window is closed, so sessionstore has already
 | |
| // updated _closedWindows (which is important). We'll open a new window here
 | |
| // which should actually trigger the bug.
 | |
| function onWindowUnloaded() {
 | |
|   info("test #" + testNum + ": onWindowClosed");
 | |
|   ok(gotLastWindowClosedTopic, "test #" + testNum + ": browser-lastwindow-close-granted was notified prior");
 | |
| 
 | |
|   let previousClosedWindowData = ss.getClosedWindowData();
 | |
| 
 | |
|   // Now we want to open a new window
 | |
|   let newWin = openDialog(location, "_blank", "chrome,all,dialog=no", "about:mozilla");
 | |
|   newWin.addEventListener("load", function(aEvent) {
 | |
|     newWin.gBrowser.selectedBrowser.addEventListener("load", function() {
 | |
|       // Good enough for checking the state
 | |
|       afterTestCallback(previousClosedWindowData, ss.getClosedWindowData());
 | |
|       afterTestCleanup(newWin);
 | |
|     }, {capture: true, once: true});
 | |
| 
 | |
|   }, {once: true});
 | |
| }
 | |
| 
 | |
| function afterTestCleanup(aNewWin) {
 | |
|   executeSoon(function() {
 | |
|     BrowserTestUtils.closeWindow(aNewWin).then(() => {
 | |
|       document.documentElement.setAttribute("windowtype", originalWindowType);
 | |
|       runNextTestOrFinish();
 | |
|     });
 | |
|   });
 | |
| }
 |