Normally, when an extension is uninstalled, any running ServiceWorkers for that extension are stopped (see StopAllServiceWorkersForOrigin(), called from OnExtensionUnloaded), and then in a separate step, all registered ServiceWorkers are unregistered (see ServiceWorkerContext::DeleteForOrigin(), called from OnExtensionUninstalled). However, while debugging issue 782349 (specifically, in the ServiceWorkerSuspensionOnExtensionUnload test), I found out that there might be a race, where if the ServiceWorker starts up just as the extension is getting uninstalled, the ServiceWorker might end up running and potentially leak. The requests serviced by it still result in errors, so the test still passes, but I'm not sure that's intended behavior -- seems like that ServiceWorker should never be allowed to start in the first place.
To be more precise, ServiceWorkerSuspensionOnExtensionUnload calls extension_service()->UninstallExtension(), and on the next navigation to the uninstalled extension URL normally serviced by the extension's SW, I sometimes observed a call to ServiceWorkerProcessManager::AllocateWorkerProcess(), which means a new ServiceWorker is starting. This seemed like fairly unexpected behavior, so filing this just in case. Note that this was flaky; I only observed it sometimes on Windows dbg with --enable-pixel-output-in-tests.
I don't really know the ServiceWorker extension plumbing, but could the following be happening?
1. Extension uninstall calls extension unload, and as part of that, StopAllServiceWorkersForOrigin() posts a task to the IO thread to stop any running ServiceWorkers.
2. Next, ServiceWorkerContext::DeleteForOrigin posts another task to the IO thread to unregister all existing SWs.
3. The task from step 1 completes.
4. The test navigates to the uninstalled extension SW URL, causing a new ServiceWorker to spin up, as it's still registered.
5. The task to remove SW registrations completes, but the new SW has already started running.
Comment 1 by horo@chromium.org
, Nov 16 2017Status: Assigned (was: Untriaged)