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

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

Issue 991743002: Service Worker: Coalesce the start worker timer into the timeout timer. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: review comments Created 5 years, 9 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_version.cc
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index 4857ff945871867b0ed6c703669c1ad678b28c18..51eb072ff933c4a2b34dc3f24aaed5d8c7fdee91 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -54,12 +54,9 @@ const int kUpdateDelaySeconds = 1;
// Timeout for waiting for a response to a ping.
const int kPingTimeoutSeconds = 30;
-// Timeout for the worker to start.
-const int kStartWorkerTimeoutMinutes = 5;
-
// If the SW was destructed while starting up, how many seconds it
// had to start up for this to be considered a timeout occurrence.
-const int kDestructedStartingWorkerTimeoutThresholdSeconds = 5; // 5 secs.
+const int kDestructedStartingWorkerTimeoutThresholdSeconds = 5;
const char kClaimClientsStateErrorMesage[] =
"Only the active worker can claim clients.";
@@ -296,6 +293,8 @@ void OnGetClientsFromUI(
} // namespace
+const int ServiceWorkerVersion::kStartWorkerTimeoutMinutes = 5;
+
ServiceWorkerVersion::ServiceWorkerVersion(
ServiceWorkerRegistration* registration,
const GURL& script_url,
@@ -307,7 +306,7 @@ ServiceWorkerVersion::ServiceWorkerVersion(
status_(NEW),
context_(context),
script_cache_map_(this, context),
- ping_timed_out_(false),
+ ping_state_(NOT_PINGING),
is_doomed_(false),
skip_waiting_(false),
weak_factory_(this) {
@@ -324,10 +323,11 @@ ServiceWorkerVersion::ServiceWorkerVersion(
ServiceWorkerVersion::~ServiceWorkerVersion() {
// The user may have closed the tab waiting for SW to start up.
- if (start_worker_timeout_timer_.IsRunning() &&
- GetTickDuration(start_timing_) >
- base::TimeDelta::FromSeconds(
- kDestructedStartingWorkerTimeoutThresholdSeconds)) {
+ if (GetTickDuration(start_time_) >
+ base::TimeDelta::FromSeconds(
+ kDestructedStartingWorkerTimeoutThresholdSeconds)) {
+ DCHECK(timeout_timer_.IsRunning());
+ DCHECK(!embedded_worker_->devtools_attached());
RecordStartWorkerResult(SERVICE_WORKER_ERROR_TIMEOUT);
}
@@ -392,8 +392,8 @@ void ServiceWorkerVersion::StartWorker(
case STOPPING:
case STOPPED:
case STARTING:
- if (!start_worker_timeout_timer_.IsRunning())
- ScheduleStartWorkerTimeout();
+ if (!timeout_timer_.IsRunning())
+ StartTimeoutTimer();
start_callbacks_.push_back(callback);
if (running_status() == STOPPED) {
DCHECK(!cache_listener_.get());
@@ -789,15 +789,11 @@ void ServiceWorkerVersion::SetDevToolsAttached(bool attached) {
embedded_worker()->set_devtools_attached(attached);
if (attached) {
// Set to null time so we don't record the startup time metric.
- ClearTick(&start_timing_);
+ ClearTick(&start_time_);
return;
}
- // If devtools is detached try scheduling the timers for stopping the worker
- // now.
if (!timeout_timer_.IsRunning())
StartTimeoutTimer();
- if (!start_worker_timeout_timer_.IsRunning() && !start_callbacks_.empty())
- ScheduleStartWorkerTimeout();
}
void ServiceWorkerVersion::SetMainScriptHttpResponseInfo(
@@ -812,7 +808,8 @@ ServiceWorkerVersion::GetMainScriptHttpResponseInfo() {
void ServiceWorkerVersion::OnScriptLoaded() {
DCHECK_EQ(STARTING, running_status());
- StartTimeoutTimer();
+ // Activate ping/pong now that JavaScript execution will start.
+ ping_state_ = PINGING;
}
void ServiceWorkerVersion::OnStarted() {
@@ -835,7 +832,7 @@ void ServiceWorkerVersion::OnStopped(
(old_status != EmbeddedWorkerInstance::STARTING);
StopTimeoutTimer();
- if (ping_timed_out_)
+ if (ping_state_ == PING_TIMED_OUT)
should_restart = false;
// Fire all stop callbacks.
@@ -881,7 +878,10 @@ void ServiceWorkerVersion::OnStopped(
// Restart worker if we have any start callbacks and the worker isn't doomed.
if (should_restart) {
- start_worker_timeout_timer_.Reset();
+ if (embedded_worker_->devtools_attached())
+ ClearTick(&start_time_);
+ else
+ RestartTick(&start_time_);
cache_listener_.reset(new ServiceWorkerCacheListener(this, context_));
embedded_worker_->Start(
version_id_, scope_, script_url_, false /* pause_after_download */,
@@ -1426,9 +1426,19 @@ void ServiceWorkerVersion::DidGetClients(
void ServiceWorkerVersion::StartTimeoutTimer() {
DCHECK(!timeout_timer_.IsRunning());
+
+ if (embedded_worker_->devtools_attached())
+ ClearTick(&start_time_);
+ else
+ RestartTick(&start_time_);
+ start_callbacks_.push_back(
+ base::Bind(&ServiceWorkerVersion::RecordStartWorkerResult,
+ weak_factory_.GetWeakPtr()));
+
ClearTick(&idle_time_);
ClearTick(&ping_time_);
- ping_timed_out_ = false;
+ ping_state_ = NOT_PINGING;
+
timeout_timer_.Start(FROM_HERE,
base::TimeDelta::FromSeconds(kTimeoutTimerDelaySeconds),
this, &ServiceWorkerVersion::OnTimeoutTimer);
@@ -1439,33 +1449,53 @@ void ServiceWorkerVersion::StopTimeoutTimer() {
}
void ServiceWorkerVersion::OnTimeoutTimer() {
+ DCHECK(running_status() == STARTING || running_status() == RUNNING ||
+ running_status() == STOPPING)
+ << running_status();
+
+ // Starting a worker hasn't finished within a certain period.
+ if (GetTickDuration(start_time_) >
+ base::TimeDelta::FromMinutes(kStartWorkerTimeoutMinutes)) {
+ DCHECK_NE(RUNNING, running_status());
+ scoped_refptr<ServiceWorkerVersion> protect(this);
+ RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_ERROR_TIMEOUT);
+ if (running_status() == STARTING)
+ embedded_worker_->Stop();
+ return;
+ }
+
+ // This check occurs after the start_time_ timeout check, since in that case
+ // the start callbacks should fail with ERROR_TIMEOUT. In the other timeout
+ // checks, there's nothing more to do as the worker is already stopping.
if (running_status() == STOPPING)
return;
- DCHECK(running_status() == STARTING || running_status() == RUNNING);
+
+ // The worker has been idle for longer than a certain period.
if (GetTickDuration(idle_time_) >
base::TimeDelta::FromSeconds(kIdleWorkerTimeoutSeconds)) {
StopWorkerIfIdle();
- StopTimeoutTimer();
return;
}
+
+ // The worker hasn't responded to ping within a certain period.
if (GetTickDuration(ping_time_) >
base::TimeDelta::FromSeconds(kPingTimeoutSeconds)) {
OnPingTimeout();
- StopTimeoutTimer();
return;
}
- if (ping_time_.is_null())
+ if (ping_state_ == PINGING && ping_time_.is_null())
PingWorker();
}
void ServiceWorkerVersion::PingWorker() {
DCHECK(running_status() == STARTING || running_status() == RUNNING);
+ DCHECK_EQ(PINGING, ping_state_);
ServiceWorkerStatusCode status =
embedded_worker_->SendMessage(ServiceWorkerMsg_Ping());
if (status != SERVICE_WORKER_OK) {
// TODO(falken): Maybe try resending Ping a few times first?
- ping_timed_out_ = true;
+ ping_state_ = PING_TIMED_OUT;
StopWorkerIfIdle();
return;
}
@@ -1474,7 +1504,7 @@ void ServiceWorkerVersion::PingWorker() {
void ServiceWorkerVersion::OnPingTimeout() {
DCHECK(running_status() == STARTING || running_status() == RUNNING);
- ping_timed_out_ = true;
+ ping_state_ = PING_TIMED_OUT;
// TODO(falken): Show a message to the developer that the SW was stopped due
// to timeout (crbug.com/457968). Also, change the error code to
// SERVICE_WORKER_ERROR_TIMEOUT.
@@ -1482,7 +1512,7 @@ void ServiceWorkerVersion::OnPingTimeout() {
}
void ServiceWorkerVersion::StopWorkerIfIdle() {
- if (HasInflightRequests() && !ping_timed_out_)
+ if (HasInflightRequests() && ping_state_ != PING_TIMED_OUT)
return;
if (running_status() == STOPPED || running_status() == STOPPING ||
!stop_callbacks_.empty()) {
@@ -1508,46 +1538,16 @@ bool ServiceWorkerVersion::HasInflightRequests() const {
!streaming_url_request_jobs_.empty();
}
-void ServiceWorkerVersion::ScheduleStartWorkerTimeout() {
- DCHECK(!start_worker_timeout_timer_.IsRunning());
- start_timing_ = embedded_worker_->devtools_attached()
- ? base::TimeTicks()
- : base::TimeTicks::Now();
- start_callbacks_.push_back(
- base::Bind(&ServiceWorkerVersion::RecordStartWorkerResult,
- weak_factory_.GetWeakPtr()));
- start_worker_timeout_timer_.Start(
- FROM_HERE, base::TimeDelta::FromMinutes(kStartWorkerTimeoutMinutes),
- base::Bind(&ServiceWorkerVersion::OnStartWorkerTimeout,
- weak_factory_.GetWeakPtr()));
-}
-
-void ServiceWorkerVersion::OnStartWorkerTimeout() {
- DCHECK(running_status() == STARTING || running_status() == STOPPING)
- << running_status();
-
- if (embedded_worker_->devtools_attached()) {
- start_worker_timeout_timer_.Stop();
- return;
- }
-
- scoped_refptr<ServiceWorkerVersion> protect(this);
- RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_ERROR_TIMEOUT);
- if (running_status() == STARTING)
- embedded_worker_->Stop();
-}
-
void ServiceWorkerVersion::RecordStartWorkerResult(
ServiceWorkerStatusCode status) {
- start_worker_timeout_timer_.Stop();
-
UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Status", status,
SERVICE_WORKER_ERROR_MAX_VALUE);
- if (status == SERVICE_WORKER_OK && !start_timing_.is_null()) {
+ if (status == SERVICE_WORKER_OK && !start_time_.is_null()) {
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.StartWorker.Time",
- GetTickDuration(start_timing_));
+ GetTickDuration(start_time_));
}
+ ClearTick(&start_time_);
if (status != SERVICE_WORKER_ERROR_TIMEOUT)
return;
EmbeddedWorkerInstance::StartingPhase phase =

Powered by Google App Engine
This is Rietveld 408576698