Bug 1461069: Remove obsolete state preference migration code. r?aswan
MozReview-Commit-ID: 6B8JLjJqFlg
--- a/toolkit/mozapps/extensions/internal/XPIDatabase.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIDatabase.jsm
@@ -42,29 +42,27 @@ const {nsIBlocklistService} = Ci;
// These are injected from XPIProvider.jsm
/* globals
* BOOTSTRAP_REASONS,
* DB_SCHEMA,
* SIGNED_TYPES,
* XPIProvider,
* XPIStates,
- * descriptorToPath,
* isTheme,
* isWebExtension,
* recordAddonTelemetry,
*/
for (let sym of [
"BOOTSTRAP_REASONS",
"DB_SCHEMA",
"SIGNED_TYPES",
"XPIProvider",
"XPIStates",
- "descriptorToPath",
"isTheme",
"isWebExtension",
"recordAddonTelemetry",
]) {
XPCOMUtils.defineLazyGetter(this, sym, () => XPIInternal[sym]);
}
ChromeUtils.import("resource://gre/modules/Log.jsm");
@@ -259,20 +257,16 @@ class AddonInternal {
* An array of bootstrapped add-on IDs on which this add-on depends.
* The add-on will remain appDisabled if any of the dependent
* add-ons is not installed and enabled.
*/
this.dependencies = EMPTY_ARRAY;
this.hasEmbeddedWebExtension = false;
if (addonData) {
- if (addonData.descriptor && !addonData.path) {
- addonData.path = descriptorToPath(addonData.descriptor);
- }
-
copyProperties(addonData, PROP_JSON_FIELDS, this);
if (!this.dependencies)
this.dependencies = [];
Object.freeze(this.dependencies);
this.addedToDatabase();
@@ -1423,19 +1417,16 @@ this.XPIDatabase = {
let forEach = this.syncLoadingDB ? arrayForEach : idleForEach;
// If we got here, we probably have good data
// Make AddonInternal instances from the loaded data and save them
let addonDB = new Map();
await forEach(inputAddons.addons, loadedAddon => {
try {
- if (!loadedAddon.path) {
- loadedAddon.path = descriptorToPath(loadedAddon.descriptor);
- }
loadedAddon._sourceBundle = new nsIFile(loadedAddon.path);
} catch (e) {
// We can fail here when the path is invalid, usually from the
// wrong OS
logger.warn("Could not find source bundle for add-on " + loadedAddon.id, e);
}
let newAddon = new AddonInternal(loadedAddon);
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -51,18 +51,16 @@ XPCOMUtils.defineLazyServiceGetters(this
});
const nsIFile = Components.Constructor("@mozilla.org/file/local;1", "nsIFile",
"initWithPath");
const FileInputStream = Components.Constructor("@mozilla.org/network/file-input-stream;1",
"nsIFileInputStream", "init");
const PREF_DB_SCHEMA = "extensions.databaseSchema";
-const PREF_XPI_STATE = "extensions.xpiState";
-const PREF_BOOTSTRAP_ADDONS = "extensions.bootstrappedAddons";
const PREF_PENDING_OPERATIONS = "extensions.pendingOperations";
const PREF_EM_ENABLED_SCOPES = "extensions.enabledScopes";
const PREF_EM_STARTUP_SCAN_SCOPES = "extensions.startupScanScopes";
// xpinstall.signatures.required only supported in dev builds
const PREF_XPI_SIGNATURES_REQUIRED = "xpinstall.signatures.required";
const PREF_LANGPACK_SIGNATURES = "extensions.langpacks.signatures.required";
const PREF_XPI_PERMISSIONS_BRANCH = "xpinstall.";
const PREF_INSTALL_DISTRO_ADDONS = "extensions.installDistroAddons";
@@ -70,35 +68,27 @@ const PREF_BRANCH_INSTALLED_ADDON =
const PREF_SYSTEM_ADDON_SET = "extensions.systemAddonSet";
const PREF_ALLOW_LEGACY = "extensions.legacy.enabled";
const PREF_EM_LAST_APP_BUILD_ID = "extensions.lastAppBuildId";
// Specify a list of valid built-in add-ons to load.
const BUILT_IN_ADDONS_URI = "chrome://browser/content/built_in_addons.json";
-const OBSOLETE_PREFERENCES = [
- "extensions.bootstrappedAddons",
- "extensions.enabledAddons",
- "extensions.xpiState",
- "extensions.installCache",
-];
-
const URI_EXTENSION_STRINGS = "chrome://mozapps/locale/extensions/extensions.properties";
const DIR_EXTENSIONS = "extensions";
const DIR_SYSTEM_ADDONS = "features";
const DIR_STAGE = "staged";
const DIR_TRASH = "trash";
const FILE_XPI_STATES = "addonStartup.json.lz4";
const FILE_DATABASE = "extensions.json";
const FILE_RDF_MANIFEST = "install.rdf";
const FILE_WEB_MANIFEST = "manifest.json";
-const FILE_XPI_ADDONS_LIST = "extensions.ini";
const KEY_PROFILEDIR = "ProfD";
const KEY_ADDON_APP_DIR = "XREAddonAppDir";
const KEY_APP_DISTRIBUTION = "XREAppDist";
const KEY_APP_FEATURES = "XREAppFeat";
const KEY_APP_PROFILE = "app-profile";
const KEY_APP_SYSTEM_ADDONS = "app-system-addons";
@@ -280,58 +270,16 @@ function tryGetMtime(file) {
// than whatever value it may have cached.
return file.clone().lastModifiedTime;
} catch (e) {
return 0;
}
}
/**
- * Returns the path to `file` relative to the directory `dir`, or an
- * absolute path to the file if no directory is passed, or the file is
- * not a descendant of it.
- *
- * @param {nsIFile} file
- * The file to return a relative path to.
- * @param {nsIFile} [dir]
- * If passed, return a path relative to this directory.
- * @returns {string}
- */
-function getRelativePath(file, dir) {
- if (dir && dir.contains(file)) {
- let path = file.getRelativePath(dir);
- if (AppConstants.platform == "win") {
- path = path.replace(/\//g, "\\");
- }
- return path;
- }
- return file.path;
-}
-
-/**
- * Converts the given opaque descriptor string into an ordinary path string.
- *
- * @param {string} descriptor
- * The opaque descriptor string to convert.
- * @param {nsIFile} [dir]
- * If passed, return a path relative to this directory.
- * @returns {string}
- * The file's path.
- */
-function descriptorToPath(descriptor, dir) {
- try {
- let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
- file.persistentDescriptor = descriptor;
- return getRelativePath(file, dir);
- } catch (e) {
- return null;
- }
-}
-
-/**
* Helper function that determines whether an addon of a certain type is a
* WebExtension.
*
* @param {string} type
* The add-on type to check.
* @returns {boolean}
*/
function isWebExtension(type) {
@@ -518,24 +466,16 @@ const JSON_FIELDS = Object.freeze([
"path",
"runInSafeMode",
"startupData",
"telemetryKey",
"type",
"version",
]);
-const BOOTSTRAPPED_FIELDS = Object.freeze([
- "dependencies",
- "hasEmbeddedWebExtension",
- "runInSafeMode",
- "type",
- "version",
-]);
-
class XPIState {
constructor(location, id, saved = {}) {
this.location = location;
this.id = id;
// Set default values.
this.type = "extension";
@@ -550,53 +490,16 @@ class XPIState {
}
if (saved.currentModifiedTime && saved.currentModifiedTime != this.lastModifiedTime) {
this.lastModifiedTime = saved.currentModifiedTime;
this.changed = true;
}
}
- /**
- * Migrates an add-on's data from xpiState and bootstrappedAddons
- * preferences, and returns an XPIState object for it.
- *
- * @param {XPIStateLocation} location
- * The location of the add-on.
- * @param {string} id
- * The ID of the add-on to migrate.
- * @param {object} saved
- * The add-on's data from the xpiState preference.
- * @param {object} [bootstrapped]
- * The add-on's data from the bootstrappedAddons preference, if
- * applicable.
- * @returns {XPIState}
- */
- static migrate(location, id, saved, bootstrapped) {
- let data = {
- enabled: saved.e,
- path: descriptorToPath(saved.d, location.dir),
- lastModifiedTime: saved.mt || saved.st,
- version: saved.v,
- };
-
- if (bootstrapped) {
- data.enabled = true;
- data.path = descriptorToPath(bootstrapped.descriptor, location.dir);
-
- for (let field of BOOTSTRAPPED_FIELDS) {
- if (field in bootstrapped) {
- data[field] = bootstrapped[field];
- }
- }
- }
-
- return new XPIState(location, id, data);
- }
-
// Compatibility shim getters for legacy callers in XPIDatabase.jsm.
get mtime() {
return this.lastModifiedTime;
}
get active() {
return this.enabled;
}
@@ -917,33 +820,16 @@ class XPIStateLocation extends Map {
* getStagedAddons() {
for (let [id, metadata] of Object.entries(this.staged)) {
yield [id, metadata];
}
}
/**
- * Migrates saved state data for the given add-on from the values
- * stored in xpiState and bootstrappedAddons preferences, and adds it to
- * the DB.
- *
- * @param {string} id
- * The ID of the add-on to migrate.
- * @param {object} state
- * The add-on's data from the xpiState preference.
- * @param {object} [bootstrapped]
- * The add-on's data from the bootstrappedAddons preference, if
- * applicable.
- */
- migrateAddon(id, state, bootstrapped) {
- this.set(id, XPIState.migrate(this, id, state, bootstrapped));
- }
-
- /**
* Returns true if the given addon was installed in this location by a text
* file pointing to its real path.
*
* @param {string} aId
* The ID of the addon
* @returns {boolean}
*/
isLinkedAddon(aId) {
@@ -1401,87 +1287,29 @@ var XPIStates = {
let count = 0;
for (let location of this.locations()) {
count += location.size;
}
return count;
},
/**
- * Migrates state data from the xpiState and bootstrappedAddons
- * preferences and adds it to the DB. Returns a JSON-compatible
- * representation of the current state of the DB.
- *
- * @returns {object}
- */
- migrateStateFromPrefs() {
- logger.info("No addonStartup.json found. Attempting to migrate data from preferences");
-
- let state;
- // Try to migrate state data from old storage locations.
- let bootstrappedAddons;
- try {
- state = JSON.parse(Services.prefs.getStringPref(PREF_XPI_STATE));
- bootstrappedAddons = JSON.parse(Services.prefs.getStringPref(PREF_BOOTSTRAP_ADDONS, "{}"));
- } catch (e) {
- logger.warn("Error parsing extensions.xpiState and " +
- "extensions.bootstrappedAddons: ${error}",
- {error: e});
-
- }
-
- for (let [locName, addons] of Object.entries(state)) {
- for (let [id, addon] of Object.entries(addons)) {
- let loc = this.getLocation(locName);
- if (loc) {
- loc.migrateAddon(id, addon, bootstrappedAddons[id] || null);
- }
- }
- }
-
- // Clear out old state data.
- for (let pref of OBSOLETE_PREFERENCES) {
- Services.prefs.clearUserPref(pref);
- }
- OS.File.remove(OS.Path.join(OS.Constants.Path.profileDir,
- FILE_XPI_ADDONS_LIST));
-
- // Serialize and deserialize so we get the expected JSON data.
- let data = JSON.parse(JSON.stringify(this));
-
- logger.debug("Migrated data: ${}", data);
-
- return data;
- },
-
- /**
- * Load extension state data from addonStartup.json, or migrates it
- * from legacy state preferences, if they exist.
+ * Load extension state data from addonStartup.json.
*
* @returns {Object}
*/
loadExtensionState() {
let state;
try {
state = aomStartup.readStartupData();
} catch (e) {
logger.warn("Error parsing extensions state: ${error}",
{error: e});
}
- if (!state && Services.prefs.getPrefType(PREF_XPI_STATE) != Ci.nsIPrefBranch.PREF_INVALID) {
- try {
- state = this.migrateStateFromPrefs();
- } catch (e) {
- logger.warn("Error migrating extensions.xpiState and " +
- "extensions.bootstrappedAddons: ${error}",
- {error: e});
- }
- }
-
logger.debug("Loaded add-on state: ${}", state);
return state || {};
},
/**
* Walk through all install locations, highest priority first,
* comparing the on-disk state of extensions to what is stored in prefs.
*
@@ -3180,17 +3008,16 @@ var XPIInternal = {
TEMPORARY_ADDON_SUFFIX,
TOOLKIT_ID,
TemporaryInstallLocation,
XPIProvider,
XPIStates,
XPI_PERMISSION,
awaitPromise,
canRunInSafeMode,
- descriptorToPath,
getExternalType,
getURIForResourceInFile,
isTheme,
isWebExtension,
};
var addonTypes = [
new AddonManagerPrivate.AddonType("extension", URI_EXTENSION_STRINGS,
deleted file mode 100644
--- a/toolkit/mozapps/extensions/test/xpcshell/test_migrate_state_prefs.js
+++ /dev/null
@@ -1,92 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-"use strict";
-
-/* globals Preferences */
-ChromeUtils.import("resource://gre/modules/Preferences.jsm");
-
-function getXS() {
- let XPI = ChromeUtils.import("resource://gre/modules/addons/XPIProvider.jsm", {});
- return XPI.XPIStates;
-}
-
-function installExtension(id, data) {
- return AddonTestUtils.promiseWriteFilesToExtension(
- AddonTestUtils.profileExtensions.path, id, data);
-}
-
-add_task(async function test_migrate_prefs() {
- createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "54");
-
- ok(!AddonTestUtils.addonStartup.exists(),
- "addonStartup.json.lz4 should not exist");
-
- const ID1 = "bootstrapped-enabled@xpcshell.mozilla.org";
- const ID2 = "bootstrapped-disabled@xpcshell.mozilla.org";
-
- let targetApplications = [{ id: "toolkit@mozilla.org", "minVersion": "0", "maxVersion": "*" }];
-
- let file1 = await installExtension(ID1, { "install.rdf": { id: ID1, name: ID1, bootstrap: true, version: "0.1", targetApplications } });
- let file2 = await installExtension(ID2, { "install.rdf": { id: ID2, name: ID2, bootstrap: true, version: "0.2", targetApplications } });
-
- function mt(file) {
- let f = file.clone();
- if (TEST_UNPACKED) {
- f.append("install.rdf");
- }
- return f.lastModifiedTime;
- }
-
- // Startup and shut down the add-on manager so the add-ons are added
- // to the DB.
- await promiseStartupManager();
- await promiseShutdownManager();
-
- // Remove the startup state file and add legacy prefs to replace it.
- AddonTestUtils.addonStartup.remove(false);
-
- Preferences.set("extensions.xpiState", JSON.stringify({
- "app-profile": {
- [ID1]: {e: true, d: file1.persistentDescriptor, v: "0.1", mt: mt(file1)},
- [ID2]: {e: false, d: file2.persistentDescriptor, v: "0.2", mt: mt(file2)},
- }
- }));
-
- Preferences.set("extensions.bootstrappedAddons", JSON.stringify({
- [ID1]: {
- version: "0.1",
- type: "extension",
- descriptor: file1.persistentDescriptor,
- hasEmbeddedWebExtension: true,
- }
- }));
-
- await promiseStartupManager();
-
- // Check the the state data is updated correctly.
- let states = getXS();
-
- let addon1 = states.findAddon(ID1);
- ok(addon1.enabled, "Addon 1 should be enabled");
- equal(addon1.version, "0.1", "Addon 1 has the correct version");
- equal(addon1.mtime, mt(file1), "Addon 1 has the correct timestamp");
- ok(addon1.hasEmbeddedWebExtension, "Addon 1 has an embedded WebExtension");
-
- let addon2 = states.findAddon(ID2);
- ok(!addon2.enabled, "Addon 2 should not be enabled");
- equal(addon2.version, "0.2", "Addon 2 has the correct version");
- equal(addon2.mtime, mt(file2), "Addon 2 has the correct timestamp");
- ok(!addon2.hasEmbeddedWebExtension, "Addon 2 no embedded WebExtension");
-
- // Check that legacy prefs and files have been removed.
- ok(!Preferences.has("extensions.xpiState"), "No xpiState pref left behind");
- ok(!Preferences.has("extensions.bootstrappedAddons"), "No bootstrappedAddons pref left behind");
- ok(!Preferences.has("extensions.enabledAddons"), "No enabledAddons pref left behind");
-
- let file = AddonTestUtils.profileDir.clone();
- file.append("extensions.ini");
- ok(!file.exists(), "No extensions.ini file left behind");
-
- await promiseShutdownManager();
-});
--- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini
+++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini
@@ -149,17 +149,16 @@ skip-if = os == "android"
[test_json_updatecheck.js]
[test_legacy.js]
skip-if = !allow_legacy_extensions || appname == "thunderbird"
[test_locale.js]
[test_manifest.js]
[test_manifest_locales.js]
# Bug 676992: test consistently hangs on Android
skip-if = os == "android"
-[test_migrate_state_prefs.js]
[test_moved_extension_metadata.js]
[test_no_addons.js]
[test_nodisable_hidden.js]
[test_onPropertyChanged_appDisabled.js]
[test_overrideblocklist.js]
run-sequentially = Uses global XCurProcD dir.
tags = blocklist
[test_pass_symbol.js]