Bug 1437382 - Part 10 - Use a reduced save delay when saving private tabs. r?esawin draft
authorJan Henning <jh+bugzilla@buttercookie.de>
Sat, 17 Feb 2018 16:31:20 +0100
changeset 761293 ce36990aed01026cfea48381ff93094a1573d4e8
parent 761292 13ce5e430bd77130f3385994edeba91a959f5662
child 761294 a6abfcd8af5c6f19d57fe52fbaf071d496d9049a
push id100929
push usermozilla@buttercookie.de
push dateWed, 28 Feb 2018 22:01:37 +0000
reviewersesawin
bugs1437382
milestone60.0a1
Bug 1437382 - Part 10 - Use a reduced save delay when saving private tabs. r?esawin ... and also shorten any already running save timer if necessary. This is because the private tab data kept by GeckoApp, that will be restored if we are OOM-killed, cannot be updated anymore after Firefox goes into the back- ground, even if we aren't immediately killed by the OS. Because during backgrounding the UI only waits a limited amount of time for the latest private tab data in order to avoid causing an ANR if Gecko is busy, we need to compensate by sending private tab data updates faster to GeckoApp than the usual write throttling interval of every 10 s would allow. To allow multiple successive tab events to be batched together in one update, e.g. if the user closes *all* private tabs, we still introduce a small save delay of a few hundred ms. MozReview-Commit-ID: J15RNfAlfy2
mobile/android/components/SessionStore.js
--- a/mobile/android/components/SessionStore.js
+++ b/mobile/android/components/SessionStore.js
@@ -44,29 +44,31 @@ const STATE_RUNNING = 1;
 const STATE_QUITTING = -1;
 const STATE_QUITTING_FLUSHED = -2;
 
 const PREFS_RESTORE_FROM_CRASH = "browser.sessionstore.resume_from_crash";
 const PREFS_MAX_CRASH_RESUMES = "browser.sessionstore.max_resumed_crashes";
 const PREFS_MAX_TABS_UNDO = "browser.sessionstore.max_tabs_undo";
 
 const MINIMUM_SAVE_DELAY = 2000;
+const SAVE_INTERVAL_PRIVATE_TABS = 500;
 
 function SessionStore() { }
 
 SessionStore.prototype = {
   classID: Components.ID("{8c1f07d6-cba3-4226-a315-8bd43d67d032}"),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISessionStore,
                                          Ci.nsIDOMEventListener,
                                          Ci.nsIObserver,
                                          Ci.nsISupportsWeakReference]),
 
   _windows: {},
   _lastSaveTime: 0,
+  _lastQueuedSaveTime: 0,
   _lastBackupTime: 0,
   _interval: 10000,
   _backupInterval: 120000, // 2 minutes
   _maxTabsUndo: 5,
   _pendingWrite: 0,
   _pendingWritePrivateOnly: 0,
   _scrollSavePending: null,
   _writeInProgress: false,
@@ -974,28 +976,37 @@ SessionStore.prototype = {
 
   saveStateDelayed: function ss_saveStateDelayed(aPrivateTabsOnly = false) {
     this._pendingWrite++;
     if (aPrivateTabsOnly) {
       this._pendingWritePrivateOnly++;
     }
     log("incrementing _pendingWrite to " + this._pendingWritePrivateOnly +
         "/" + this._pendingWrite);
+
     if (!this._saveTimer) {
       // Interval until the next disk operation is allowed
       let currentDelay = this._lastSaveTime + this._interval - Date.now();
 
       // If we have to wait, set a timer, otherwise saveState directly
-      let delay = Math.max(currentDelay, MINIMUM_SAVE_DELAY);
+      let delay = aPrivateTabsOnly
+                    ? SAVE_INTERVAL_PRIVATE_TABS
+                    : Math.max(currentDelay, MINIMUM_SAVE_DELAY);
       if (delay > 0) {
         this._createTimer(delay);
       } else {
         log("saveStateDelayed() no delay");
         this.saveState();
       }
+    } else if (aPrivateTabsOnly &&
+               // How long until the current timer would fire?
+               this._saveTimer.delay - (Date.now() - this._lastQueuedSaveTime)
+                 > SAVE_INTERVAL_PRIVATE_TABS) {
+      this._killTimer();
+      this._createTimer(SAVE_INTERVAL_PRIVATE_TABS);
     } else {
       log("saveStateDelayed() timer already running, taking no action");
     }
   },
 
   saveState: function ss_saveState(aPrivateTabsOnly = false) {
     this._pendingWrite++;
     if (aPrivateTabsOnly) {
@@ -1016,16 +1027,17 @@ SessionStore.prototype = {
     if (this._pendingWrite) {
       this._saveState(false);
       return true;
     }
     return false;
   },
 
   _createTimer: function ss_createTimer(aDelay) {
+    this._lastQueuedSaveTime = Date.now();
     this._saveTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
     this._saveTimer.init(this, aDelay, Ci.nsITimer.TYPE_ONE_SHOT);
     log("saveTimer delay = " + aDelay);
   },
 
   _killTimer: function ss_killTimer() {
     if (this._saveTimer) {
       this._saveTimer.cancel();