зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1192928: Purge outdated system add-ons. r=rhelmer
--HG-- extra : commitid : LQ0UhTVa1Zz extra : rebase_source : 897c85df3902fe16e2ae45960c9d65b1cfb86df0
This commit is contained in:
Родитель
0b07bf438d
Коммит
763411093a
|
@ -2808,7 +2808,11 @@ this.XPIProvider = {
|
|||
!XPIDatabase.writeAddonsList());
|
||||
},
|
||||
|
||||
updateSystemAddons: Task.async(function XPI_updateSystemAddons() {
|
||||
updateSystemAddons: Task.async(function* XPI_updateSystemAddons() {
|
||||
let systemAddonLocation = XPIProvider.installLocationsByName[KEY_APP_SYSTEM_ADDONS];
|
||||
if (!systemAddonLocation)
|
||||
return;
|
||||
|
||||
// Don't do anything in safe mode
|
||||
if (Services.appinfo.inSafeMode)
|
||||
return;
|
||||
|
@ -2816,7 +2820,7 @@ this.XPIProvider = {
|
|||
// Download the list of system add-ons
|
||||
let url = Preferences.get(PREF_SYSTEM_ADDON_UPDATE_URL, null);
|
||||
if (!url)
|
||||
return;
|
||||
return systemAddonLocation.cleanDirectories();
|
||||
|
||||
url = UpdateUtils.formatUpdateURL(url);
|
||||
|
||||
|
@ -2826,7 +2830,7 @@ this.XPIProvider = {
|
|||
// If there was no list then do nothing.
|
||||
if (!addonList) {
|
||||
logger.info("No system add-ons list was returned.");
|
||||
return;
|
||||
return systemAddonLocation.cleanDirectories();
|
||||
}
|
||||
|
||||
addonList = new Map([for (spec of addonList) [spec.id, { spec, path: null, addon: null }]]);
|
||||
|
@ -2853,13 +2857,11 @@ this.XPIProvider = {
|
|||
return true;
|
||||
};
|
||||
|
||||
let systemAddonLocation = XPIProvider.installLocationsByName[KEY_APP_SYSTEM_ADDONS];
|
||||
|
||||
// If this matches the current set in the profile location then do nothing.
|
||||
let updatedAddons = addonMap(yield getAddonsInLocation(KEY_APP_SYSTEM_ADDONS));
|
||||
if (setMatches(addonList, updatedAddons)) {
|
||||
logger.info("Retaining existing updated system add-ons.");
|
||||
return;
|
||||
return systemAddonLocation.cleanDirectories();
|
||||
}
|
||||
|
||||
// If this matches the current set in the default location then reset the
|
||||
|
@ -2868,7 +2870,7 @@ this.XPIProvider = {
|
|||
if (setMatches(addonList, defaultAddons)) {
|
||||
logger.info("Resetting system add-ons.");
|
||||
systemAddonLocation.resetAddonSet();
|
||||
return;
|
||||
return systemAddonLocation.cleanDirectories();
|
||||
}
|
||||
|
||||
// Download all the add-ons
|
||||
|
@ -2951,6 +2953,8 @@ this.XPIProvider = {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
yield systemAddonLocation.cleanDirectories();
|
||||
}
|
||||
}),
|
||||
|
||||
|
@ -7506,6 +7510,7 @@ Object.assign(MutableDirectoryInstallLocation.prototype, {
|
|||
*/
|
||||
function SystemAddonInstallLocation(aName, aDirectory, aScope, aResetSet) {
|
||||
this._baseDir = aDirectory;
|
||||
this._nextDir = null;
|
||||
|
||||
if (aResetSet)
|
||||
this.resetAddonSet();
|
||||
|
@ -7626,6 +7631,58 @@ Object.assign(SystemAddonInstallLocation.prototype, {
|
|||
this._saveAddonSet({ schema: 1, addons: {} });
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes any directories not currently in use or pending use after a
|
||||
* restart. Any errors that happen here don't really matter as we'll attempt
|
||||
* to cleanup again next time.
|
||||
*/
|
||||
cleanDirectories: Task.async(function*() {
|
||||
let iterator;
|
||||
try {
|
||||
iterator = new OS.File.DirectoryIterator(this._baseDir.path);
|
||||
}
|
||||
catch (e) {
|
||||
logger.error("Failed to clean updated system add-ons directories.", e);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
let entries = [];
|
||||
|
||||
yield iterator.forEach(entry => {
|
||||
// Skip the directory currently in use
|
||||
if (this._directory && this._directory.path == entry.path)
|
||||
return;
|
||||
|
||||
// Skip the next directory
|
||||
if (this._nextDir && this._nextDir.path == entry.path)
|
||||
return;
|
||||
|
||||
entries.push(entry);
|
||||
});
|
||||
|
||||
for (let entry of entries) {
|
||||
if (entry.isDir) {
|
||||
yield OS.File.removeDir(entry.path, {
|
||||
ignoreAbsent: true,
|
||||
ignorePermissions: true,
|
||||
});
|
||||
}
|
||||
else {
|
||||
yield OS.File.remove(entry.path, {
|
||||
ignoreAbsent: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
logger.error("Failed to clean updated system add-ons directories.", e);
|
||||
}
|
||||
finally {
|
||||
iterator.close();
|
||||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
* Installs a new set of system add-ons into the location and updates the
|
||||
* add-on set in prefs. We wait to switch state until a restart.
|
||||
|
@ -7687,6 +7744,7 @@ Object.assign(SystemAddonInstallLocation.prototype, {
|
|||
}
|
||||
|
||||
this._saveAddonSet(state);
|
||||
this._nextDir = newDir;
|
||||
}),
|
||||
});
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ Services.prefs.setBoolPref(PREF_XPI_SIGNATURES_REQUIRED, true);
|
|||
|
||||
BootstrapMonitor.init();
|
||||
|
||||
const featureDir = FileUtils.getDir("ProfD", ["features"]);
|
||||
const featureDir = FileUtils.getDir("ProfD", ["features"], false);
|
||||
|
||||
function getCurrentFeatureDir() {
|
||||
let dir = featureDir.clone();
|
||||
|
@ -22,29 +22,42 @@ function getCurrentFeatureDir() {
|
|||
return dir;
|
||||
}
|
||||
|
||||
// Build the test sets
|
||||
let dir = FileUtils.getDir("ProfD", ["features", "prefilled"], true);
|
||||
do_get_file("data/system_addons/system2_2.xpi").copyTo(dir, "system2@tests.mozilla.org.xpi");
|
||||
do_get_file("data/system_addons/system3_2.xpi").copyTo(dir, "system3@tests.mozilla.org.xpi");
|
||||
function clearFeatureDir() {
|
||||
// Delete any existing directories
|
||||
if (featureDir.exists())
|
||||
featureDir.remove(true);
|
||||
|
||||
// Mark these in the past so the startup file scan notices when files have changed properly
|
||||
FileUtils.getFile("ProfD", ["features", "prefilled", "system2@tests.mozilla.org.xpi"]).lastModifiedTime -= 10000;
|
||||
FileUtils.getFile("ProfD", ["features", "prefilled", "system3@tests.mozilla.org.xpi"]).lastModifiedTime -= 10000;
|
||||
Services.prefs.clearUserPref(PREF_SYSTEM_ADDON_SET);
|
||||
}
|
||||
|
||||
const prefilledSet = {
|
||||
schema: 1,
|
||||
directory: dir.leafName,
|
||||
addons: {
|
||||
"system2@tests.mozilla.org": {
|
||||
version: "2.0"
|
||||
},
|
||||
"system3@tests.mozilla.org": {
|
||||
version: "2.0"
|
||||
},
|
||||
}
|
||||
};
|
||||
function buildPrefilledFeatureDir() {
|
||||
clearFeatureDir();
|
||||
|
||||
dir = FileUtils.getDir("ProfD", ["sysfeatures", "hidden"], true);
|
||||
// Build the test set
|
||||
let dir = FileUtils.getDir("ProfD", ["features", "prefilled"], true);
|
||||
|
||||
do_get_file("data/system_addons/system2_2.xpi").copyTo(dir, "system2@tests.mozilla.org.xpi");
|
||||
do_get_file("data/system_addons/system3_2.xpi").copyTo(dir, "system3@tests.mozilla.org.xpi");
|
||||
|
||||
// Mark these in the past so the startup file scan notices when files have changed properly
|
||||
FileUtils.getFile("ProfD", ["features", "prefilled", "system2@tests.mozilla.org.xpi"]).lastModifiedTime -= 10000;
|
||||
FileUtils.getFile("ProfD", ["features", "prefilled", "system3@tests.mozilla.org.xpi"]).lastModifiedTime -= 10000;
|
||||
|
||||
Services.prefs.setCharPref(PREF_SYSTEM_ADDON_SET, JSON.stringify({
|
||||
schema: 1,
|
||||
directory: dir.leafName,
|
||||
addons: {
|
||||
"system2@tests.mozilla.org": {
|
||||
version: "2.0"
|
||||
},
|
||||
"system3@tests.mozilla.org": {
|
||||
version: "2.0"
|
||||
},
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
let dir = FileUtils.getDir("ProfD", ["sysfeatures", "hidden"], true);
|
||||
do_get_file("data/system_addons/system1_1.xpi").copyTo(dir, "system1@tests.mozilla.org.xpi");
|
||||
do_get_file("data/system_addons/system2_1.xpi").copyTo(dir, "system2@tests.mozilla.org.xpi");
|
||||
|
||||
|
@ -202,7 +215,7 @@ const TEST_CONDITIONS = {
|
|||
// Runs tests with no updated or default system add-ons initially installed
|
||||
blank: {
|
||||
setup: function*() {
|
||||
Services.prefs.clearUserPref(PREF_SYSTEM_ADDON_SET);
|
||||
clearFeatureDir();
|
||||
distroDir.leafName = "empty";
|
||||
},
|
||||
initialState: [false, null, null, null, null, null],
|
||||
|
@ -211,7 +224,7 @@ const TEST_CONDITIONS = {
|
|||
// Runs tests with default system add-ons installed
|
||||
withAppSet: {
|
||||
setup: function*() {
|
||||
Services.prefs.clearUserPref(PREF_SYSTEM_ADDON_SET);
|
||||
clearFeatureDir();
|
||||
distroDir.leafName = "prefilled";
|
||||
},
|
||||
initialState: [false, null, "2.0", "2.0", null, null],
|
||||
|
@ -220,7 +233,7 @@ const TEST_CONDITIONS = {
|
|||
// Runs tests with updated system add-ons installed
|
||||
withProfileSet: {
|
||||
setup: function*() {
|
||||
Services.prefs.setCharPref(PREF_SYSTEM_ADDON_SET, JSON.stringify(prefilledSet));
|
||||
buildPrefilledFeatureDir();
|
||||
distroDir.leafName = "empty";
|
||||
},
|
||||
initialState: [true, null, "2.0", "2.0", null, null],
|
||||
|
@ -229,7 +242,7 @@ const TEST_CONDITIONS = {
|
|||
// Runs tests with both default and updated system add-ons installed
|
||||
withBothSets: {
|
||||
setup: function*() {
|
||||
Services.prefs.setCharPref(PREF_SYSTEM_ADDON_SET, JSON.stringify(prefilledSet));
|
||||
buildPrefilledFeatureDir();
|
||||
distroDir.leafName = "hidden";
|
||||
},
|
||||
initialState: [true, null, "2.0", "2.0", null, null],
|
||||
|
@ -347,6 +360,22 @@ add_task(function* setup() {
|
|||
yield promiseShutdownManager();
|
||||
})
|
||||
|
||||
function* get_directories() {
|
||||
let subdirs = [];
|
||||
|
||||
if (yield OS.File.exists(featureDir.path)) {
|
||||
let iterator = new OS.File.DirectoryIterator(featureDir.path);
|
||||
yield iterator.forEach(entry => {
|
||||
if (entry.isDir) {
|
||||
subdirs.push(entry);
|
||||
}
|
||||
});
|
||||
iterator.close();
|
||||
}
|
||||
|
||||
return subdirs;
|
||||
}
|
||||
|
||||
function* setup_conditions(setup) {
|
||||
do_print("Clearing existing database.");
|
||||
Services.prefs.clearUserPref(PREF_SYSTEM_ADDON_SET);
|
||||
|
@ -364,9 +393,28 @@ function* setup_conditions(setup) {
|
|||
yield check_installed(...setup.initialState);
|
||||
}
|
||||
|
||||
function* verify_state(finalState) {
|
||||
function* verify_state(initialState, finalState = undefined) {
|
||||
let expectedDirs = 0;
|
||||
|
||||
// If the initial state was using the profile set then that directory will
|
||||
// still exist.
|
||||
if (initialState[0])
|
||||
expectedDirs++;
|
||||
|
||||
if (finalState == undefined) {
|
||||
finalState = initialState;
|
||||
}
|
||||
else {
|
||||
// If the new state is using the profile then that directory will exist.
|
||||
if (finalState[0])
|
||||
expectedDirs++;
|
||||
}
|
||||
|
||||
do_print("Checking final state.");
|
||||
|
||||
let dirs = yield get_directories();
|
||||
do_check_eq(dirs.length, expectedDirs);
|
||||
|
||||
// Bug 1204156: Currently switching to the new state requires a restart
|
||||
// yield check_installed(...finalState);
|
||||
|
||||
|
@ -396,7 +444,7 @@ function* exec_test(setup, test) {
|
|||
}
|
||||
}
|
||||
|
||||
yield verify_state(test.finalState ? test.finalState : setup.initialState);
|
||||
yield verify_state(setup.initialState, test.finalState);
|
||||
|
||||
yield promiseShutdownManager();
|
||||
}
|
||||
|
@ -423,7 +471,8 @@ add_task(function* test_addon_update() {
|
|||
{ id: "system3@tests.mozilla.org", version: "2.0", path: "system3_2.xpi" }
|
||||
]));
|
||||
|
||||
yield verify_state([true, null, "2.0", "2.0", null, null]);
|
||||
yield verify_state(TEST_CONDITIONS.blank.initialState,
|
||||
[true, null, "2.0", "2.0", null, null]);
|
||||
|
||||
yield promiseShutdownManager();
|
||||
});
|
||||
|
@ -490,7 +539,8 @@ add_task(function* test_match_default_revert() {
|
|||
|
||||
// This should revert to the default set instead of installing new versions
|
||||
// into an updated set.
|
||||
yield verify_state([false, "1.0", "1.0", null, null, null]);
|
||||
yield verify_state(TEST_CONDITIONS.withBothSets.initialState,
|
||||
[false, "1.0", "1.0", null, null, null]);
|
||||
|
||||
yield promiseShutdownManager();
|
||||
});
|
||||
|
@ -523,7 +573,49 @@ add_task(function* test_no_download() {
|
|||
{ id: "system4@tests.mozilla.org", version: "1.0", path: "system4_1.xpi" }
|
||||
]));
|
||||
|
||||
yield verify_state([true, null, "2.0", null, "1.0", null]);
|
||||
yield verify_state(TEST_CONDITIONS.withBothSets.initialState,
|
||||
[true, null, "2.0", null, "1.0", null]);
|
||||
|
||||
yield promiseShutdownManager();
|
||||
});
|
||||
|
||||
// Tests that a second update before a restart works
|
||||
add_task(function* test_double_update() {
|
||||
yield setup_conditions(TEST_CONDITIONS.withAppSet);
|
||||
|
||||
yield install_system_addons(yield build_xml([
|
||||
{ id: "system2@tests.mozilla.org", version: "2.0", path: "system2_2.xpi" },
|
||||
{ id: "system3@tests.mozilla.org", version: "1.0", path: "system3_1.xpi" }
|
||||
]));
|
||||
|
||||
yield install_system_addons(yield build_xml([
|
||||
{ id: "system3@tests.mozilla.org", version: "2.0", path: "system3_2.xpi" },
|
||||
{ id: "system4@tests.mozilla.org", version: "1.0", path: "system4_1.xpi" }
|
||||
]));
|
||||
|
||||
yield verify_state(TEST_CONDITIONS.withAppSet.initialState,
|
||||
[true, null, null, "2.0", "1.0", null]);
|
||||
|
||||
yield promiseShutdownManager();
|
||||
});
|
||||
|
||||
// A second update after a restart will delete the original unused set
|
||||
add_task(function* test_update_purges() {
|
||||
yield setup_conditions(TEST_CONDITIONS.withBothSets);
|
||||
|
||||
yield install_system_addons(yield build_xml([
|
||||
{ id: "system2@tests.mozilla.org", version: "2.0", path: "system2_2.xpi" },
|
||||
{ id: "system3@tests.mozilla.org", version: "1.0", path: "system3_1.xpi" }
|
||||
]));
|
||||
|
||||
yield verify_state(TEST_CONDITIONS.withBothSets.initialState,
|
||||
[true, null, "2.0", "1.0", null, null]);
|
||||
|
||||
yield install_system_addons(yield build_xml(null));
|
||||
|
||||
let dirs = yield get_directories();
|
||||
do_check_eq(dirs.length, 1);
|
||||
|
||||
yield promiseShutdownManager();
|
||||
});
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче