Bug 1134518 - Cap shistory entries in the SessionWorker when shutting down r=Yoric
authorTim Taubert <ttaubert@mozilla.com>
Wed, 22 Apr 2015 18:41:32 +0200
changeset 240632 a0b3a91f096088c71849ab19c88c5fdc5394f16c
parent 240631 9484987dbf3e6817535975b2fecf4b7792d09211
child 240633 8a151d59bdec0cf0e946396771ff8dc2953be736
push id12537
push userttaubert@mozilla.com
push dateThu, 23 Apr 2015 12:44:40 +0000
treeherderfx-team@8a151d59bdec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersYoric
bugs1134518
milestone40.0a1
Bug 1134518 - Cap shistory entries in the SessionWorker when shutting down r=Yoric
browser/components/sessionstore/SessionFile.jsm
browser/components/sessionstore/SessionWorker.js
--- a/browser/components/sessionstore/SessionFile.jsm
+++ b/browser/components/sessionstore/SessionFile.jsm
@@ -50,16 +50,19 @@ XPCOMUtils.defineLazyServiceGetter(this,
 XPCOMUtils.defineLazyServiceGetter(this, "sessionStartup",
   "@mozilla.org/browser/sessionstartup;1", "nsISessionStartup");
 XPCOMUtils.defineLazyModuleGetter(this, "SessionWorker",
   "resource:///modules/sessionstore/SessionWorker.jsm");
 
 const PREF_UPGRADE_BACKUP = "browser.sessionstore.upgradeBackup.latestBuildID";
 const PREF_MAX_UPGRADE_BACKUPS = "browser.sessionstore.upgradeBackup.maxUpgradeBackups";
 
+const PREF_MAX_SERIALIZE_BACK = "browser.sessionstore.max_serialize_back";
+const PREF_MAX_SERIALIZE_FWD = "browser.sessionstore.max_serialize_forward";
+
 this.SessionFile = {
   /**
    * Read the contents of the session file, asynchronously.
    */
   read: function () {
     return SessionFileInternal.read();
   },
   /**
@@ -251,21 +254,21 @@ let SessionFileInternal = {
         parsed: null
       };
     }
 
     result.noFilesFound = noFilesFound;
 
     // Initialize the worker to let it handle backups and also
     // as a workaround for bug 964531.
-    SessionWorker.post("init", [
-      result.origin,
-      this.Paths,
-      Preferences.get(PREF_MAX_UPGRADE_BACKUPS, 3)
-    ]);
+    SessionWorker.post("init", [result.origin, this.Paths, {
+      maxUpgradeBackups: Preferences.get(PREF_MAX_UPGRADE_BACKUPS, 3),
+      maxSerializeBack: Preferences.get(PREF_MAX_SERIALIZE_BACK, 10),
+      maxSerializeForward: Preferences.get(PREF_MAX_SERIALIZE_FWD, -1)
+    }]);
 
     return result;
   }),
 
   gatherTelemetry: function(aStateString) {
     return Task.spawn(function() {
       let msg = yield SessionWorker.post("gatherTelemetry", [aStateString]);
       this._recordTelemetry(msg.telemetry);
--- a/browser/components/sessionstore/SessionWorker.js
+++ b/browser/components/sessionstore/SessionWorker.js
@@ -83,25 +83,35 @@ let Agent = {
   maxUpgradeBackups: null,
 
   /**
    * Initialize (or reinitialize) the worker
    *
    * @param {string} origin Which of sessionstore.js or its backups
    *   was used. One of the `STATE_*` constants defined above.
    * @param {object} paths The paths at which to find the various files.
-   * @param {number} maxUpgradeBackups The number of old upgrade backups that should be kept.
+   * @param {object} prefs The preferences the worker needs to known.
    */
-  init: function (origin, paths, maxUpgradeBackups) {
+  init(origin, paths, prefs = {}) {
     if (!(origin in paths || origin == STATE_EMPTY)) {
       throw new TypeError("Invalid origin: " + origin);
     }
+
+    // Check that all required preference values were passed.
+    for (let pref of ["maxUpgradeBackups", "maxSerializeBack", "maxSerializeForward"]) {
+      if (!prefs.hasOwnProperty(pref)) {
+        throw new TypeError(`Missing preference value for ${pref}`);
+      }
+    }
+
     this.state = origin;
     this.Paths = paths;
-    this.maxUpgradeBackups = maxUpgradeBackups || 3;
+    this.maxUpgradeBackups = prefs.maxUpgradeBackups;
+    this.maxSerializeBack = prefs.maxSerializeBack;
+    this.maxSerializeForward = prefs.maxSerializeForward;
     this.upgradeBackupNeeded = paths.nextUpgradeBackup != paths.upgradeBackup;
     return {result: true};
   },
 
   /**
    * Write the session to disk.
    * Write the session to disk, performing any necessary backup
    * along the way.
@@ -113,16 +123,36 @@ let Agent = {
    *    is not left lying around;
    *  - isFinalWrite If |true|, write to Paths.clean instead of
    *    Paths.recovery
    */
   write: function (state, options = {}) {
     let exn;
     let telemetry = {};
 
+    // Cap the number of backward and forward shistory entries on shutdown.
+    if (options.isFinalWrite) {
+      for (let window of state.windows) {
+        for (let tab of window.tabs) {
+          let lower = 0;
+          let upper = tab.entries.length;
+
+          if (this.maxSerializeBack > -1) {
+            lower = Math.max(lower, tab.index - this.maxSerializeBack - 1);
+          }
+          if (this.maxSerializeForward > -1) {
+            upper = Math.min(upper, tab.index + this.maxSerializeForward);
+          }
+
+          tab.entries = tab.entries.slice(lower, upper);
+          tab.index -= lower;
+        }
+      }
+    }
+
     let stateString = JSON.stringify(state);
     let data = Encoder.encode(stateString);
     let startWriteMs, stopWriteMs;
 
     try {
 
       if (this.state == STATE_CLEAN || this.state == STATE_EMPTY) {
         // The backups directory may not exist yet. In all other cases,