diff --git a/browser/components/sessionstore/SessionFile.jsm b/browser/components/sessionstore/SessionFile.jsm index e6c3886f41a3..a9d6429f6a9e 100644 --- a/browser/components/sessionstore/SessionFile.jsm +++ b/browser/components/sessionstore/SessionFile.jsm @@ -451,7 +451,11 @@ var SessionFileInternal = { }, wipe() { - return this._postToWorker("wipe"); + return this._postToWorker("wipe").then(() => { + // After a wipe, we need to make sure to re-initialize upon the next read(), + // because the state variables as sent to the worker have changed. + this._initializationStarted = false; + }); }, _recordTelemetry(telemetry) { diff --git a/browser/components/sessionstore/test/browser_backup_recovery.js b/browser/components/sessionstore/test/browser_backup_recovery.js index 6addfd30f652..ac87500d4206 100644 --- a/browser/components/sessionstore/test/browser_backup_recovery.js +++ b/browser/components/sessionstore/test/browser_backup_recovery.js @@ -22,6 +22,11 @@ function promiseRead(path) { return File.read(path, {encoding: "utf-8", compression: "lz4"}); } +async function reInitSessionFile() { + await SessionFile.wipe(); + await SessionFile.read(); +} + add_task(async function init() { // Make sure that we are not racing with SessionSaver's time based // saves. @@ -40,8 +45,7 @@ add_task(async function test_creation() { await File.writeAtomic(OLD_BACKUP, "sessionstore.bak"); await File.writeAtomic(OLD_UPGRADE_BACKUP, "sessionstore upgrade backup"); - await SessionFile.wipe(); - await SessionFile.read(); // Reinitializes SessionFile + await reInitSessionFile(); // Ensure none of the sessionstore files and backups exists for (let k of Paths.loadOrder) { @@ -63,7 +67,8 @@ add_task(async function test_creation() { ok((await File.exists(Paths.recovery)), "After write, recovery sessionstore file exists again"); ok(!(await File.exists(Paths.recoveryBackup)), "After write, recoveryBackup sessionstore doesn't exist"); ok((await promiseRead(Paths.recovery)).includes(URL), "Recovery sessionstore file contains the required tab"); - ok(!(await File.exists(Paths.clean)), "After first write, clean shutdown sessionstore doesn't exist, since we haven't shutdown yet"); + ok(!(await File.exists(Paths.clean)), "After first write, clean shutdown " + + "sessionstore doesn't exist, since we haven't shutdown yet"); // Open a second tab, save session, ensure that the correct files exist. info("Testing situation after a second write"); @@ -79,17 +84,20 @@ add_task(async function test_creation() { let backup = await promiseRead(Paths.recoveryBackup); ok(!backup.includes(URL2), "Recovery backup doesn't contain the latest url"); ok(backup.includes(URL), "Recovery backup contains the original url"); - ok(!(await File.exists(Paths.clean)), "After first write, clean shutdown sessinstore doesn't exist, since we haven't shutdown yet"); + ok(!(await File.exists(Paths.clean)), "After first write, clean shutdown " + + "sessionstore doesn't exist, since we haven't shutdown yet"); info("Reinitialize, ensure that we haven't leaked sensitive files"); await SessionFile.read(); // Reinitializes SessionFile await SessionSaver.run(); - ok(!(await File.exists(Paths.clean)), "After second write, clean shutdown sessonstore doesn't exist, since we haven't shutdown yet"); - ok(!(await File.exists(Paths.upgradeBackup)), "After second write, clean shutdwn sessionstore doesn't exist, since we haven't shutdown yet"); - ok(!(await File.exists(Paths.nextUpgradeBackup)), "After second write, clean sutdown sessionstore doesn't exist, since we haven't shutdown yet"); + ok(!(await File.exists(Paths.clean)), "After second write, clean shutdown " + + "sessionstore doesn't exist, since we haven't shutdown yet"); + ok(!(await File.exists(Paths.upgradeBackup)), "After second write, clean " + + "shutdown sessionstore doesn't exist, since we haven't shutdown yet"); + ok(!(await File.exists(Paths.nextUpgradeBackup)), "After second write, clean " + + "shutdown sessionstore doesn't exist, since we haven't shutdown yet"); gBrowser.removeTab(tab); - await SessionFile.wipe(); }); var promiseSource = async function(name) { @@ -107,8 +115,7 @@ var promiseSource = async function(name) { }; add_task(async function test_recovery() { - // Remove all files. - await SessionFile.wipe(); + await reInitSessionFile(); info("Attempting to recover from the recovery file"); // Create Paths.recovery, ensure that we can recover from it. @@ -116,7 +123,6 @@ add_task(async function test_recovery() { await File.makeDir(Paths.backups); await File.writeAtomic(Paths.recovery, SOURCE, {encoding: "utf-8", compression: "lz4"}); is((await SessionFile.read()).source, SOURCE, "Recovered the correct source from the recovery file"); - await SessionFile.wipe(); info("Corrupting recovery file, attempting to recover from recovery backup"); SOURCE = await promiseSource("Paths.recoveryBackup"); @@ -124,7 +130,6 @@ add_task(async function test_recovery() { await File.writeAtomic(Paths.recoveryBackup, SOURCE, {encoding: "utf-8", compression: "lz4"}); await File.writeAtomic(Paths.recovery, "", {encoding: "utf-8", compression: "lz4"}); is((await SessionFile.read()).source, SOURCE, "Recovered the correct source from the recovery file"); - await SessionFile.wipe(); }); add_task(async function test_recovery_inaccessible() { @@ -133,6 +138,7 @@ add_task(async function test_recovery_inaccessible() { return; } + await reInitSessionFile(); info("Making recovery file inaccessible, attempting to recover from recovery backup"); let SOURCE_RECOVERY = await promiseSource("Paths.recovery"); let SOURCE = await promiseSource("Paths.recoveryBackup"); @@ -148,12 +154,13 @@ add_task(async function test_recovery_inaccessible() { }); add_task(async function test_clean() { - await SessionFile.wipe(); + await reInitSessionFile(); let SOURCE = await promiseSource("Paths.clean"); await File.writeAtomic(Paths.clean, SOURCE, {encoding: "utf-8", compression: "lz4"}); await SessionFile.read(); await SessionSaver.run(); - is((await promiseRead(Paths.cleanBackup)), SOURCE, "After first read/write, clean shutdown file has been moved to cleanBackup"); + is((await promiseRead(Paths.cleanBackup)), SOURCE, "After first read/write, " + + "clean shutdown file has been moved to cleanBackup"); }); @@ -180,6 +187,7 @@ add_task(async function test_version() { * Tests fallback to previous backups if format version is unknown. */ add_task(async function test_version_fallback() { + await reInitSessionFile(); info("Preparing data, making sure that it has a version number"); let SOURCE = await promiseSource("Paths.clean"); let BACKUP_SOURCE = await promiseSource("Paths.cleanBackup"); @@ -205,5 +213,5 @@ add_task(async function test_version_fallback() { }); add_task(async function cleanup() { - await SessionFile.wipe(); + await reInitSessionFile(); }); diff --git a/browser/components/sessionstore/test/browser_upgrade_backup.js b/browser/components/sessionstore/test/browser_upgrade_backup.js index de79b27eb10d..881a66747662 100644 --- a/browser/components/sessionstore/test/browser_upgrade_backup.js +++ b/browser/components/sessionstore/test/browser_upgrade_backup.js @@ -14,7 +14,7 @@ const PREF_MAX_UPGRADE_BACKUPS = "browser.sessionstore.upgradeBackup.maxUpgradeB * build where the last backup was created and creating arbitrary JSON data * for a new backup. */ -var prepareTest = async function() { +function prepareTest() { let result = {}; result.buildID = Services.appinfo.platformBuildID; @@ -22,12 +22,12 @@ var prepareTest = async function() { result.contents = JSON.stringify({"browser_upgrade_backup.js": Math.random()}); return result; -}; +} /** * Retrieves all upgrade backups and returns them in an array. */ -var getUpgradeBackups = async function() { +async function getUpgradeBackups() { let iterator; let backups = []; @@ -50,17 +50,17 @@ var getUpgradeBackups = async function() { // return results return backups; -}; +} add_task(async function init() { // Wait until initialization is complete await SessionStore.promiseInitialized; - await SessionFile.wipe(); }); add_task(async function test_upgrade_backup() { - let test = await prepareTest(); + let test = prepareTest(); info("Let's check if we create an upgrade backup"); + await SessionFile.wipe(); await OS.File.writeAtomic(Paths.clean, test.contents, {encoding: "utf-8", compression: "lz4"}); await SessionFile.read(); // First call to read() initializes the SessionWorker await SessionFile.write(""); // First call to write() triggers the backup @@ -82,9 +82,11 @@ add_task(async function test_upgrade_backup() { }); add_task(async function test_upgrade_backup_removal() { - let test = await prepareTest(); + let test = prepareTest(); let maxUpgradeBackups = Preferences.get(PREF_MAX_UPGRADE_BACKUPS, 3); info("Let's see if we remove backups if there are too many"); + await SessionFile.wipe(); + await OS.File.makeDir(Paths.backups); await OS.File.writeAtomic(Paths.clean, test.contents, {encoding: "utf-8", compression: "lz4"}); // if the nextUpgradeBackup already exists (from another test), remove it diff --git a/browser/components/sessionstore/test/unit/test_shutdown_cleanup.js b/browser/components/sessionstore/test/unit/test_shutdown_cleanup.js index 8e54f8056486..6856e0dce2bb 100644 --- a/browser/components/sessionstore/test/unit/test_shutdown_cleanup.js +++ b/browser/components/sessionstore/test/unit/test_shutdown_cleanup.js @@ -28,13 +28,26 @@ updateAppInfo({ platformVersion: "", }); -add_task(async function setup() { - let source = do_get_file("data/sessionstore_valid.js"); - source.copyTo(profd, "sessionstore.js"); +var gSourceHandle; + +async function prepareWithLimit(back, fwd) { + await SessionFile.wipe(); + + if (!gSourceHandle) { + gSourceHandle = do_get_file("data/sessionstore_valid.js"); + } + gSourceHandle.copyTo(profd, "sessionstore.js"); await writeCompressedFile(Paths.clean.replace("jsonlz4", "js"), Paths.clean); + Services.prefs.setIntPref("browser.sessionstore.max_serialize_back", back); + Services.prefs.setIntPref("browser.sessionstore.max_serialize_forward", fwd); + // Finish SessionFile initialization. await SessionFile.read(); +} + +add_task(async function setup() { + await SessionFile.read(); // Reset prefs on cleanup. registerCleanupFunction(() => { @@ -54,12 +67,6 @@ function createSessionState(index) { return {windows: [{tabs: [tabState]}]}; } -async function setMaxBackForward(back, fwd) { - Services.prefs.setIntPref("browser.sessionstore.max_serialize_back", back); - Services.prefs.setIntPref("browser.sessionstore.max_serialize_forward", fwd); - await SessionFile.read(); -} - async function writeAndParse(state, path, options = {}) { await SessionWorker.post("write", [state, options]); return JSON.parse(await File.read(path, {encoding: "utf-8", compression: "lz4"})); @@ -69,7 +76,7 @@ add_task(async function test_shistory_cap_none() { let state = createSessionState(5); // Don't limit the number of shistory entries. - await setMaxBackForward(-1, -1); + await prepareWithLimit(-1, -1); // Check that no caps are applied. let diskState = await writeAndParse(state, Paths.clean, {isFinalWrite: true}); @@ -78,7 +85,7 @@ add_task(async function test_shistory_cap_none() { add_task(async function test_shistory_cap_middle() { let state = createSessionState(5); - await setMaxBackForward(2, 3); + await prepareWithLimit(2, 3); // Cap is only applied on clean shutdown. let diskState = await writeAndParse(state, Paths.recovery); @@ -95,7 +102,7 @@ add_task(async function test_shistory_cap_middle() { add_task(async function test_shistory_cap_lower_bound() { let state = createSessionState(1); - await setMaxBackForward(5, 5); + await prepareWithLimit(5, 5); // Cap is only applied on clean shutdown. let diskState = await writeAndParse(state, Paths.recovery); @@ -110,7 +117,7 @@ add_task(async function test_shistory_cap_lower_bound() { add_task(async function test_shistory_cap_upper_bound() { let state = createSessionState(MAX_ENTRIES); - await setMaxBackForward(5, 5); + await prepareWithLimit(5, 5); // Cap is only applied on clean shutdown. let diskState = await writeAndParse(state, Paths.recovery); @@ -124,3 +131,8 @@ add_task(async function test_shistory_cap_upper_bound() { tabState.index = 6; Assert.deepEqual(state, diskState, "cap applied"); }); + +add_task(async function cleanup() { + await SessionFile.wipe(); + await SessionFile.read(); +});