diff options
Diffstat (limited to '')
-rw-r--r-- | toolkit/components/extensions/test/xpcshell/test_extension_permissions_migrate_kvstore_path.js | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/toolkit/components/extensions/test/xpcshell/test_extension_permissions_migrate_kvstore_path.js b/toolkit/components/extensions/test/xpcshell/test_extension_permissions_migrate_kvstore_path.js new file mode 100644 index 0000000000..5f1c73dd3b --- /dev/null +++ b/toolkit/components/extensions/test/xpcshell/test_extension_permissions_migrate_kvstore_path.js @@ -0,0 +1,234 @@ +"use strict"; + +const { + ExtensionPermissions, + OLD_RKV_DIRNAME, + RKV_DIRNAME, + VERSION_KEY, + VERSION_VALUE, +} = ChromeUtils.importESModule( + "resource://gre/modules/ExtensionPermissions.sys.mjs" +); +const { FileTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/FileTestUtils.sys.mjs" +); +const { FileUtils } = ChromeUtils.importESModule( + "resource://gre/modules/FileUtils.sys.mjs" +); +const { KeyValueService } = ChromeUtils.importESModule( + "resource://gre/modules/kvstore.sys.mjs" +); + +add_setup(async () => { + // Bug 1646182: Force ExtensionPermissions to run in rkv mode, because this + // test does not make sense with the legacy method (which will be removed in + // the above bug). + ExtensionPermissions._useLegacyStorageBackend = false; + await ExtensionPermissions._uninit(); +}); + +// NOTE: this test lives in its own test file to make sure it is isolated +// from other tests that would be creating the kvstore instance and +// would prevent this test to properly simulate the kvstore path migration. +add_task(async function test_migrate_to_separate_kvstore_store_path() { + const ADDON_ID_01 = "test-addon-01@test-extension"; + const ADDON_ID_02 = "test-addon-02@test-extension"; + // This third test extension is only used as the one that should + // have some content scripts stored in ExtensionScriptingStore. + const ADDON_ID_03 = "test-addon-03@test-extension"; + + const oldStorePath = FileUtils.getDir("ProfD", [OLD_RKV_DIRNAME]).path; + const newStorePath = FileUtils.getDir("ProfD", [RKV_DIRNAME]).path; + + // Verify that we are going to be using the expected backend, and that + // the rkv path migration is only enabled by default in Nightly builds. + info("Verify test environment match the expected pre-conditions"); + + const permsStore = ExtensionPermissions._getStore(); + equal( + permsStore.constructor.name, + "PermissionStore", + "active ExtensionPermissions store should be an instance of PermissionStore" + ); + + equal( + permsStore._shouldMigrateFromOldKVStorePath, + AppConstants.NIGHTLY_BUILD, + "ExtensionPermissions rkv migration expected to be enabled by default only in Nightly" + ); + + info( + "Uninitialize ExtensionPermissions and make sure no existing kvstore dir" + ); + await ExtensionPermissions._uninit({ recreateStore: false }); + equal( + ExtensionPermissions._getStore(), + null, + "PermissionStore has been nullified" + ); + await IOUtils.remove(oldStorePath, { ignoreAbsent: true, recursive: true }); + await IOUtils.remove(newStorePath, { ignoreAbsent: true, recursive: true }); + + info("Create an existing kvstore dir on the old path"); + + // Populated the kvstore with some expected permissions. + const expectedPermsAddon01 = { + permissions: ["tabs"], + origins: ["http://*/*"], + }; + const expectedPermsAddon02 = { + permissions: ["proxy"], + origins: ["https://*/*"], + }; + + const expectedScriptAddon01 = { + id: "script-addon-01", + allFrames: false, + matches: ["<all_urls>"], + js: ["/test-script-addon-01.js"], + persistAcrossSessions: true, + runAt: "document_end", + }; + + const expectedScriptAddon02 = { + id: "script-addon-02", + allFrames: false, + matches: ["<all_urls"], + css: ["/test-script-addon-02.css"], + persistAcrossSessions: true, + runAt: "document_start", + }; + + { + // Make sure the folder exists + await IOUtils.makeDirectory(oldStorePath, { ignoreExisting: true }); + // Create a permission kvstore dir on the old file path. + const kvstore = await KeyValueService.getOrCreate( + oldStorePath, + "permissions" + ); + await kvstore.writeMany([ + ["_version", 1], + [`id-${ADDON_ID_01}`, JSON.stringify(expectedPermsAddon01)], + [`id-${ADDON_ID_02}`, JSON.stringify(expectedPermsAddon02)], + ]); + } + + { + // Add also scripting kvstore data into the same temp dir path. + const kvstore = await KeyValueService.getOrCreate( + oldStorePath, + "scripting-contentScripts" + ); + await kvstore.writeMany([ + [ + `${ADDON_ID_03}/${expectedScriptAddon01.id}`, + JSON.stringify(expectedScriptAddon01), + ], + [ + `${ADDON_ID_03}/${expectedScriptAddon02.id}`, + JSON.stringify(expectedScriptAddon02), + ], + ]); + } + + ok( + await IOUtils.exists(oldStorePath), + "Found kvstore dir for the old store path" + ); + ok( + !(await IOUtils.exists(newStorePath)), + "Expect kvstore dir for the new store path to don't exist yet" + ); + + info("Re-initialize the ExtensionPermission store and assert migrated data"); + await ExtensionPermissions._uninit({ recreateStore: true }); + + // Explicitly enable migration (needed to make sure we hit the migration code + // that is only enabled by default on Nightly). + if (!AppConstants.NIGHTLY_BUILD) { + info("Enable ExtensionPermissions rkv migration on non-nightly channel"); + const newStoreInstance = ExtensionPermissions._getStore(); + newStoreInstance._shouldMigrateFromOldKVStorePath = true; + } + + const permsAddon01 = await ExtensionPermissions._get(ADDON_ID_01); + const permsAddon02 = await ExtensionPermissions._get(ADDON_ID_02); + + Assert.deepEqual( + { permsAddon01, permsAddon02 }, + { + permsAddon01: expectedPermsAddon01, + permsAddon02: expectedPermsAddon02, + }, + "Got the expected permissions migrated to the new store file path" + ); + + await ExtensionPermissions._uninit({ recreateStore: false }); + + ok( + await IOUtils.exists(newStorePath), + "Found kvstore dir for the new store path" + ); + + { + const newKVStore = await KeyValueService.getOrCreate( + newStorePath, + "permissions" + ); + Assert.equal( + await newKVStore.get(VERSION_KEY), + VERSION_VALUE, + "Got the expected value set on the kvstore _version key" + ); + } + + // kvstore internally caching behavior doesn't make it easy to make sure + // we would be hitting a failure if the ExtensionPermissions kvstore migration + // would be mistakenly removing the old kvstore dir as part of that migration, + // and so the test case is explicitly verifying that the directory does still + // exist and then it copies it into a new path to confirm that the expected + // data have been kept in the old kvstore dir. + ok( + await IOUtils.exists(oldStorePath), + "Found kvstore dir for the old store path" + ); + const oldStoreCopiedPath = FileTestUtils.getTempFile("kvstore-dir").path; + await IOUtils.copy(oldStorePath, oldStoreCopiedPath, { recursive: true }); + + // Confirm that the content scripts have not been copied into + // the new kvstore path. + async function assertStoredContentScripts(storePath, expectedKeys) { + const kvstore = await KeyValueService.getOrCreate( + storePath, + "scripting-contentScripts" + ); + const enumerator = await kvstore.enumerate(); + const keys = []; + while (enumerator.hasMoreElements()) { + keys.push(enumerator.getNext().key); + } + Assert.deepEqual( + keys, + expectedKeys, + `Got the expected scripts in the kvstore path ${storePath}` + ); + } + + info( + "Verify that no content scripts are stored in the new kvstore dir reserved for permissions" + ); + await assertStoredContentScripts(newStorePath, []); + info( + "Verify that existing content scripts have been not been removed old kvstore dir" + ); + await assertStoredContentScripts(oldStoreCopiedPath, [ + `${ADDON_ID_03}/${expectedScriptAddon01.id}`, + `${ADDON_ID_03}/${expectedScriptAddon02.id}`, + ]); + + await ExtensionPermissions._uninit({ recreateStore: true }); + + await IOUtils.remove(newStorePath, { recursive: true }); + await IOUtils.remove(oldStorePath, { recursive: true }); +}); |