Bug 1312571 - Implement SessionStore.lastClosedObjectType, r=mikedeboer
☠☠ backed out by 75db19443bc0 ☠ ☠
authorBob Silverberg <bsilverberg@mozilla.com>
Mon, 24 Oct 2016 17:56:30 -0400
changeset 319911 4537bb4cfb82972e3c88b73e1b7c48e98e667348
parent 319910 0fd006bf6f9d5080b10fce59d8cad71cbf72659b
child 319912 466b0de6dfcbb27630de8ddfe66db89951a2dc34
push id20749
push userryanvm@gmail.com
push dateSat, 29 Oct 2016 13:21:21 +0000
treeherderfx-team@1b170b39ed6b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmikedeboer
bugs1312571
milestone52.0a1
Bug 1312571 - Implement SessionStore.lastClosedObjectType, r=mikedeboer MozReview-Commit-ID: 1COPiRTmeW7
browser/components/sessionstore/SessionStore.jsm
browser/components/sessionstore/test/browser_undoCloseById.js
--- a/browser/components/sessionstore/SessionStore.jsm
+++ b/browser/components/sessionstore/SessionStore.jsm
@@ -206,16 +206,20 @@ this.SessionStore = {
   get canRestoreLastSession() {
     return SessionStoreInternal.canRestoreLastSession;
   },
 
   set canRestoreLastSession(val) {
     SessionStoreInternal.canRestoreLastSession = val;
   },
 
+  get lastClosedObjectType() {
+    return SessionStoreInternal.lastClosedObjectType;
+  },
+
   init: function ss_init() {
     SessionStoreInternal.init();
   },
 
   getBrowserState: function ss_getBrowserState() {
     return SessionStoreInternal.getBrowserState();
   },
 
@@ -499,16 +503,43 @@ var SessionStoreInternal = {
   set canRestoreLastSession(val) {
     // Cheat a bit; only allow false.
     if (!val) {
       LastSession.clear();
     }
   },
 
   /**
+   * Returns a string describing the last closed object, either "tab" or "window".
+   *
+   * This was added to support the sessions.restore WebExtensions API.
+   */
+  get lastClosedObjectType() {
+    if (this._closedWindows.length) {
+      // Since there are closed windows, we need to check if there's a closed tab
+      // in one of the currently open windows that was closed after the
+      // last-closed window.
+      let tabTimestamps = [];
+      let windowsEnum = Services.wm.getEnumerator("navigator:browser");
+      while (windowsEnum.hasMoreElements()) {
+        let window = windowsEnum.getNext();
+        let windowState = this._windows[window.__SSi];
+        if (windowState && windowState._closedTabs[0]) {
+          tabTimestamps.push(windowState._closedTabs[0].closedAt);
+        }
+      }
+      if (!tabTimestamps.length ||
+          (tabTimestamps.sort((a, b) => b - a)[0] < this._closedWindows[0].closedAt)) {
+        return "window";
+      }
+    }
+    return "tab";
+  },
+
+  /**
    * Initialize the sessionstore service.
    */
   init: function () {
     if (this._initialized) {
       throw new Error("SessionStore.init() must only be called once!");
     }
 
     TelemetryTimestamps.add("sessionRestoreInitialized");
--- a/browser/components/sessionstore/test/browser_undoCloseById.js
+++ b/browser/components/sessionstore/test/browser_undoCloseById.js
@@ -31,69 +31,85 @@ add_task(function* test_undoCloseById() 
     SessionStore.forgetClosedTab(window, 0);
   }
 
   // Open a new window.
   let win = yield openWindow("about:robots");
 
   // Open and close a tab.
   yield openAndCloseTab(win, "about:mozilla");
+  is(SessionStore.lastClosedObjectType, "tab", "The last closed object is a tab");
 
   // Record the first closedId created.
   let initialClosedId = SessionStore.getClosedTabData(win, false)[0].closedId;
 
-  // Open and close another tab.
-  yield openAndCloseTab(win, "about:robots");  // closedId == initialClosedId + 1
+  // Open and close another window.
+  let win2 = yield openWindow("about:mozilla");
+  yield BrowserTestUtils.closeWindow(win2);  // closedId == initialClosedId + 1
+  is(SessionStore.lastClosedObjectType, "window", "The last closed object is a window");
+
+  // Open and close another tab in the first window.
+  yield openAndCloseTab(win, "about:robots");  // closedId == initialClosedId + 2
+  is(SessionStore.lastClosedObjectType, "tab", "The last closed object is a tab");
 
   // Undo closing the second tab.
-  let tab = SessionStore.undoCloseById(initialClosedId + 1);
+  let tab = SessionStore.undoCloseById(initialClosedId + 2);
   yield promiseBrowserLoaded(tab.linkedBrowser);
   is(tab.linkedBrowser.currentURI.spec, "about:robots", "The expected tab was re-opened");
 
-  let notTab = SessionStore.undoCloseById(initialClosedId + 1);
+  let notTab = SessionStore.undoCloseById(initialClosedId + 2);
   is(notTab, undefined, "Re-opened tab cannot be unClosed again by closedId");
 
+  // Now the last closed object should be a window again.
+  is(SessionStore.lastClosedObjectType, "window", "The last closed object is a window");
+
   // Undo closing the first tab.
   let tab2 = SessionStore.undoCloseById(initialClosedId);
   yield promiseBrowserLoaded(tab2.linkedBrowser);
   is(tab2.linkedBrowser.currentURI.spec, "about:mozilla", "The expected tab was re-opened");
 
   // Close the two tabs we re-opened.
-  yield promiseRemoveTab(tab); // closedId == initialClosedId + 2
-  yield promiseRemoveTab(tab2); // closedId == initialClosedId + 3
+  yield promiseRemoveTab(tab); // closedId == initialClosedId + 3
+  is(SessionStore.lastClosedObjectType, "tab", "The last closed object is a tab");
+  yield promiseRemoveTab(tab2); // closedId == initialClosedId + 4
+  is(SessionStore.lastClosedObjectType, "tab", "The last closed object is a tab");
 
   // Open another new window.
-  let win2 = yield openWindow("about:mozilla");
+  let win3 = yield openWindow("about:mozilla");
 
   // Close both windows.
-  yield BrowserTestUtils.closeWindow(win); // closedId == initialClosedId + 4
-  yield BrowserTestUtils.closeWindow(win2); // closedId == initialClosedId + 5
+  yield BrowserTestUtils.closeWindow(win); // closedId == initialClosedId + 5
+  is(SessionStore.lastClosedObjectType, "window", "The last closed object is a window");
+  yield BrowserTestUtils.closeWindow(win3); // closedId == initialClosedId + 6
+  is(SessionStore.lastClosedObjectType, "window", "The last closed object is a window");
 
   // Undo closing the second window.
-  win = SessionStore.undoCloseById(initialClosedId + 5);
+  win = SessionStore.undoCloseById(initialClosedId + 6);
   yield BrowserTestUtils.waitForEvent(win, "load");
 
   // Make sure we wait until this window is restored.
   yield BrowserTestUtils.waitForEvent(win.gBrowser.tabContainer,
                                       "SSTabRestored");
 
   is(win.gBrowser.selectedBrowser.currentURI.spec, "about:mozilla", "The expected window was re-opened");
 
-  let notWin = SessionStore.undoCloseById(initialClosedId + 5);
+  let notWin = SessionStore.undoCloseById(initialClosedId + 6);
   is(notWin, undefined, "Re-opened window cannot be unClosed again by closedId");
 
   // Close the window again.
   yield BrowserTestUtils.closeWindow(win);
+  is(SessionStore.lastClosedObjectType, "window", "The last closed object is a window");
 
   // Undo closing the first window.
-  win = SessionStore.undoCloseById(initialClosedId + 4);
+  win = SessionStore.undoCloseById(initialClosedId + 5);
 
   yield BrowserTestUtils.waitForEvent(win, "load");
 
   // Make sure we wait until this window is restored.
   yield BrowserTestUtils.waitForEvent(win.gBrowser.tabContainer,
                                       "SSTabRestored");
 
   is(win.gBrowser.selectedBrowser.currentURI.spec, "about:robots", "The expected window was re-opened");
 
   // Close the window again.
   yield BrowserTestUtils.closeWindow(win);
+  is(SessionStore.lastClosedObjectType, "window", "The last closed object is a window");
 });