commit bcae7607639931bf4edd7b95d8bff93c375f3cde parent d94b0b02b72143fab4c92892d1a67f27f3b24c59 Author: Harsheet <hsohaney@mozilla.com> Date: Wed, 17 Dec 2025 02:02:22 +0000 Bug 1994875 - Test updates. r=mconley Differential Revision: https://phabricator.services.mozilla.com/D272080 Diffstat:
9 files changed, 534 insertions(+), 309 deletions(-)
diff --git a/browser/components/backup/tests/xpcshell/head.js b/browser/components/backup/tests/xpcshell/head.js @@ -20,6 +20,16 @@ ChromeUtils.defineESModuleGetters(this, { const HISTORY_ENABLED_PREF = "places.history.enabled"; const SANITIZE_ON_SHUTDOWN_PREF = "privacy.sanitize.sanitizeOnShutdown"; +const USE_OLD_CLEAR_HISTORY_DIALOG_PREF = + "privacy.sanitize.useOldClearHistoryDialog"; +const FORM_HISTORY_CLEARED_ON_SHUTDOWN_PREF = + "privacy.clearOnShutdown_v2.formdata"; +const HISTORY_CLEARED_ON_SHUTDOWN_PREF = + "privacy.clearOnShutdown_v2.browsingHistoryAndDownloads"; +const SITE_SETTINGS_CLEARED_ON_SHUTDOWN_PREF = + "privacy.clearOnShutdown_v2.siteSettings"; +const SITE_SETTINGS_CLEARED_ON_SHUTDOWN_OLD_PREF = + "privacy.clearOnShutdown.siteSettings"; let gFakeOSKeyStore; diff --git a/browser/components/backup/tests/xpcshell/test_BackupResource.js b/browser/components/backup/tests/xpcshell/test_BackupResource.js @@ -7,6 +7,14 @@ const { bytesToFuzzyKilobytes } = ChromeUtils.importESModule( "resource:///modules/backup/BackupResource.sys.mjs" ); +const { BookmarksBackupResource } = ChromeUtils.importESModule( + "resource:///modules/backup/BookmarksBackupResource.sys.mjs" +); + +const { PlacesBackupResource } = ChromeUtils.importESModule( + "resource:///modules/backup/PlacesBackupResource.sys.mjs" +); + const EXPECTED_KILOBYTES_FOR_XULSTORE = 1; /** @@ -248,3 +256,32 @@ add_task(async function test_copyFiles() { await maybeRemovePath(sourcePath); await maybeRemovePath(destPath); }); + +add_task(async function test_bookmarks_places_backup_relation() { + // If places can be backed up, we don't need to backup bookmarks separately + Services.prefs.setBoolPref(HISTORY_ENABLED_PREF, true); + Services.prefs.setBoolPref(SANITIZE_ON_SHUTDOWN_PREF, false); + + Assert.ok(PlacesBackupResource.canBackupResource, "Places can be backed up"); + + Assert.ok( + !BookmarksBackupResource.canBackupResource, + "Bookmarks won't be backed up separately" + ); + + // If places can't be backed up, we need to backup bookmarks separately + Services.prefs.setBoolPref(SANITIZE_ON_SHUTDOWN_PREF, true); + + Assert.ok( + !PlacesBackupResource.canBackupResource, + "Places can not be backed up" + ); + + Assert.ok( + BookmarksBackupResource.canBackupResource, + "Bookmarks will be backed up separately" + ); + + Services.prefs.clearUserPref(HISTORY_ENABLED_PREF); + Services.prefs.clearUserPref(SANITIZE_ON_SHUTDOWN_PREF); +}); diff --git a/browser/components/backup/tests/xpcshell/test_BookmarksBackupResource.js b/browser/components/backup/tests/xpcshell/test_BookmarksBackupResource.js @@ -0,0 +1,162 @@ +/* Any copyright is dedicated to the Public Domain. +https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { BookmarksBackupResource } = ChromeUtils.importESModule( + "resource:///modules/backup/BookmarksBackupResource.sys.mjs" +); +const { BookmarkJSONUtils } = ChromeUtils.importESModule( + "resource://gre/modules/BookmarkJSONUtils.sys.mjs" +); + +/** + * Test that the backup method correctly creates a compressed bookmarks JSON file. + */ +add_task(async function test_backup() { + let sandbox = sinon.createSandbox(); + + let bookmarksBackupResource = new BookmarksBackupResource(); + let sourcePath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "BookmarksBackupResource-source-test" + ); + let stagingPath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "BookmarksBackupResource-staging-test" + ); + + let exportStub = sandbox.stub(BookmarkJSONUtils, "exportToFile").resolves(); + + let manifestEntry = await bookmarksBackupResource.backup( + stagingPath, + sourcePath + ); + Assert.equal( + manifestEntry, + null, + "BookmarksBackupResource.backup should return null as its ManifestEntry" + ); + + Assert.ok( + exportStub.calledOnce, + "BookmarkJSONUtils.exportToFile should have been called once" + ); + Assert.ok( + exportStub.calledWith(PathUtils.join(stagingPath, "bookmarks.jsonlz4"), { + compress: true, + }), + "BookmarkJSONUtils.exportToFile should have been called with the correct arguments" + ); + + await maybeRemovePath(stagingPath); + await maybeRemovePath(sourcePath); + + sandbox.restore(); +}); + +/** + * Test that the recover method correctly returns the path to the bookmarks backup file. + */ +add_task(async function test_recover() { + let bookmarksBackupResource = new BookmarksBackupResource(); + let recoveryPath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "BookmarksBackupResource-recovery-test" + ); + let destProfilePath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "BookmarksBackupResource-test-profile" + ); + + await createTestFiles(recoveryPath, [{ path: "bookmarks.jsonlz4" }]); + + let postRecoveryEntry = await bookmarksBackupResource.recover( + null, + recoveryPath, + destProfilePath + ); + + let expectedBookmarksPath = PathUtils.join(recoveryPath, "bookmarks.jsonlz4"); + + Assert.deepEqual( + postRecoveryEntry, + { bookmarksBackupPath: expectedBookmarksPath }, + "BookmarksBackupResource.recover should return the path to the bookmarks backup file" + ); + + // The bookmarks file should not be copied to the destination profile during recovery, + // it will be imported in postRecovery + Assert.ok( + !(await IOUtils.exists( + PathUtils.join(destProfilePath, "bookmarks.jsonlz4") + )), + "bookmarks.jsonlz4 should not exist in the destination profile yet" + ); + + await maybeRemovePath(recoveryPath); + await maybeRemovePath(destProfilePath); +}); + +/** + * Test that the postRecovery method correctly imports bookmarks from the backup file. + */ +add_task(async function test_postRecovery() { + let sandbox = sinon.createSandbox(); + + let bookmarksBackupResource = new BookmarksBackupResource(); + let recoveryPath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "BookmarksBackupResource-recovery-test" + ); + + await createTestFiles(recoveryPath, [{ path: "bookmarks.jsonlz4" }]); + + let bookmarksBackupPath = PathUtils.join(recoveryPath, "bookmarks.jsonlz4"); + let importStub = sandbox + .stub(BookmarkJSONUtils, "importFromFile") + .resolves(true); + + await bookmarksBackupResource.postRecovery({ bookmarksBackupPath }); + + Assert.ok( + importStub.calledOnce, + "BookmarkJSONUtils.importFromFile should have been called once" + ); + Assert.ok( + importStub.calledWith(bookmarksBackupPath, { replace: true }), + "BookmarkJSONUtils.importFromFile should have been called with the correct arguments" + ); + + await maybeRemovePath(recoveryPath); + + sandbox.restore(); +}); + +/** + * Test that postRecovery handles missing bookmarksBackupPath gracefully. + */ +add_task(async function test_postRecovery_no_path() { + let sandbox = sinon.createSandbox(); + + let bookmarksBackupResource = new BookmarksBackupResource(); + let importStub = sandbox + .stub(BookmarkJSONUtils, "importFromFile") + .resolves(true); + + await bookmarksBackupResource.postRecovery(null); + + Assert.ok( + importStub.notCalled, + "BookmarkJSONUtils.importFromFile should not have been called with null postRecoveryEntry" + ); + + await bookmarksBackupResource.postRecovery({}); + + Assert.ok( + importStub.notCalled, + "BookmarkJSONUtils.importFromFile should not have been called with empty postRecoveryEntry" + ); + + sandbox.restore(); +}); diff --git a/browser/components/backup/tests/xpcshell/test_CookiesBackupResource.js b/browser/components/backup/tests/xpcshell/test_CookiesBackupResource.js @@ -131,19 +131,9 @@ add_task(async function test_backup_no_saved_history() { Services.prefs.setBoolPref(HISTORY_ENABLED_PREF, false); Services.prefs.setBoolPref(SANITIZE_ON_SHUTDOWN_PREF, false); - let manifestEntry = await cookiesBackupResource.backup( - stagingPath, - sourcePath - ); - Assert.deepEqual( - manifestEntry, - null, - "Should have gotten back a null ManifestEntry" - ); - Assert.ok( - fakeConnection.backup.notCalled, - "No sqlite connections should have been made with remember history disabled" + !CookiesBackupResource.canBackupResource, + "Should not be able to backup cookies" ); // Now verify that the sanitize shutdown pref also prevents us from backing @@ -152,7 +142,10 @@ add_task(async function test_backup_no_saved_history() { Services.prefs.setBoolPref(SANITIZE_ON_SHUTDOWN_PREF, true); fakeConnection.backup.resetHistory(); - manifestEntry = await cookiesBackupResource.backup(stagingPath, sourcePath); + let manifestEntry = await cookiesBackupResource.backup( + stagingPath, + sourcePath + ); Assert.deepEqual( manifestEntry, null, diff --git a/browser/components/backup/tests/xpcshell/test_FormHistoryBackupResource.js b/browser/components/backup/tests/xpcshell/test_FormHistoryBackupResource.js @@ -131,18 +131,23 @@ add_task(async function test_backup_no_saved_history() { }; sandbox.stub(Sqlite, "openConnection").returns(fakeConnection); - // First, we'll try with browsing history in general being disabled. - Services.prefs.setBoolPref(HISTORY_ENABLED_PREF, false); - Services.prefs.setBoolPref(SANITIZE_ON_SHUTDOWN_PREF, false); + Services.prefs.setBoolPref(FORM_HISTORY_CLEARED_ON_SHUTDOWN_PREF, true); + Services.prefs.setBoolPref(SANITIZE_ON_SHUTDOWN_PREF, true); - let manifestEntry = await formHistoryBackupResource.backup( - stagingPath, - sourcePath + Assert.ok( + !FormHistoryBackupResource.canBackupResource, + "Cannot backup form history since it is being cleared on shutdown" ); - Assert.deepEqual( - manifestEntry, - null, - "Should have gotten back a null ManifestEntry" + + Services.prefs.setBoolPref(SANITIZE_ON_SHUTDOWN_PREF, false); + Services.prefs.setBoolPref(FORM_HISTORY_CLEARED_ON_SHUTDOWN_PREF, false); + + // We'll try with browsing history in general being disabled. + Services.prefs.setBoolPref(HISTORY_ENABLED_PREF, false); + + Assert.ok( + !FormHistoryBackupResource.canBackupResource, + "Cannot backup form history since it is being cleared on shutdown" ); Assert.ok( @@ -150,13 +155,15 @@ add_task(async function test_backup_no_saved_history() { "No sqlite connections should have been made with remember history disabled" ); - // Now verify that the sanitize shutdown pref also prevents us from backing - // up form history Services.prefs.setBoolPref(HISTORY_ENABLED_PREF, true); - Services.prefs.setBoolPref(SANITIZE_ON_SHUTDOWN_PREF, true); + + Assert.ok( + FormHistoryBackupResource.canBackupResource, + "We should be allowed to backup this resource now" + ); fakeConnection.backup.resetHistory(); - manifestEntry = await formHistoryBackupResource.backup( + let manifestEntry = await formHistoryBackupResource.backup( stagingPath, sourcePath ); @@ -185,42 +192,13 @@ add_task(async function test_backup_no_saved_history() { */ add_task(async function test_backup_private_browsing() { let sandbox = sinon.createSandbox(); - - let formHistoryBackupResource = new FormHistoryBackupResource(); - let sourcePath = await IOUtils.createUniqueDirectory( - PathUtils.tempDir, - "FormHistoryBackupResource-source-test" - ); - let stagingPath = await IOUtils.createUniqueDirectory( - PathUtils.tempDir, - "FormHistoryBackupResource-staging-test" - ); - - let fakeConnection = { - backup: sandbox.stub().resolves(true), - close: sandbox.stub().resolves(true), - }; - sandbox.stub(Sqlite, "openConnection").returns(fakeConnection); sandbox.stub(PrivateBrowsingUtils, "permanentPrivateBrowsing").value(true); - let manifestEntry = await formHistoryBackupResource.backup( - stagingPath, - sourcePath - ); - Assert.deepEqual( - manifestEntry, - null, - "Should have gotten back a null ManifestEntry" - ); - Assert.ok( - fakeConnection.backup.notCalled, - "No sqlite connections should have been made with permanent private browsing enabled" + !FormHistoryBackupResource.canBackupResource, + "Cannot backup form history since Private Browsing is enabled" ); - await maybeRemovePath(stagingPath); - await maybeRemovePath(sourcePath); - sandbox.restore(); }); diff --git a/browser/components/backup/tests/xpcshell/test_PlacesBackupResource.js b/browser/components/backup/tests/xpcshell/test_PlacesBackupResource.js @@ -3,9 +3,6 @@ https://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; -const { BookmarkJSONUtils } = ChromeUtils.importESModule( - "resource://gre/modules/BookmarkJSONUtils.sys.mjs" -); const { PlacesBackupResource } = ChromeUtils.importESModule( "resource:///modules/backup/PlacesBackupResource.sys.mjs" ); @@ -157,8 +154,8 @@ add_task(async function test_backup() { }); /** - * Tests that the backup method correctly creates a compressed bookmarks JSON file when users - * don't want history saved, even on shutdown. + * Tests that we don't backup history is the user is clearing browsing history + * on shutdown. */ add_task(async function test_backup_no_saved_history() { Services.fog.testResetFOG(); @@ -170,7 +167,6 @@ add_task(async function test_backup_no_saved_history() { ); let sandbox = sinon.createSandbox(); - let placesBackupResource = new PlacesBackupResource(); let sourcePath = await IOUtils.createUniqueDirectory( PathUtils.tempDir, "PlacesBackupResource-source-test" @@ -193,22 +189,13 @@ add_task(async function test_backup_no_saved_history() { Services.prefs.setBoolPref(HISTORY_ENABLED_PREF, false); Services.prefs.setBoolPref(SANITIZE_ON_SHUTDOWN_PREF, false); - let manifestEntry = await placesBackupResource.backup( - stagingPath, - sourcePath - ); - Assert.deepEqual( - manifestEntry, - { bookmarksOnly: true }, - "Should have gotten back a ManifestEntry indicating that we only copied " + - "bookmarks" - ); - Assert.ok( - fakeConnection.backup.notCalled, - "No sqlite connections should have been made with remember history disabled" + !PlacesBackupResource.canBackupResource, + "Cannot backup places when history is disabled" ); - await assertFilesExist(stagingPath, [{ path: "bookmarks.jsonlz4" }]); + + // PlacesBackupResource should not be called when canBackupResource is false + // The test is just verifying the check works correctly // Validate no timing metrics Assert.equal( Glean.browserBackup.placesTime.testGetValue(), @@ -223,29 +210,20 @@ add_task(async function test_backup_no_saved_history() { assertHistogramMeasurementQuantity(placesTimeHistogram, 0); assertHistogramMeasurementQuantity(faviconsTimeHistogram, 0); - await IOUtils.remove(PathUtils.join(stagingPath, "bookmarks.jsonlz4")); - /** - * Now verify that the sanitize shutdown pref alone affects backup file type for places, - * even if the user is okay with remembering history while browsing. + * Now verify that the sanitize shutdown pref also prevents backup of places. */ Services.prefs.setBoolPref(HISTORY_ENABLED_PREF, true); Services.prefs.setBoolPref(SANITIZE_ON_SHUTDOWN_PREF, true); - - fakeConnection.backup.resetHistory(); - manifestEntry = await placesBackupResource.backup(stagingPath, sourcePath); - Assert.deepEqual( - manifestEntry, - { bookmarksOnly: true }, - "Should have gotten back a ManifestEntry indicating that we only copied " + - "bookmarks" - ); + Services.prefs.setBoolPref(HISTORY_CLEARED_ON_SHUTDOWN_PREF, true); Assert.ok( - fakeConnection.backup.notCalled, - "No sqlite connections should have been made with sanitize shutdown enabled" + !PlacesBackupResource.canBackupResource, + "Cannot backup places when sanitizeOnShutdown and history cleared on shutdown are enabled" ); - await assertFilesExist(stagingPath, [{ path: "bookmarks.jsonlz4" }]); + + // PlacesBackupResource should not be called when canBackupResource is false + // The test is just verifying the check works correctly // Validate no timing metrics Assert.equal( Glean.browserBackup.placesTime.testGetValue(), @@ -266,11 +244,11 @@ add_task(async function test_backup_no_saved_history() { sandbox.restore(); Services.prefs.clearUserPref(HISTORY_ENABLED_PREF); Services.prefs.clearUserPref(SANITIZE_ON_SHUTDOWN_PREF); + Services.prefs.clearUserPref(HISTORY_CLEARED_ON_SHUTDOWN_PREF); }); /** - * Tests that the backup method correctly creates a compressed bookmarks JSON file when - * permanent private browsing mode is enabled. + * Tests that we don't backup history if permanent private browsing is enabled */ add_task(async function test_backup_private_browsing() { Services.fog.testResetFOG(); @@ -282,7 +260,6 @@ add_task(async function test_backup_private_browsing() { ); let sandbox = sinon.createSandbox(); - let placesBackupResource = new PlacesBackupResource(); let sourcePath = await IOUtils.createUniqueDirectory( PathUtils.tempDir, "PlacesBackupResource-source-test" @@ -299,22 +276,13 @@ add_task(async function test_backup_private_browsing() { sandbox.stub(Sqlite, "openConnection").returns(fakeConnection); sandbox.stub(PrivateBrowsingUtils, "permanentPrivateBrowsing").value(true); - let manifestEntry = await placesBackupResource.backup( - stagingPath, - sourcePath - ); - Assert.deepEqual( - manifestEntry, - { bookmarksOnly: true }, - "Should have gotten back a ManifestEntry indicating that we only copied " + - "bookmarks" - ); - Assert.ok( - fakeConnection.backup.notCalled, - "No sqlite connections should have been made with permanent private browsing enabled" + !PlacesBackupResource.canBackupResource, + "Cannot backup places when permanent private browsing is enabled" ); - await assertFilesExist(stagingPath, [{ path: "bookmarks.jsonlz4" }]); + + // PlacesBackupResource should not be called when canBackupResource is false + // The test is just verifying the check works correctly // Validate no timing metrics Assert.equal( Glean.browserBackup.placesTime.testGetValue(), @@ -375,63 +343,33 @@ add_task(async function test_recover() { }); /** - * Test that the recover method correctly copies bookmarks.jsonlz4 from the recovery - * directory into the destination profile directory. + * Tests the canBackupResource method with various pref configurations. */ -add_task(async function test_recover_bookmarks_only() { - let sandbox = sinon.createSandbox(); - let placesBackupResource = new PlacesBackupResource(); - let recoveryPath = await IOUtils.createUniqueDirectory( - PathUtils.tempDir, - "PlacesBackupResource-recovery-test" - ); - let destProfilePath = await IOUtils.createUniqueDirectory( - PathUtils.tempDir, - "PlacesBackupResource-test-profile" +add_task(async function test_canBackupResource() { + Assert.ok( + PlacesBackupResource.canBackupResource, + "Should be able to backup by default" ); - let bookmarksImportStub = sandbox - .stub(BookmarkJSONUtils, "importFromFile") - .resolves(true); - - await createTestFiles(recoveryPath, [{ path: "bookmarks.jsonlz4" }]); - // The backup method is expected to detect bookmarks import only - let postRecoveryEntry = await placesBackupResource.recover( - { bookmarksOnly: true }, - recoveryPath, - destProfilePath + Services.prefs.setBoolPref(HISTORY_ENABLED_PREF, false); + Assert.ok( + !PlacesBackupResource.canBackupResource, + "Cannot backup when history is disabled" ); + Services.prefs.clearUserPref(HISTORY_ENABLED_PREF); - let expectedBookmarksPath = PathUtils.join(recoveryPath, "bookmarks.jsonlz4"); - - // Expect the bookmarks backup file path to be passed from recover() - Assert.deepEqual( - postRecoveryEntry, - { bookmarksBackupPath: expectedBookmarksPath }, - "PlacesBackupResource.recover should return the expected post recovery entry" - ); - - // Ensure that files stored in a places backup are not copied to the new profile during recovery - for (let placesFile of [ - "places.sqlite", - "favicons.sqlite", - "bookmarks.jsonlz4", - ]) { - Assert.ok( - !(await IOUtils.exists(PathUtils.join(destProfilePath, placesFile))), - `${placesFile} should not exist in the new profile` - ); - } - - // Now pretend that BackupService called the postRecovery method - await placesBackupResource.postRecovery(postRecoveryEntry); Assert.ok( - bookmarksImportStub.calledOnce, - "BookmarkJSONUtils.importFromFile was called in the postRecovery step" + PlacesBackupResource.canBackupResource, + "Should be able to backup after clearing pref" ); - await maybeRemovePath(recoveryPath); - await maybeRemovePath(destProfilePath); + Services.prefs.setBoolPref(SANITIZE_ON_SHUTDOWN_PREF, true); + Services.prefs.setBoolPref(HISTORY_CLEARED_ON_SHUTDOWN_PREF, true); + Assert.ok( + !PlacesBackupResource.canBackupResource, + "Cannot backup when sanitizeOnShutdown and history cleared on shutdown are enabled" + ); - sandbox.restore(); + Services.prefs.clearUserPref(SANITIZE_ON_SHUTDOWN_PREF); + Services.prefs.clearUserPref(HISTORY_CLEARED_ON_SHUTDOWN_PREF); }); diff --git a/browser/components/backup/tests/xpcshell/test_PreferencesBackupResource.js b/browser/components/backup/tests/xpcshell/test_PreferencesBackupResource.js @@ -17,7 +17,7 @@ const { SearchUtils } = ChromeUtils.importESModule( add_task(async function test_measure() { Services.fog.testResetFOG(); - const EXPECTED_PREFERENCES_KILOBYTES_SIZE = 415; + const EXPECTED_PREFERENCES_KILOBYTES_SIZE = 55; const tempDir = await IOUtils.createUniqueDirectory( PathUtils.tempDir, "PreferencesBackupResource-measure-test" @@ -25,8 +25,6 @@ add_task(async function test_measure() { const mockFiles = [ { path: "prefs.js", sizeInKB: 20 }, { path: "xulstore.json", sizeInKB: 1 }, - { path: "permissions.sqlite", sizeInKB: 100 }, - { path: "content-prefs.sqlite", sizeInKB: 260 }, { path: "containers.json", sizeInKB: 1 }, { path: "handlers.json", sizeInKB: 1 }, { path: "search.json.mozlz4", sizeInKB: 1 }, @@ -89,14 +87,6 @@ add_task(async function test_backup() { ]; await createTestFiles(sourcePath, simpleCopyFiles); - // Create our fake database files. We don't expect these to be copied to the - // staging directory in this test due to our stubbing of the backup method, so - // we don't include it in `simpleCopyFiles`. - await createTestFiles(sourcePath, [ - { path: "permissions.sqlite" }, - { path: "content-prefs.sqlite" }, - ]); - // We have no need to test that Sqlite.sys.mjs's backup method is working - // this is something that is tested in Sqlite's own tests. We can just make // sure that it's being called using sinon. Unfortunately, we cannot do the @@ -120,23 +110,9 @@ add_task(async function test_backup() { await assertFilesExist(stagingPath, simpleCopyFiles); - // Next, we'll make sure that the Sqlite connection had `backup` called on it - // with the right arguments. - Assert.ok( - fakeConnection.backup.calledTwice, - "Called backup the expected number of times for all connections" - ); Assert.ok( - fakeConnection.backup.firstCall.calledWith( - PathUtils.join(stagingPath, "permissions.sqlite") - ), - "Called backup on the permissions.sqlite Sqlite connection" - ); - Assert.ok( - fakeConnection.backup.secondCall.calledWith( - PathUtils.join(stagingPath, "content-prefs.sqlite") - ), - "Called backup on the content-prefs.sqlite Sqlite connection" + fakeConnection.backup.notCalled, + "No sqlite connections should have been made" ); // And we'll make sure that preferences were properly written out. @@ -152,125 +128,6 @@ add_task(async function test_backup() { }); /** - * Tests that the backup method does not copy the permissions or content prefs - * databases if the browser is configured to not save history - either while - * running, or to clear it at shutdown. - */ -add_task(async function test_backup_no_saved_history() { - let preferencesBackupResource = new PreferencesBackupResource(); - let sourcePath = await IOUtils.createUniqueDirectory( - PathUtils.tempDir, - "PreferencesBackupResource-source-test" - ); - let stagingPath = await IOUtils.createUniqueDirectory( - PathUtils.tempDir, - "PreferencesBackupResource-staging-test" - ); - - let sandbox = sinon.createSandbox(); - let fakeConnection = { - backup: sandbox.stub().resolves(true), - close: sandbox.stub().resolves(true), - }; - sandbox.stub(Sqlite, "openConnection").returns(fakeConnection); - - // First, we'll try with browsing history in general being disabled. - Services.prefs.setBoolPref(HISTORY_ENABLED_PREF, false); - Services.prefs.setBoolPref(SANITIZE_ON_SHUTDOWN_PREF, false); - - let manifestEntry = await preferencesBackupResource.backup( - stagingPath, - sourcePath - ); - Assert.deepEqual( - manifestEntry, - { profilePath: sourcePath }, - "PreferencesBackupResource.backup should return the original profile path " + - "in its ManifestEntry" - ); - - Assert.ok( - fakeConnection.backup.notCalled, - "No sqlite connections should have been made with remember history disabled" - ); - - // Now verify that the sanitize shutdown pref also prevents us from backing - // up site permissions and preferences - Services.prefs.setBoolPref(HISTORY_ENABLED_PREF, true); - Services.prefs.setBoolPref(SANITIZE_ON_SHUTDOWN_PREF, true); - - fakeConnection.backup.resetHistory(); - manifestEntry = await preferencesBackupResource.backup( - stagingPath, - sourcePath - ); - Assert.deepEqual( - manifestEntry, - { profilePath: sourcePath }, - "PreferencesBackupResource.backup should return the original profile path " + - "in its ManifestEntry" - ); - - Assert.ok( - fakeConnection.backup.notCalled, - "No sqlite connections should have been made with sanitize shutdown enabled" - ); - - await maybeRemovePath(stagingPath); - await maybeRemovePath(sourcePath); - - sandbox.restore(); - Services.prefs.clearUserPref(HISTORY_ENABLED_PREF); - Services.prefs.clearUserPref(SANITIZE_ON_SHUTDOWN_PREF); -}); - -/** - * Tests that the backup method correctly skips backing up the permissions and - * content prefs databases if permanent private browsing mode is enabled. - */ -add_task(async function test_backup_private_browsing() { - let sandbox = sinon.createSandbox(); - - let preferencesBackupResource = new PreferencesBackupResource(); - let sourcePath = await IOUtils.createUniqueDirectory( - PathUtils.tempDir, - "PreferencesBackupResource-source-test" - ); - let stagingPath = await IOUtils.createUniqueDirectory( - PathUtils.tempDir, - "PreferencesBackupResource-staging-test" - ); - - let fakeConnection = { - backup: sandbox.stub().resolves(true), - close: sandbox.stub().resolves(true), - }; - sandbox.stub(Sqlite, "openConnection").returns(fakeConnection); - sandbox.stub(PrivateBrowsingUtils, "permanentPrivateBrowsing").value(true); - - let manifestEntry = await preferencesBackupResource.backup( - stagingPath, - sourcePath - ); - Assert.deepEqual( - manifestEntry, - { profilePath: sourcePath }, - "PreferencesBackupResource.backup should return the original profile path " + - "in its ManifestEntry" - ); - - Assert.ok( - fakeConnection.backup.notCalled, - "No sqlite connections should have been made with permanent private browsing enabled" - ); - - await maybeRemovePath(stagingPath); - await maybeRemovePath(sourcePath); - - sandbox.restore(); -}); - -/** * Check that prefs.js has "browser.backup.profile-restoration-date". Due to * concerns over potential time skips in automation, we only check that the * timestamp is not more than a week before/after now (we would expect the @@ -322,8 +179,6 @@ add_task(async function test_recover() { const simpleCopyFiles = [ { path: "prefs.js" }, { path: "xulstore.json" }, - { path: "permissions.sqlite" }, - { path: "content-prefs.sqlite" }, { path: "containers.json" }, { path: "handlers.json" }, { path: "user.js" }, diff --git a/browser/components/backup/tests/xpcshell/test_SiteSettingsBackupResource.js b/browser/components/backup/tests/xpcshell/test_SiteSettingsBackupResource.js @@ -0,0 +1,248 @@ +/* Any copyright is dedicated to the Public Domain. +https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { SiteSettingsBackupResource } = ChromeUtils.importESModule( + "resource:///modules/backup/SiteSettingsBackupResource.sys.mjs" +); + +/** + * Tests that we can measure the Site Settings databases in a profile directory. + */ +add_task(async function test_measure() { + const EXPECTED_PERMISSIONS_DB_SIZE = 500; + const EXPECTED_CONTENT_PREFS_DB_SIZE = 500; + + Services.fog.testResetFOG(); + + let tempDir = PathUtils.tempDir; + let tempPermissionsDBPath = PathUtils.join(tempDir, "permissions.sqlite"); + let tempContentPrefsDBPath = PathUtils.join(tempDir, "content-prefs.sqlite"); + + await createKilobyteSizedFile( + tempPermissionsDBPath, + EXPECTED_PERMISSIONS_DB_SIZE + ); + await createKilobyteSizedFile( + tempContentPrefsDBPath, + EXPECTED_CONTENT_PREFS_DB_SIZE + ); + + let siteSettingsBackupResource = new SiteSettingsBackupResource(); + await siteSettingsBackupResource.measure(tempDir); + + await IOUtils.remove(tempPermissionsDBPath); + await IOUtils.remove(tempContentPrefsDBPath); +}); + +/** + * Test that the backup method correctly copies items from the profile directory + * into the staging directory. + */ +add_task(async function test_backup() { + let sandbox = sinon.createSandbox(); + + let siteSettingsBackupResource = new SiteSettingsBackupResource(); + let sourcePath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "SiteSettingsBackupResource-source-test" + ); + let stagingPath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "SiteSettingsBackupResource-staging-test" + ); + + await createTestFiles(sourcePath, [ + { path: "permissions.sqlite" }, + { path: "content-prefs.sqlite" }, + ]); + + let fakeConnection = { + backup: sandbox.stub().resolves(true), + close: sandbox.stub().resolves(true), + }; + sandbox.stub(Sqlite, "openConnection").returns(fakeConnection); + + let manifestEntry = await siteSettingsBackupResource.backup( + stagingPath, + sourcePath + ); + Assert.equal( + manifestEntry, + null, + "SiteSettingsBackupResource.backup should return null as its ManifestEntry" + ); + + Assert.ok( + fakeConnection.backup.calledTwice, + "Called backup the expected number of times for all connections" + ); + Assert.ok( + fakeConnection.backup.calledWith( + PathUtils.join(stagingPath, "permissions.sqlite") + ), + "Called backup on the permissions.sqlite Sqlite connection" + ); + Assert.ok( + fakeConnection.backup.calledWith( + PathUtils.join(stagingPath, "content-prefs.sqlite") + ), + "Called backup on the content-prefs.sqlite Sqlite connection" + ); + + await maybeRemovePath(stagingPath); + await maybeRemovePath(sourcePath); + + sandbox.restore(); +}); + +/** + * Test that the recover method correctly copies items from the recovery + * directory into the destination profile directory. + */ +add_task(async function test_recover() { + let siteSettingsBackupResource = new SiteSettingsBackupResource(); + let recoveryPath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "SiteSettingsBackupResource-recovery-test" + ); + let destProfilePath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "SiteSettingsBackupResource-test-profile" + ); + + const simpleCopyFiles = [ + { path: "permissions.sqlite" }, + { path: "content-prefs.sqlite" }, + ]; + await createTestFiles(recoveryPath, simpleCopyFiles); + + let postRecoveryEntry = await siteSettingsBackupResource.recover( + null, + recoveryPath, + destProfilePath + ); + Assert.equal( + postRecoveryEntry, + null, + "SiteSettingsBackupResource.recover should return null as its post recovery entry" + ); + + await assertFilesExist(destProfilePath, simpleCopyFiles); + + await maybeRemovePath(recoveryPath); + await maybeRemovePath(destProfilePath); +}); + +/** + * Tests that the backup method does not copy the permissions or content prefs + * databases if the browser is configured to not save history - either while + * running, or to clear it at shutdown. + */ +add_task(async function test_backup_no_saved_history() { + let siteSettingsBackupResource = new SiteSettingsBackupResource(); + let sourcePath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "SiteSettingsBackupResource-source-test" + ); + let stagingPath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "SiteSettingsBackupResource-staging-test" + ); + + let sandbox = sinon.createSandbox(); + let fakeConnection = { + backup: sandbox.stub().resolves(true), + close: sandbox.stub().resolves(true), + }; + sandbox.stub(Sqlite, "openConnection").returns(fakeConnection); + + Services.prefs.setBoolPref(SANITIZE_ON_SHUTDOWN_PREF, true); + Services.prefs.setBoolPref(SITE_SETTINGS_CLEARED_ON_SHUTDOWN_PREF, true); + + Assert.ok( + !SiteSettingsBackupResource.canBackupResource, + "Cannot backup site settings since they are being cleared on shutdown" + ); + + let manifestEntry = await siteSettingsBackupResource.backup( + stagingPath, + sourcePath + ); + Assert.equal( + manifestEntry, + null, + "SiteSettingsBackupResource.backup should return null as its ManifestEntry" + ); + + Assert.ok( + fakeConnection.backup.notCalled, + "No sqlite connections should have been made with sanitize shutdown enabled" + ); + + Services.prefs.clearUserPref(SANITIZE_ON_SHUTDOWN_PREF); + Services.prefs.clearUserPref(SITE_SETTINGS_CLEARED_ON_SHUTDOWN_PREF); + + Assert.ok( + SiteSettingsBackupResource.canBackupResource, + "We should be allowed to backup this resource now" + ); + + fakeConnection.backup.resetHistory(); + manifestEntry = await siteSettingsBackupResource.backup( + stagingPath, + sourcePath + ); + Assert.equal( + manifestEntry, + null, + "Should have gotten back a null ManifestEntry" + ); + + Assert.ok( + fakeConnection.backup.notCalled, + "No files to backup, so no sqlite connections should have been made" + ); + + await maybeRemovePath(stagingPath); + await maybeRemovePath(sourcePath); + + sandbox.restore(); +}); + +/** + * Tests the canBackupResource method with various pref configurations. + */ +add_task(async function test_canBackupResource() { + Assert.ok( + SiteSettingsBackupResource.canBackupResource, + "Should be able to backup by default" + ); + + Services.prefs.setBoolPref(SANITIZE_ON_SHUTDOWN_PREF, true); + Services.prefs.setBoolPref(SITE_SETTINGS_CLEARED_ON_SHUTDOWN_PREF, true); + Assert.ok( + !SiteSettingsBackupResource.canBackupResource, + "Cannot backup when sanitizeOnShutdown and site settings cleared on shutdown (v2) are enabled" + ); + Services.prefs.clearUserPref(SANITIZE_ON_SHUTDOWN_PREF); + Services.prefs.clearUserPref(SITE_SETTINGS_CLEARED_ON_SHUTDOWN_PREF); + + Assert.ok( + SiteSettingsBackupResource.canBackupResource, + "Should be able to backup after clearing prefs" + ); + + Services.prefs.setBoolPref(USE_OLD_CLEAR_HISTORY_DIALOG_PREF, true); + Services.prefs.setBoolPref(SANITIZE_ON_SHUTDOWN_PREF, true); + Services.prefs.setBoolPref(SITE_SETTINGS_CLEARED_ON_SHUTDOWN_OLD_PREF, true); + Assert.ok( + !SiteSettingsBackupResource.canBackupResource, + "Cannot backup when sanitizeOnShutdown and site settings cleared on shutdown (old) are enabled" + ); + + Services.prefs.clearUserPref(USE_OLD_CLEAR_HISTORY_DIALOG_PREF); + Services.prefs.clearUserPref(SANITIZE_ON_SHUTDOWN_PREF); + Services.prefs.clearUserPref(SITE_SETTINGS_CLEARED_ON_SHUTDOWN_OLD_PREF); +}); diff --git a/browser/components/backup/tests/xpcshell/xpcshell.toml b/browser/components/backup/tests/xpcshell/xpcshell.toml @@ -80,6 +80,8 @@ run-sequentially = ["true"] # Mock Windows registry interferes with normal opera ["test_BackupService_wrongPassword.js"] +["test_BookmarksBackupResource.js"] + ["test_CookiesBackupResource.js"] ["test_CredentialsAndSecurityBackupResource.js"] @@ -104,4 +106,6 @@ run-sequentially = ["true"] # Mock Windows registry interferes with normal opera ["test_SessionStoreBackupResource_mockSessionStore.js"] +["test_SiteSettingsBackupResource.js"] + ["test_backupService_findBackupsInWellKnownLocations.js"]