| 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 ede55528807ba8d7cfd4b30c191196b5b354be17..138c11555d8201b11f538bbd2b18570c6665640d 100644
|
| --- a/content/browser/service_worker/service_worker_version.cc
|
| +++ b/content/browser/service_worker/service_worker_version.cc
|
| @@ -85,6 +85,12 @@ const int64 kStopDoomedWorkerDelay = 5; // 5 secs.
|
| // Default delay for scheduled update.
|
| const int kUpdateDelaySeconds = 1;
|
|
|
| +// Delay between sending pings to the worker.
|
| +const int kPingIntervalTime = 10; // 10 secs.
|
| +
|
| +// Timeout for waiting for a response to a ping.
|
| +const int kPingTimeoutTime = 30; // 30 secs.
|
| +
|
| const char kClaimClientsStateErrorMesage[] =
|
| "Only the active worker can claim clients.";
|
|
|
| @@ -297,6 +303,7 @@ ServiceWorkerVersion::ServiceWorkerVersion(
|
| status_(NEW),
|
| context_(context),
|
| script_cache_map_(this, context),
|
| + ping_timed_out_(false),
|
| is_doomed_(false),
|
| skip_waiting_(false),
|
| weak_factory_(this) {
|
| @@ -791,11 +798,14 @@ void ServiceWorkerVersion::Doom() {
|
|
|
| void ServiceWorkerVersion::SetDevToolsAttached(bool attached) {
|
| embedded_worker()->set_devtools_attached(attached);
|
| - if (!attached && !stop_worker_timer_.IsRunning()) {
|
| - // If devtools is detached from this version and stop-worker-timer is not
|
| - // running, try scheduling stop-worker-timer now.
|
| + if (attached)
|
| + return;
|
| + // If devtools is detached try scheduling the timers for stopping the worker
|
| + // now.
|
| + if (!stop_worker_timer_.IsRunning())
|
| ScheduleStopWorker();
|
| - }
|
| + if (!ping_worker_timer_.IsRunning())
|
| + StartPingWorker();
|
| }
|
|
|
| void ServiceWorkerVersion::SetMainScriptHttpResponseInfo(
|
| @@ -808,6 +818,11 @@ ServiceWorkerVersion::GetMainScriptHttpResponseInfo() {
|
| return main_script_http_info_.get();
|
| }
|
|
|
| +void ServiceWorkerVersion::OnScriptLoaded() {
|
| + DCHECK_EQ(STARTING, running_status());
|
| + StartPingWorker();
|
| +}
|
| +
|
| void ServiceWorkerVersion::OnStarted() {
|
| DCHECK_EQ(RUNNING, running_status());
|
| DCHECK(cache_listener_.get());
|
| @@ -827,6 +842,10 @@ void ServiceWorkerVersion::OnStopped(
|
| bool should_restart = !is_doomed() && !start_callbacks_.empty() &&
|
| (old_status != EmbeddedWorkerInstance::STARTING);
|
|
|
| + ping_worker_timer_.Stop();
|
| + if (ping_timed_out_)
|
| + should_restart = false;
|
| +
|
| // Fire all stop callbacks.
|
| RunCallbacks(this, &stop_callbacks_, SERVICE_WORKER_OK);
|
|
|
| @@ -940,6 +959,7 @@ bool ServiceWorkerVersion::OnMessageReceived(const IPC::Message& message) {
|
| OnSkipWaiting)
|
| IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ClaimClients,
|
| OnClaimClients)
|
| + IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_Pong, OnPongFromWorker)
|
| IPC_MESSAGE_UNHANDLED(handled = false)
|
| IPC_END_MESSAGE_MAP()
|
| return handled;
|
| @@ -1349,6 +1369,12 @@ void ServiceWorkerVersion::OnClaimClients(int request_id) {
|
| registration->ClaimClients(callback);
|
| }
|
|
|
| +void ServiceWorkerVersion::OnPongFromWorker() {
|
| + if (ping_timed_out_)
|
| + return;
|
| + SchedulePingWorker();
|
| +}
|
| +
|
| void ServiceWorkerVersion::DidClaimClients(
|
| int request_id, ServiceWorkerStatusCode status) {
|
| if (status == SERVICE_WORKER_ERROR_STATE) {
|
| @@ -1387,6 +1413,46 @@ void ServiceWorkerVersion::DidGetClientInfo(
|
| callback->AddClientInfo(client_id, info);
|
| }
|
|
|
| +void ServiceWorkerVersion::PingWorker() {
|
| + if (running_status() != STARTING && running_status() != RUNNING)
|
| + return;
|
| + 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;
|
| + StopWorkerIfIdle();
|
| + return;
|
| + }
|
| + ping_worker_timer_.Start(FROM_HERE,
|
| + base::TimeDelta::FromSeconds(kPingTimeoutTime),
|
| + base::Bind(&ServiceWorkerVersion::OnPingTimeout,
|
| + weak_factory_.GetWeakPtr()));
|
| +}
|
| +
|
| +void ServiceWorkerVersion::StartPingWorker() {
|
| + ping_timed_out_ = false;
|
| + SchedulePingWorker();
|
| +}
|
| +
|
| +void ServiceWorkerVersion::SchedulePingWorker() {
|
| + DCHECK(!ping_timed_out_);
|
| + ping_worker_timer_.Stop();
|
| + ping_worker_timer_.Start(FROM_HERE,
|
| + base::TimeDelta::FromSeconds(kPingIntervalTime),
|
| + base::Bind(&ServiceWorkerVersion::PingWorker,
|
| + weak_factory_.GetWeakPtr()));
|
| +}
|
| +
|
| +void ServiceWorkerVersion::OnPingTimeout() {
|
| + if (running_status() != STARTING && running_status() != RUNNING)
|
| + return;
|
| + ping_timed_out_ = true;
|
| + // TODO(falken): Show a message to the developer that the SW was stopped due
|
| + // to timeout (crbug.com/457968).
|
| + StopWorkerIfIdle();
|
| +}
|
| +
|
| void ServiceWorkerVersion::ScheduleStopWorker() {
|
| if (running_status() != RUNNING)
|
| return;
|
| @@ -1399,10 +1465,7 @@ void ServiceWorkerVersion::ScheduleStopWorker() {
|
| }
|
|
|
| void ServiceWorkerVersion::StopWorkerIfIdle() {
|
| - // Reschedule the stop the worker while there're inflight requests.
|
| - // (Note: we'll probably need to revisit this so that we can kill 'bad' SW.
|
| - // See https://github.com/slightlyoff/ServiceWorker/issues/527)
|
| - if (HasInflightRequests()) {
|
| + if (HasInflightRequests() && !ping_timed_out_) {
|
| ScheduleStopWorker();
|
| return;
|
| }
|
| @@ -1410,6 +1473,10 @@ void ServiceWorkerVersion::StopWorkerIfIdle() {
|
| !stop_callbacks_.empty()) {
|
| return;
|
| }
|
| +
|
| + // TODO(falken): We may need to handle StopIfIdle failure and
|
| + // forcibly fail pending callbacks so no one is stuck waiting
|
| + // for the worker.
|
| embedded_worker_->StopIfIdle();
|
| }
|
|
|
|
|