Bug 1012466 - Introduce AddonManager shutdown barrier. r=irving

This commit is contained in:
Georg Fritzsche 2014-07-08 18:56:04 +02:00
parent 4eead57c15
commit 4fdc6edd44
3 changed files with 38 additions and 10 deletions

View File

@ -463,6 +463,7 @@ var gCheckUpdateSecurity = gCheckUpdateSecurityDefault;
var gUpdateEnabled = true;
var gAutoUpdateDefault = true;
var gHotfixID = null;
var gShutdownBarrier = null;
/**
* This is the real manager, kept here rather than in AddonManager to keep its
@ -741,8 +742,9 @@ var AddonManagerInternal = {
}
// Register our shutdown handler with the AsyncShutdown manager
gShutdownBarrier = new AsyncShutdown.Barrier("AddonManager: Waiting for clients to shut down.");
AsyncShutdown.profileBeforeChange.addBlocker("AddonManager: shutting down providers",
this.shutdown.bind(this));
this.shutdownManager.bind(this));
// Once we start calling providers we must allow all normal methods to work.
gStarted = true;
@ -930,7 +932,7 @@ var AddonManagerInternal = {
* @return Promise{null} that resolves when all providers and dependent modules
* have finished shutting down
*/
shutdown: function AMI_shutdown() {
shutdownManager: function() {
logger.debug("shutdown");
// Clean up listeners
Services.prefs.removeObserver(PREF_EM_CHECK_COMPATIBILITY, this);
@ -944,7 +946,9 @@ var AddonManagerInternal = {
// AddonRepository after providers (if any).
let shuttingDown = null;
if (gStarted) {
shuttingDown = this.callProvidersAsync("shutdown")
shuttingDown = gShutdownBarrier.wait()
.then(null, err => logger.error("Failure during wait for shutdown barrier", err))
.then(() => this.callProvidersAsync("shutdown"))
.then(null,
err => logger.error("Failure during async provider shutdown", err))
.then(() => AddonRepository.shutdown());
@ -953,8 +957,8 @@ var AddonManagerInternal = {
shuttingDown = AddonRepository.shutdown();
}
shuttingDown.then(val => logger.debug("Async provider shutdown done"),
err => logger.error("Failure during AddonRepository shutdown", err))
shuttingDown.then(val => logger.debug("Async provider shutdown done"),
err => logger.error("Failure during AddonRepository shutdown", err))
.then(() => {
this.managerListeners.splice(0, this.managerListeners.length);
this.installListeners.splice(0, this.installListeners.length);
@ -964,7 +968,9 @@ var AddonManagerInternal = {
delete this.startupChanges[type];
gStarted = false;
gStartupComplete = false;
gShutdownBarrier = null;
});
return shuttingDown;
},
@ -2799,7 +2805,11 @@ this.AddonManager = {
escapeAddonURI: function AM_escapeAddonURI(aAddon, aUri, aAppVersion) {
return AddonManagerInternal.escapeAddonURI(aAddon, aUri, aAppVersion);
}
},
get shutdown() {
return gShutdownBarrier.client;
},
};
// load the timestamps module into AddonManagerInternal

View File

@ -42,8 +42,26 @@ let MockAsyncShutdown = {
do_print("Mock profileBeforeChange blocker for '" + aName + "'");
MockAsyncShutdown.hook = aBlocker;
}
}
},
Barrier: function (name) {
this.name = name;
this.client.addBlocker = (name, blocker) => {
do_print("Mock Barrier blocker for '" + name + "' for barrier '" + this.name + "'");
this.blockers.push({name: name, blocker: blocker});
};
},
};
MockAsyncShutdown.Barrier.prototype = Object.freeze({
blockers: [],
client: {},
wait: Task.async(function* () {
for (let b of this.blockers) {
yield b.blocker();
}
}),
});
AMscope.AsyncShutdown = MockAsyncShutdown;
var gInternalManager = null;

View File

@ -9,7 +9,7 @@ const IGNORE = ["escapeAddonURI", "shouldAutoUpdate", "getStartupChanges",
"addAddonListener", "removeAddonListener",
"addInstallListener", "removeInstallListener",
"addManagerListener", "removeManagerListener",
"mapURIToAddonID"];
"mapURIToAddonID", "shutdown"];
const IGNORE_PRIVATE = ["AddonAuthor", "AddonCompatibilityOverride",
"AddonScreenshot", "AddonType", "startup", "shutdown",
@ -22,10 +22,10 @@ const IGNORE_PRIVATE = ["AddonAuthor", "AddonCompatibilityOverride",
function test_functions() {
for (let prop in AddonManager) {
if (typeof AddonManager[prop] != "function")
continue;
if (IGNORE.indexOf(prop) != -1)
continue;
if (typeof AddonManager[prop] != "function")
continue;
try {
do_print("AddonManager." + prop);