Bug 819510 - Quitting from a Private Browsing window makes Restore Previous Session fail once. r=ttaubert
authorAndres Hernandez <andres@appcoast.com>
Wed, 19 Dec 2012 16:52:30 -0600
changeset 117087 e7b858cfccc27e4eaeade03d294f7e24bddb48f5
parent 117086 305236f284cfbf1927bd62d8f0b181e6bcd8b79e
child 117088 af2c780aa93163939ba96dcdd142413f9cdcdd4d
push id24083
push userdholbert@mozilla.com
push dateThu, 27 Dec 2012 21:54:50 +0000
treeherdermozilla-central@65de3fdfe888 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersttaubert
bugs819510
milestone20.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 819510 - Quitting from a Private Browsing window makes Restore Previous Session fail once. r=ttaubert
browser/components/sessionstore/src/SessionStore.jsm
browser/components/sessionstore/test/Makefile.in
browser/components/sessionstore/test/browser_819510_perwindowpb.js
--- a/browser/components/sessionstore/src/SessionStore.jsm
+++ b/browser/components/sessionstore/src/SessionStore.jsm
@@ -3723,16 +3723,19 @@ let SessionStoreInternal = {
       return;
     }
 
 #ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
     // Forget about private windows.
     for (let i = oState.windows.length - 1; i >= 0; i--) {
       if (oState.windows[i].isPrivate) {
         oState.windows.splice(i, 1);
+        if (oState.selectedWindow >= i) {
+          oState.selectedWindow--;
+        }
       }
     }
     for (let i = oState._closedWindows.length - 1; i >= 0; i--) {
       if (oState._closedWindows[i].isPrivate) {
         oState._closedWindows.splice(i, 1);
       }
     }
 #endif
--- a/browser/components/sessionstore/test/Makefile.in
+++ b/browser/components/sessionstore/test/Makefile.in
@@ -136,16 +136,17 @@ MOCHITEST_BROWSER_FILES = \
 	$(filter disabled-for-intermittent-failures--bug-766044, browser_459906_sample.html) \
 	$(filter disabled-for-intermittent-failures--bug-765389, browser_461743_sample.html) \
 	$(NULL)
 
 ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
 MOCHITEST_BROWSER_FILES += \
 	browser_354894_perwindowpb.js \
 	browser_394759_perwindowpb.js \
+	browser_819510_perwindowpb.js \
 	$(NULL)
 else
 MOCHITEST_BROWSER_FILES += \
 	browser_248970_a.js \
 	browser_248970_b.js \
 	browser_248970_b_perwindowpb.js \
 	browser_354894.js \
 	browser_394759_privatebrowsing.js \
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/test/browser_819510_perwindowpb.js
@@ -0,0 +1,181 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const originalState = ss.getBrowserState();
+
+/** Private Browsing Test for Bug 819510 **/
+function test() {
+  waitForExplicitFinish();
+
+  registerCleanupFunction(function() {
+    Services.prefs.clearUserPref("browser.sessionstore.interval");
+    ss.setBrowserState(originalState);
+  });
+
+  runNextTest();
+}
+
+let tests = [test_1, test_2, test_3 ];
+
+const testState = {
+  windows: [{
+    tabs: [
+      { entries: [{ url: "about:blank" }] },
+    ]
+  }]
+};
+
+function runNextTest() {
+  // Set an empty state
+  closeAllButPrimaryWindow();
+
+  // Run the next test, or finish
+  if (tests.length) {
+    let currentTest = tests.shift();
+    waitForBrowserState(testState, currentTest);
+  } else {
+    Services.prefs.clearUserPref("browser.sessionstore.interval");
+    ss.setBrowserState(originalState);
+    finish();
+  }
+}
+
+// Test opening default mochitest-normal-private-normal-private windows
+// (saving the state with last window being private)
+function test_1() {
+  testOnWindow(false, function(aWindow) {
+    aWindow.gBrowser.addTab("http://www.example.com/1");
+    testOnWindow(true, function(aWindow) {
+      aWindow.gBrowser.addTab("http://www.example.com/2");
+      testOnWindow(false, function(aWindow) {
+        aWindow.gBrowser.addTab("http://www.example.com/3");
+        testOnWindow(true, function(aWindow) {
+          aWindow.gBrowser.addTab("http://www.example.com/4");
+
+          let curState = JSON.parse(ss.getBrowserState());
+          is (curState.windows.length, 5, "Browser has opened 5 windows");
+          is (curState.windows[2].isPrivate, true, "Window is private");
+          is (curState.windows[4].isPrivate, true, "Last window is private");
+          is (curState.selectedWindow, 5, "Last window opened is the one selected");
+
+          forceWriteState(function(state) {
+            is(state.windows.length, 3,
+               "sessionstore state: 3 windows in data being written to disk");
+            is (state.selectedWindow, 3,
+               "Selected window is updated to match one of the saved windows");
+            state.windows.forEach(function(win) {
+              is(!win.isPrivate, true, "Saved window is not private");
+            });
+            is(state._closedWindows.length, 0,
+               "sessionstore state: no closed windows in data being written to disk");
+            runNextTest();
+          });
+        });
+      });
+    });
+  });
+}
+
+// Test opening default mochitest window + 2 private windows
+function test_2() {
+  testOnWindow(true, function(aWindow) {
+    aWindow.gBrowser.addTab("http://www.example.com/1");
+    testOnWindow(true, function(aWindow) {
+      aWindow.gBrowser.addTab("http://www.example.com/2");
+
+      let curState = JSON.parse(ss.getBrowserState());
+      is (curState.windows.length, 3, "Browser has opened 3 windows");
+      is (curState.windows[1].isPrivate, true, "Window 1 is private");
+      is (curState.windows[2].isPrivate, true, "Window 2 is private");
+      is (curState.selectedWindow, 3, "Last window opened is the one selected");
+
+      forceWriteState(function(state) {
+        is(state.windows.length, 1,
+           "sessionstore state: 1 windows in data being writted to disk");
+        is (state.selectedWindow, 1,
+           "Selected window is updated to match one of the saved windows");
+        is(state._closedWindows.length, 0,
+           "sessionstore state: no closed windows in data being writted to disk");
+        runNextTest();
+      });
+    });
+  });
+}
+
+// Test opening default-normal-private-normal windows and closing a normal window
+function test_3() {
+  testOnWindow(false, function(normalWindow) {
+    let tab = normalWindow.gBrowser.addTab("http://www.example.com/1");
+    whenBrowserLoaded(tab.linkedBrowser, function() {
+      testOnWindow(true, function(aWindow) {
+        aWindow.gBrowser.addTab("http://www.example.com/2");
+        testOnWindow(false, function(aWindow) {
+          aWindow.gBrowser.addTab("http://www.example.com/3");
+
+          let curState = JSON.parse(ss.getBrowserState());
+          is (curState.windows.length, 4, "Browser has opened 4 windows");
+          is (curState.windows[2].isPrivate, true, "Window 2 is private");
+          is (curState.selectedWindow, 4, "Last window opened is the one selected");
+
+          waitForWindowClose(normalWindow, function() {
+            forceWriteState(function(state) {
+              is(state.windows.length, 2,
+                 "sessionstore state: 2 windows in data being writted to disk");
+              is(state.selectedWindow, 2,
+                 "Selected window is updated to match one of the saved windows");
+              state.windows.forEach(function(win) {
+                is(!win.isPrivate, true, "Saved window is not private");
+              });
+              is(state._closedWindows.length, 1,
+                 "sessionstore state: 1 closed window in data being writted to disk");
+              state._closedWindows.forEach(function(win) {
+                is(!win.isPrivate, true, "Closed window is not private");
+              });
+              runNextTest();
+            });
+          });
+        });
+      });
+    });
+  });
+}
+
+function waitForWindowClose(aWin, aCallback) {
+  Services.obs.addObserver(function observe(aSubject, aTopic, aData) {
+    if (aTopic == "domwindowclosed" && aWin == aSubject) {
+      Services.obs.removeObserver(observe, aTopic);
+      checkWindowIsClosed(aWin, aCallback);
+    }
+  }, "domwindowclosed", false);
+  aWin.close();
+}
+
+function checkWindowIsClosed(aWin, aCallback) {
+  if (aWin.closed) {
+    info("Window is closed");
+    executeSoon(aCallback);
+  } else {
+    executeSoon(function() {
+      checkWindowIsClosed(aWin, aCallback);
+    });
+  }
+}
+
+function forceWriteState(aCallback) {
+  Services.obs.addObserver(function observe(aSubject, aTopic, aData) {
+    if (aTopic == "sessionstore-state-write") {
+      Services.obs.removeObserver(observe, aTopic);
+      aSubject.QueryInterface(Ci.nsISupportsString);
+      aCallback(JSON.parse(aSubject.data));
+    }
+  }, "sessionstore-state-write", false);
+  Services.prefs.setIntPref("browser.sessionstore.interval", 0);
+}
+
+function testOnWindow(aIsPrivate, aCallback) {
+  let win = OpenBrowserWindow({private: aIsPrivate});
+  win.addEventListener("load", function onLoad() {
+    win.removeEventListener("load", onLoad, false);
+    executeSoon(function() { aCallback(win); });
+  }, false);
+}