Bug 1346171 - Part 2 - Test synchronous session file deletion on clearing history. r=sebastian a=lizzard
authorJan Henning <jh+bugzilla@buttercookie.de>
Sun, 12 Mar 2017 11:13:33 +0100
changeset 379036 a70aec4e81ce3ca5fd1a5303b6aa1251fc9bb1a1
parent 379035 ffb57e932e835673ada66e817053a5aa54a06889
child 379037 6f254d491d00b67c0effe24fbe0b87cbc6f812b0
push id1419
push userjlund@mozilla.com
push dateMon, 10 Apr 2017 20:44:07 +0000
treeherdermozilla-release@5e6801b73ef6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssebastian, lizzard
bugs1346171
milestone53.0
Bug 1346171 - Part 2 - Test synchronous session file deletion on clearing history. r=sebastian a=lizzard MozReview-Commit-ID: JUrbSD2t41t
mobile/android/components/SessionStore.idl
mobile/android/components/SessionStore.js
mobile/android/tests/browser/chrome/test_session_clear_history.html
--- a/mobile/android/components/SessionStore.idl
+++ b/mobile/android/components/SessionStore.idl
@@ -78,9 +78,15 @@ interface nsISessionStore : nsISupports
   void restoreLastSession(in AString aSessionString);
 
   /**
    * Removes a window from the current session history. Data from this window
    * won't be saved when its closed.
    * @param aWindow The window to remove
    */
   void removeWindow(in nsIDOMWindow aWindow);
+
+  /**
+   * Set the load state of the session store. Use only for testing.
+   * @param aState The target load state.
+   */
+  void setLoadState(in long aState);
 };
--- a/mobile/android/components/SessionStore.js
+++ b/mobile/android/components/SessionStore.js
@@ -1864,13 +1864,18 @@ SessionStore.prototype = {
     delete aWindow.__SSID;
 
     if (this._loadState == STATE_RUNNING) {
       // Save the purged state immediately
       this.saveState();
     } else if (this._loadState <= STATE_QUITTING) {
       this.saveStateDelayed();
     }
+  },
+
+  setLoadState: function ss_setLoadState(aState) {
+    this.flushPendingState();
+    this._loadState = aState;
   }
 
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SessionStore]);
--- a/mobile/android/tests/browser/chrome/test_session_clear_history.html
+++ b/mobile/android/tests/browser/chrome/test_session_clear_history.html
@@ -51,17 +51,31 @@ https://bugzilla.mozilla.org/show_bug.cg
       tabTest = null;
     }
   }
 
   SimpleTest.registerCleanupFunction(function() {
     cleanupTabs();
   });
 
+  let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
 
+  // Session store load state constants
+  const STATE_STOPPED = 0;
+  const STATE_RUNNING = 1;
+  const STATE_QUITTING = -1;
+  const STATE_QUITTING_FLUSHED = -2;
+
+  function createFileIfNotExists(file) {
+    if (!file.exists()) {
+      file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
+    }
+  }
+
+  // URLs for testing
   const url1 = "http://example.org/chrome/mobile/android/tests/browser/chrome/basic_article_mobile.html";
   const url2 = "http://example.org/chrome/mobile/android/tests/browser/chrome/basic_article.html";
   const url3 = "data:text/html;charset=utf-8,It%20was%20a%20dark%20and%20stormy%20night.";
 
   add_task(function* test_sessionStoreClearTabHistory() {
     // Add a new tab with some content
     tabTest = BrowserApp.addTab(url1 , { selected: true, parentId: BrowserApp.selectedTab.id });
     yield promiseBrowserEvent(tabTest.browser, "DOMTitleChanged");
@@ -92,16 +106,61 @@ https://bugzilla.mozilla.org/show_bug.cg
     data = tabTest.browser.__SS_data;
     is(data.entries.length, 1, "the session store has cleared all previous entries");
     is(data.index, 1, "history index is correct");
     is(data.entries[0].url, url2, "URL of first history entry is correct after data clearing");
 
     cleanupTabs();
   });
 
+  add_task(function* test_sessionStoreClearFiles() {
+    // Temporarily set the session store to shutdown mode to test the
+    // synchronous deletion code path.
+    // This also means that nothing gets written to disk until explicitly
+    // flushed, so we can test that all files have been deleted and don't
+    // have to worry about them already having been recreated before we get
+    // around checking on them.
+    ss.setLoadState(STATE_QUITTING);
+
+    let sessionFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
+    let sessionFileBackup = sessionFile.clone();
+    let sessionFilePrevious = sessionFile.clone();
+    let sessionFileTemp = sessionFile.clone();
+
+    sessionFile.append("sessionstore.js"); // The main session store save file.
+    sessionFileBackup.append("sessionstore.bak"); // A backup copy to guard against interrupted writes.
+    sessionFilePrevious.append("sessionstore.old"); // The previous session's file, used for what used to be the "Tabs from last time".
+    sessionFileTemp.append(sessionFile.leafName + ".tmp"); // Temporary file for writing changes to disk.
+
+    createFileIfNotExists(sessionFile);
+    createFileIfNotExists(sessionFileBackup);
+    createFileIfNotExists(sessionFilePrevious);
+    createFileIfNotExists(sessionFileTemp);
+
+    ok(sessionFile.exists(), "session file exists");
+    ok(sessionFileBackup.exists(), "backup file exists");
+    ok(sessionFilePrevious.exists(), "last session file exists");
+    ok(sessionFileTemp.exists(), "temp file exists");
+
+    // Clear browsing history
+    let sanitize = { history:true };
+    let notification = promiseNotification("sessionstore-state-purge-complete");
+
+    BrowserApp.sanitize(sanitize);
+    yield notification;
+
+    ok(!sessionFile.exists(), "session file was deleted");
+    ok(!sessionFileBackup.exists(), "backup file was deleted");
+    ok(!sessionFilePrevious.exists(), "last session file was deleted");
+    ok(!sessionFileTemp.exists(), "temp file was deleted");
+
+    // Revert back to normal
+    ss.setLoadState(STATE_RUNNING);
+  });
+
   add_task(function* test_sessionStoreClearZombieTabHistory() {
     // Add a new tab with some content
     tabTest = BrowserApp.addTab(url1 , { selected: true, parentId: BrowserApp.selectedTab.id });
     yield promiseBrowserEvent(tabTest.browser, "DOMTitleChanged");
 
     // Navigate to create some history
     tabTest.browser.loadURI(url2);
     yield promiseBrowserEvent(tabTest.browser, "DOMTitleChanged");