Bug 898775 - Fix the browser.sessionstore.resume_from_crash preference; r=yoric

This commit is contained in:
Tim Taubert 2013-08-05 20:26:27 +02:00
Родитель 7e2fe79397
Коммит 346a812e7a
6 изменённых файлов: 29 добавлений и 90 удалений

Просмотреть файл

@ -547,13 +547,6 @@ let SessionStoreInternal = {
return this._prefBranch.getIntPref("sessionstore.interval"); return this._prefBranch.getIntPref("sessionstore.interval");
}); });
// when crash recovery is disabled, session data is not written to disk
XPCOMUtils.defineLazyGetter(this, "_resume_from_crash", function () {
// get crash recovery state from prefs and allow for proper reaction to state changes
this._prefBranch.addObserver("sessionstore.resume_from_crash", this, true);
return this._prefBranch.getBoolPref("sessionstore.resume_from_crash");
});
XPCOMUtils.defineLazyGetter(this, "_max_tabs_undo", function () { XPCOMUtils.defineLazyGetter(this, "_max_tabs_undo", function () {
this._prefBranch.addObserver("sessionstore.max_tabs_undo", this, true); this._prefBranch.addObserver("sessionstore.max_tabs_undo", this, true);
return this._prefBranch.getIntPref("sessionstore.max_tabs_undo"); return this._prefBranch.getIntPref("sessionstore.max_tabs_undo");
@ -1191,14 +1184,6 @@ let SessionStoreInternal = {
} }
this.saveStateDelayed(null, -1); this.saveStateDelayed(null, -1);
break; break;
case "sessionstore.resume_from_crash":
this._resume_from_crash = this._prefBranch.getBoolPref("sessionstore.resume_from_crash");
// either create the file with crash recovery information or remove it
// (when _loadState is not STATE_RUNNING, that file is used for session resuming instead)
if (!this._resume_from_crash)
_SessionFile.wipe();
this.saveState(true);
break;
} }
}, },
@ -2547,11 +2532,9 @@ let SessionStoreInternal = {
* gather session data as object * gather session data as object
* @param aUpdateAll * @param aUpdateAll
* Bool update all windows * Bool update all windows
* @param aPinnedOnly
* Bool collect pinned tabs only
* @returns object * @returns object
*/ */
_getCurrentState: function ssi_getCurrentState(aUpdateAll, aPinnedOnly) { _getCurrentState: function ssi_getCurrentState(aUpdateAll) {
this._handleClosedWindows(); this._handleClosedWindows();
var activeWindow = this._getMostRecentBrowserWindow(); var activeWindow = this._getMostRecentBrowserWindow();
@ -2614,24 +2597,6 @@ let SessionStoreInternal = {
} }
#endif #endif
if (aPinnedOnly) {
// perform a deep copy so that existing session variables are not changed.
total = JSON.parse(this._toJSONString(total));
total = total.filter(function (win) {
win.tabs = win.tabs.filter(function (tab) tab.pinned);
// remove closed tabs
win._closedTabs = [];
// correct selected tab index if it was stripped out
if (win.selected > win.tabs.length)
win.selected = 1;
return win.tabs.length > 0;
});
if (total.length == 0)
return null;
lastClosedWindowsCopy = [];
}
if (activeWindow) { if (activeWindow) {
this.activeWindowSSiCache = activeWindow.__SSi || ""; this.activeWindowSSiCache = activeWindow.__SSi || "";
} }
@ -3759,12 +3724,10 @@ let SessionStoreInternal = {
saveState: function ssi_saveState(aUpdateAll) { saveState: function ssi_saveState(aUpdateAll) {
// If crash recovery is disabled, we only want to resume with pinned tabs // If crash recovery is disabled, we only want to resume with pinned tabs
// if we crash. // if we crash.
let pinnedOnly = this._loadState == STATE_RUNNING && !this._resume_from_crash;
TelemetryStopwatch.start("FX_SESSION_RESTORE_COLLECT_DATA_MS"); TelemetryStopwatch.start("FX_SESSION_RESTORE_COLLECT_DATA_MS");
TelemetryStopwatch.start("FX_SESSION_RESTORE_COLLECT_DATA_LONGEST_OP_MS"); TelemetryStopwatch.start("FX_SESSION_RESTORE_COLLECT_DATA_LONGEST_OP_MS");
var oState = this._getCurrentState(aUpdateAll, pinnedOnly); var oState = this._getCurrentState(aUpdateAll);
if (!oState) { if (!oState) {
TelemetryStopwatch.cancel("FX_SESSION_RESTORE_COLLECT_DATA_MS"); TelemetryStopwatch.cancel("FX_SESSION_RESTORE_COLLECT_DATA_MS");
TelemetryStopwatch.cancel("FX_SESSION_RESTORE_COLLECT_DATA_LONGEST_OP_MS"); TelemetryStopwatch.cancel("FX_SESSION_RESTORE_COLLECT_DATA_LONGEST_OP_MS");
@ -3844,8 +3807,7 @@ let SessionStoreInternal = {
} }
// Write (atomically) to a session file, using a tmp file. // Write (atomically) to a session file, using a tmp file.
let promise = let promise = _SessionFile.write(data);
_SessionFile.write(data, {backupOnFirstWrite: this._resume_from_crash});
// Once the session file is successfully updated, save the time stamp of the // Once the session file is successfully updated, save the time stamp of the
// last save and notify the observers. // last save and notify the observers.

Просмотреть файл

@ -124,23 +124,33 @@ let Agent = {
/** /**
* Write the session to disk. * Write the session to disk.
*/ */
write: function (stateString, options) { write: function (stateString) {
let exn;
let telemetry = {}; let telemetry = {};
if (!this.hasWrittenState) { if (!this.hasWrittenState) {
if (options && options.backupOnFirstWrite) {
try { try {
let startMs = Date.now(); let startMs = Date.now();
File.move(this.path, this.backupPath); File.move(this.path, this.backupPath);
telemetry.FX_SESSION_RESTORE_BACKUP_FILE_MS = Date.now() - startMs; telemetry.FX_SESSION_RESTORE_BACKUP_FILE_MS = Date.now() - startMs;
} catch (ex if isNoSuchFileEx(ex)) { } catch (ex if isNoSuchFileEx(ex)) {
// Ignore exceptions about non-existent files. // Ignore exceptions about non-existent files.
} } catch (ex) {
// Throw the exception after we wrote the state to disk
// so that the backup can't interfere with the actual write.
exn = ex;
} }
this.hasWrittenState = true; this.hasWrittenState = true;
} }
return this._write(stateString, telemetry); let ret = this._write(stateString, telemetry);
if (exn) {
throw exn;
}
return ret;
}, },
/** /**

Просмотреть файл

@ -67,8 +67,8 @@ this._SessionFile = {
/** /**
* Write the contents of the session file, asynchronously. * Write the contents of the session file, asynchronously.
*/ */
write: function (aData, aOptions = {}) { write: function (aData) {
return SessionFileInternal.write(aData, aOptions); return SessionFileInternal.write(aData);
}, },
/** /**
* Writes the initial state to disk again only to change the session's load * Writes the initial state to disk again only to change the session's load
@ -209,13 +209,13 @@ let SessionFileInternal = {
}); });
}, },
write: function (aData, aOptions) { write: function (aData) {
let refObj = {}; let refObj = {};
return TaskUtils.spawn(function task() { return TaskUtils.spawn(function task() {
TelemetryStopwatch.start("FX_SESSION_RESTORE_WRITE_FILE_LONGEST_OP_MS", refObj); TelemetryStopwatch.start("FX_SESSION_RESTORE_WRITE_FILE_LONGEST_OP_MS", refObj);
try { try {
let promise = SessionWorker.post("write", [aData, aOptions]); let promise = SessionWorker.post("write", [aData]);
// At this point, we measure how long we stop the main thread // At this point, we measure how long we stop the main thread
TelemetryStopwatch.finish("FX_SESSION_RESTORE_WRITE_FILE_LONGEST_OP_MS", refObj); TelemetryStopwatch.finish("FX_SESSION_RESTORE_WRITE_FILE_LONGEST_OP_MS", refObj);

Просмотреть файл

@ -25,7 +25,7 @@ add_task(function test_first_write_backup() {
let initial_content = decoder.decode(yield OS.File.read(pathStore)); let initial_content = decoder.decode(yield OS.File.read(pathStore));
do_check_true(!(yield OS.File.exists(pathBackup))); do_check_true(!(yield OS.File.exists(pathBackup)));
yield _SessionFile.write(content, {backupOnFirstWrite: true}); yield _SessionFile.write(content);
do_check_true(yield OS.File.exists(pathBackup)); do_check_true(yield OS.File.exists(pathBackup));
let backup_content = decoder.decode(yield OS.File.read(pathBackup)); let backup_content = decoder.decode(yield OS.File.read(pathBackup));
@ -38,7 +38,7 @@ add_task(function test_second_write_no_backup() {
let initial_content = decoder.decode(yield OS.File.read(pathStore)); let initial_content = decoder.decode(yield OS.File.read(pathStore));
let initial_backup_content = decoder.decode(yield OS.File.read(pathBackup)); let initial_backup_content = decoder.decode(yield OS.File.read(pathBackup));
yield _SessionFile.write(content, {backupOnFirstWrite: true}); yield _SessionFile.write(content);
let written_content = decoder.decode(yield OS.File.read(pathStore)); let written_content = decoder.decode(yield OS.File.read(pathStore));
do_check_eq(content, written_content); do_check_eq(content, written_content);

Просмотреть файл

@ -1,32 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
let toplevel = this;
Cu.import("resource://gre/modules/osfile.jsm");
function run_test() {
let profd = do_get_profile();
Cu.import("resource:///modules/sessionstore/_SessionFile.jsm", toplevel);
pathStore = OS.Path.join(OS.Constants.Path.profileDir, "sessionstore.js");
pathBackup = OS.Path.join(OS.Constants.Path.profileDir, "sessionstore.bak");
let source = do_get_file("data/sessionstore_valid.js");
source.copyTo(profd, "sessionstore.js");
run_next_test();
}
let pathStore;
let pathBackup;
// Write to the store first with |backupOnFirstWrite: false|,
// and make sure second write does not backup even with
// |backupOnFirstWrite: true|
add_task(function test_no_backup_on_second_write() {
let content = "test_1";
do_check_true(!(yield OS.File.exists(pathBackup)));
yield _SessionFile.write(content, {backupOnFirstWrite: false});
do_check_true(!(yield OS.File.exists(pathBackup)));
yield _SessionFile.write(content, {backupOnFirstWrite: true});
do_check_true(!(yield OS.File.exists(pathBackup)));
});

Просмотреть файл

@ -5,7 +5,6 @@ firefox-appdir = browser
[test_backup.js] [test_backup.js]
[test_backup_once.js] [test_backup_once.js]
[test_no_backup_first_write.js]
[test_startup_nosession_sync.js] [test_startup_nosession_sync.js]
# bug 845190 - thread pool wasn't shutdown assertions # bug 845190 - thread pool wasn't shutdown assertions
skip-if = (os == "win" || "linux") && debug skip-if = (os == "win" || "linux") && debug