Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(144)

Unified Diff: content/browser/service_worker/service_worker_registration.cc

Issue 2027583002: service worker: Avoid starting up for activation during shutdown (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: comments Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/service_worker/service_worker_registration.cc
diff --git a/content/browser/service_worker/service_worker_registration.cc b/content/browser/service_worker/service_worker_registration.cc
index b803edf1865954db918665b644c0d8f173607f8d..8e0a50b53308f72ffe8a7391ea82d1212b601c56 100644
--- a/content/browser/service_worker/service_worker_registration.cc
+++ b/content/browser/service_worker/service_worker_registration.cc
@@ -7,6 +7,7 @@
#include <vector>
#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_info.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/browser/service_worker/service_worker_register_job.h"
@@ -24,6 +25,13 @@ ServiceWorkerVersionInfo GetVersionInfo(ServiceWorkerVersion* version) {
return version->GetInfo();
}
+bool GetShutdownStatusOnUIThread(
+ scoped_refptr<ServiceWorkerContextWrapper> wrapper,
+ ServiceWorkerStatusCode status) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ return wrapper->process_manager()->IsShutdown();
+}
+
} // namespace
ServiceWorkerRegistration::ServiceWorkerRegistration(
@@ -176,8 +184,9 @@ void ServiceWorkerRegistration::ActivateWaitingVersionWhenReady() {
should_activate_when_ready_ = true;
if (!active_version() || !active_version()->HasControllee() ||
- waiting_version()->skip_waiting())
- ActivateWaitingVersion();
+ waiting_version()->skip_waiting()) {
+ ActivateWaitingVersion(false);
+ }
}
void ServiceWorkerRegistration::ClaimClients() {
@@ -243,12 +252,12 @@ void ServiceWorkerRegistration::OnNoControllees(ServiceWorkerVersion* version) {
if (is_uninstalling_)
Clear();
else if (should_activate_when_ready_)
- ActivateWaitingVersion();
+ ActivateWaitingVersion(true);
is_uninstalling_ = false;
should_activate_when_ready_ = false;
}
-void ServiceWorkerRegistration::ActivateWaitingVersion() {
+void ServiceWorkerRegistration::ActivateWaitingVersion(bool delay) {
DCHECK(context_);
DCHECK(waiting_version());
DCHECK(should_activate_when_ready_);
@@ -283,6 +292,24 @@ void ServiceWorkerRegistration::ActivateWaitingVersion() {
FOR_EACH_OBSERVER(Listener, listeners_, OnSkippedWaiting(this));
// "10. Queue a task to fire an event named activate..."
+ // The browser could be shutting down. To avoid spurious start worker
+ // failures, wait a bit before continuing.
+ if (delay) {
+ timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(1),
+ base::Bind(&ServiceWorkerRegistration::ContinueActivation,
+ this, activating_version));
+ } else {
+ ContinueActivation(std::move(activating_version));
+ }
+}
+
+void ServiceWorkerRegistration::ContinueActivation(
+ scoped_refptr<ServiceWorkerVersion> activating_version) {
+ if (!context_)
+ return;
+ if (active_version() != activating_version.get())
+ return;
+ DCHECK_EQ(ServiceWorkerVersion::ACTIVATING, activating_version->status());
activating_version->RunAfterStartWorker(
ServiceWorkerMetrics::EventType::ACTIVATE,
base::Bind(&ServiceWorkerRegistration::DispatchActivateEvent, this,
@@ -331,6 +358,11 @@ void ServiceWorkerRegistration::NotifyRegistrationFinished() {
callback.Run();
}
+void ServiceWorkerRegistration::SetTimerTaskRunnerForTest(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ timer_.SetTaskRunner(std::move(task_runner));
+}
+
void ServiceWorkerRegistration::RegisterRegistrationFinishedCallback(
const base::Closure& callback) {
// This should only be called if the registration is in progress.
@@ -340,7 +372,7 @@ void ServiceWorkerRegistration::RegisterRegistrationFinishedCallback(
}
void ServiceWorkerRegistration::DispatchActivateEvent(
- const scoped_refptr<ServiceWorkerVersion>& activating_version) {
+ scoped_refptr<ServiceWorkerVersion> activating_version) {
if (activating_version != active_version()) {
OnActivateEventFinished(activating_version, SERVICE_WORKER_ERROR_FAILED);
return;
@@ -359,15 +391,42 @@ void ServiceWorkerRegistration::DispatchActivateEvent(
}
void ServiceWorkerRegistration::OnActivateEventFinished(
- const scoped_refptr<ServiceWorkerVersion>& activating_version,
+ scoped_refptr<ServiceWorkerVersion> activating_version,
ServiceWorkerStatusCode status) {
+ ServiceWorkerMetrics::RecordActivateEventStatus(status);
+
+ if (!context_)
+ return;
+
+ // Activate is prone to failing due to shutdown, because it's triggered when
+ // tabs close. Try to detect that case for metrics and to ignore failures on
+ // shutdown.
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&GetShutdownStatusOnUIThread,
+ make_scoped_refptr(context_->wrapper()), status),
+ base::Bind(&ServiceWorkerRegistration::CompleteActivation, this,
+ activating_version, status));
+}
+
+void ServiceWorkerRegistration::CompleteActivation(
+ scoped_refptr<ServiceWorkerVersion> activating_version,
+ ServiceWorkerStatusCode status,
+ bool is_shutdown) {
+ ServiceWorkerMetrics::RecordActivateEventStatusWithShutdownStatus(
+ status, is_shutdown);
if (!context_ || activating_version != active_version() ||
- activating_version->status() != ServiceWorkerVersion::ACTIVATING)
+ activating_version->status() != ServiceWorkerVersion::ACTIVATING) {
return;
+ }
- // |status| is just for UMA. Once we've attempted to dispatch the activate
- // event to an installed worker, it's committed to becoming active.
- ServiceWorkerMetrics::RecordActivateEventStatus(status);
+ // Normally, the worker is committed to become activated once we get here, per
+ // spec. E.g., if the script rejected waitUntil or had an unhandled exception,
+ // it should still be activated. However, if the failure occurred during
+ // shutdown, ignore it to give the worker another chance the next time the
+ // browser starts up.
+ if (is_shutdown && status != SERVICE_WORKER_OK)
+ return;
// "Run the Update State algorithm passing registration's active worker and
// 'activated' as the arguments."

Powered by Google App Engine
This is Rietveld 408576698