| 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 55b6a0e5dc2822ab51e846b8525fa0765b1a0f2f..0c3fedb14f76a46b659781a10ad2892beeeda60b 100644
|
| --- a/content/browser/service_worker/service_worker_version.cc
|
| +++ b/content/browser/service_worker/service_worker_version.cc
|
| @@ -415,7 +415,7 @@ class ServiceWorkerVersion::Metrics {
|
| // if the worker is not stalling.
|
| class ServiceWorkerVersion::PingController {
|
| public:
|
| - PingController(ServiceWorkerVersion* version) : version_(version) {}
|
| + explicit PingController(ServiceWorkerVersion* version) : version_(version) {}
|
| ~PingController() {}
|
|
|
| void Activate() { ping_state_ = PINGING; }
|
| @@ -600,30 +600,37 @@ void ServiceWorkerVersion::StopWorker(const StatusCallback& callback) {
|
| }
|
|
|
| void ServiceWorkerVersion::ScheduleUpdate() {
|
| + if (!context_)
|
| + return;
|
| if (update_timer_.IsRunning()) {
|
| update_timer_.Reset();
|
| return;
|
| }
|
| - update_timer_.Start(
|
| - FROM_HERE, base::TimeDelta::FromSeconds(kUpdateDelaySeconds),
|
| - base::Bind(&ServiceWorkerVersion::StartUpdate,
|
| - weak_factory_.GetWeakPtr()));
|
| -}
|
| + if (is_update_scheduled_)
|
| + return;
|
| + is_update_scheduled_ = true;
|
|
|
| -void ServiceWorkerVersion::DeferScheduledUpdate() {
|
| - if (update_timer_.IsRunning())
|
| - update_timer_.Reset();
|
| + // Protect |this| until the timer fires, since we may be stopping
|
| + // and soon no one might hold a reference to us.
|
| + context_->ProtectVersion(make_scoped_refptr(this));
|
| + update_timer_.Start(FROM_HERE,
|
| + base::TimeDelta::FromSeconds(kUpdateDelaySeconds),
|
| + base::Bind(&ServiceWorkerVersion::StartUpdate,
|
| + weak_factory_.GetWeakPtr()));
|
| }
|
|
|
| void ServiceWorkerVersion::StartUpdate() {
|
| - update_timer_.Stop();
|
| if (!context_)
|
| return;
|
| - ServiceWorkerRegistration* registration =
|
| - context_->GetLiveRegistration(registration_id_);
|
| - if (!registration || !registration->GetNewestVersion())
|
| - return;
|
| - context_->UpdateServiceWorker(registration, false /* force_bypass_cache */);
|
| + context_->storage()->FindRegistrationForId(
|
| + registration_id_, scope_.GetOrigin(),
|
| + base::Bind(&ServiceWorkerVersion::FoundRegistrationForUpdate,
|
| + weak_factory_.GetWeakPtr()));
|
| +}
|
| +
|
| +void ServiceWorkerVersion::DeferScheduledUpdate() {
|
| + if (update_timer_.IsRunning())
|
| + update_timer_.Reset();
|
| }
|
|
|
| void ServiceWorkerVersion::DispatchMessageEvent(
|
| @@ -1725,6 +1732,8 @@ void ServiceWorkerVersion::DidEnsureLiveRegistrationForStartWorker(
|
| return;
|
| }
|
|
|
| + MarkIfStale();
|
| +
|
| switch (running_status()) {
|
| case RUNNING:
|
| RunSoon(base::Bind(callback, SERVICE_WORKER_OK));
|
| @@ -1837,6 +1846,13 @@ void ServiceWorkerVersion::StartTimeoutTimer() {
|
|
|
| void ServiceWorkerVersion::StopTimeoutTimer() {
|
| timeout_timer_.Stop();
|
| +
|
| + // Trigger update if worker is stale.
|
| + if (!stale_time_.is_null()) {
|
| + ClearTick(&stale_time_);
|
| + if (!update_timer_.IsRunning())
|
| + ScheduleUpdate();
|
| + }
|
| }
|
|
|
| void ServiceWorkerVersion::OnTimeoutTimer() {
|
| @@ -1844,6 +1860,17 @@ void ServiceWorkerVersion::OnTimeoutTimer() {
|
| running_status() == STOPPING)
|
| << running_status();
|
|
|
| + MarkIfStale();
|
| +
|
| + // Trigger update if worker is stale and we waited long enough for it to go
|
| + // idle.
|
| + if (GetTickDuration(stale_time_) >
|
| + base::TimeDelta::FromMinutes(kRequestTimeoutMinutes)) {
|
| + ClearTick(&stale_time_);
|
| + if (!update_timer_.IsRunning())
|
| + ScheduleUpdate();
|
| + }
|
| +
|
| // Starting a worker hasn't finished within a certain period.
|
| if (GetTickDuration(start_time_) >
|
| base::TimeDelta::FromMinutes(kStartWorkerTimeoutMinutes)) {
|
| @@ -2056,4 +2083,38 @@ ServiceWorkerStatusCode ServiceWorkerVersion::DeduceStartWorkerFailureReason(
|
| return default_code;
|
| }
|
|
|
| +void ServiceWorkerVersion::MarkIfStale() {
|
| + if (!context_)
|
| + return;
|
| + if (update_timer_.IsRunning() || !stale_time_.is_null())
|
| + return;
|
| + ServiceWorkerRegistration* registration =
|
| + context_->GetLiveRegistration(registration_id_);
|
| + if (!registration || registration->active_version() != this)
|
| + return;
|
| + base::TimeDelta time_since_last_check =
|
| + base::Time::Now() - registration->last_update_check();
|
| + if (time_since_last_check >
|
| + base::TimeDelta::FromHours(kServiceWorkerScriptMaxCacheAgeInHours))
|
| + RestartTick(&stale_time_);
|
| +}
|
| +
|
| +void ServiceWorkerVersion::FoundRegistrationForUpdate(
|
| + ServiceWorkerStatusCode status,
|
| + const scoped_refptr<ServiceWorkerRegistration>& registration) {
|
| + if (!context_)
|
| + return;
|
| +
|
| + const scoped_refptr<ServiceWorkerVersion> protect = this;
|
| + if (is_update_scheduled_) {
|
| + context_->UnprotectVersion(version_id_);
|
| + is_update_scheduled_ = false;
|
| + }
|
| +
|
| + if (status != SERVICE_WORKER_OK || registration->active_version() != this)
|
| + return;
|
| + context_->UpdateServiceWorker(registration.get(),
|
| + false /* force_bypass_cache */);
|
| +}
|
| +
|
| } // namespace content
|
|
|