Bug 1609920 - part 3: Terminate extension background workers on shutdown and unregister on uninstall. r=dom-workers-and-storage-reviewers,asuth,mixedpuppy

Depends on D60245

Differential Revision: https://phabricator.services.mozilla.com/D60301
This commit is contained in:
Luca Greco 2020-06-10 20:48:23 +00:00
parent ac67fbe999
commit 0578891772
5 changed files with 62 additions and 8 deletions

View File

@ -109,6 +109,22 @@ interface nsIServiceWorkerRegistrationInfo : nsISupports
void addListener(in nsIServiceWorkerRegistrationInfoListener listener);
void removeListener(in nsIServiceWorkerRegistrationInfoListener listener);
// Terminate all the service worker relate to this registration.
// This is used by the WebExtensions framework to shutdown the extension's
// background service workers as part of shutdown, which happens when:
// - the extension has been disabled.
// - the extension is shutting down to be updated.
// - the extension is shutting down as part of the uninstall flow.
//
// All the service workers instances related to this registration are expected
// to be terminate immediately.
//
// TODO - Bug 1638099: This method should also allow the WebExtension framework
// to mark the registration as disabled (e.g. through an additional parameter),
// to avoid it to be started again until the WebExtensions framework does explicitly
// mark it back to enabled.
void forceShutdown();
};
[scriptable, uuid(9e523e7c-ad6f-4df0-8077-c74aebbc679d)]

View File

@ -268,6 +268,13 @@ ServiceWorkerRegistrationInfo::RemoveListener(
return NS_OK;
}
NS_IMETHODIMP
ServiceWorkerRegistrationInfo::ForceShutdown() {
ClearInstalling();
ShutdownWorkers();
return NS_OK;
}
already_AddRefed<ServiceWorkerInfo>
ServiceWorkerRegistrationInfo::GetServiceWorkerInfoById(uint64_t aId) {
MOZ_ASSERT(NS_IsMainThread());

View File

@ -519,6 +519,12 @@ void ServiceWorkerUpdateJob::ContinueAfterInstallEvent(
return;
}
// Abort the update Job if the installWorker is null (e.g. when an extension
// is shutting down and all its workers have been terminated).
if (!mRegistration->GetInstalling()) {
return FailUpdateJob(NS_ERROR_DOM_ABORT_ERR);
}
MOZ_DIAGNOSTIC_ASSERT(mRegistration->GetInstalling());
mRegistration->TransitionInstallingToWaiting();

View File

@ -67,6 +67,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
OS: "resource://gre/modules/osfile.jsm",
PluralForm: "resource://gre/modules/PluralForm.jsm",
Schemas: "resource://gre/modules/Schemas.jsm",
ServiceWorkerCleanUp: "resource://gre/modules/ServiceWorkerCleanUp.jsm",
XPIProvider: "resource://gre/modules/addons/XPIProvider.jsm",
});
@ -331,6 +332,32 @@ var ExtensionAddonObserver = {
return;
}
let baseURI = Services.io.newURI(`moz-extension://${uuid}/`);
let principal = Services.scriptSecurityManager.createContentPrincipal(
baseURI,
{}
);
// Clear all the registered service workers for the extension
// principal.
// Any stored data would be cleared below (if the pref
// "extensions.webextensions.keepStorageOnUninstall has not been
// explicitly set to true, which is usually only done in
// tests and by some extensions developers for testing purpose).
if (WebExtensionPolicy.backgroundServiceWorkerEnabled) {
// TODO: ServiceWorkerCleanUp may go away once Bug 1183245
// is fixed, and so this may actually go away, replaced by
// marking the registration as disabled or to be removed on
// shutdown (where we do know if the extension is shutting
// down because is being uninstalled) and then cleared from
// the persisted serviceworker registration on the next
// startup.
AsyncShutdown.profileChangeTeardown.addBlocker(
`Clear ServiceWorkers for ${addon.id}`,
ServiceWorkerCleanUp.removeFromPrincipal(principal)
);
}
if (!Services.prefs.getBoolPref(LEAVE_STORAGE_PREF, false)) {
// Clear browser.storage.local backends.
AsyncShutdown.profileChangeTeardown.addBlocker(
@ -340,11 +367,6 @@ var ExtensionAddonObserver = {
// Clear any IndexedDB storage created by the extension
// If LSNG is enabled, this also clears localStorage.
let baseURI = Services.io.newURI(`moz-extension://${uuid}/`);
let principal = Services.scriptSecurityManager.createContentPrincipal(
baseURI,
{}
);
Services.qms.clearStoragesForPrincipal(principal);
// Clear any storage.local data stored in the IDBBackend.

View File

@ -111,8 +111,10 @@ class BackgroundPage extends HiddenExtensionPage {
// Responsible for the background.service_worker section of the manifest.
class BackgroundWorker {
constructor(extension, options) {
this.registrationInfo = null;
this.extension = extension;
this.workerScript = options.service_worker;
if (!this.workerScript) {
throw new Error("Missing mandatory background.service_worker property");
}
@ -128,9 +130,10 @@ class BackgroundWorker {
}
shutdown() {
// TODO: ask to the ServiceWorkerManager to terminate any
// worker related to the extension principal, because the
// extension is shutting down.
if (this.registrationInfo) {
this.registrationInfo.forceShutdown();
this.registrationInfo = null;
}
}
}